Giter Club home page Giter Club logo

zrender's Introduction

ZRender

A lightweight graphic library which provides 2d draw for Apache ECharts.

Commits Since 4.0.0

Documentation

https://ecomfe.github.io/zrender-doc/public/

License

BSD 3-Clause License

Copyright (c) 2017, Baidu Inc. All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

  • Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.

  • Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.

  • Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Notice

The Apache Software Foundation Apache ECharts, ECharts, Apache, the Apache feather, and the Apache ECharts project logo are either registered trademarks or trademarks of the Apache Software Foundation.

zrender's People

Contributors

100pah avatar acierto avatar beebole avatar carterli avatar chriswong avatar dependabot[bot] avatar deqingli avatar erik168 avatar jonasba avatar jov5 avatar kener avatar kongmoumou avatar liuyang0826 avatar lzxb avatar mrwd2009 avatar ovilia avatar pissang avatar plainheart avatar soakit avatar southwhale avatar ssthouse avatar striezel avatar strwind avatar susiwen8 avatar uzlopak avatar yechunxi avatar yuqianma avatar zhuangzhuang avatar zhulin3141 avatar zoumiaojiang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

zrender's Issues

path不支持invisible?

RT,path shape设置invisible后,mouseover时不出现形状,代码报错。。。我暂时只好用透明色替代了。。。

cpu占用问题

发现requestAnimationFrame非常占用cpu,觉得可以在不需要动画的时候停止,所以
我在代码中加了stopAnimation和startAnimation,如果这样没有问题的话,希望在后续版本中加入类似功能接口.
或者可以做到智能侦测?!
self.startAnimation = function () {
animation.start();
}
self.stopAnimation = function () {
animation.stop();
}

window.devicePixelRatio造成的问题

为了retina 屏幕优化使用了window.devicePixelRatio,但是实际使用中,如果缩放浏览器大小,会导致canvas显示不完整,出现很多异常情况。。

例如把zrender官方demo页面调整到75%时,刷新页面,就很清楚看到问题了。。

部署和使用zrender过程中的困惑

关于zrender部署和使用,我有以下几个疑问:
1、将下载的压缩包先解压,然后将src、asset两个文件夹复制到我自己的程序包中就OK了,对吗?
2、其中asset\js\esl\esl.js文件中已经内嵌了r.js(require的JS文件)是吗?
3、在我要使用的页面JS文件中只要引入“<script src="zrender/asset/js/esl/esl.js"></script> ”就可以了,对吗?
4、以圆形Circle为例,加载的路径为'zrender/shape/Circle',可实际上Circle.js在我电脑上的存放位置是zrender\src\shape\Circle.js,为何require时不能写成'zrender/src/shape/Circle'?
5、看下面的这段代码:
require.config({
packages: [
{
name: 'zrender',
location: 'zrender/src',
main: 'zrender'
}
]
});

require(['zrender','zrender/shape/Circle'],
function(zrender)
{
var zr = zrender.init(domMain);
var CircleShape=require('zrender/shape/Circle'); //******
});
标记为//******的这行代码中的require函数不是标准的require.js吧?是不是开发者自己定义的函数?
而且var CircleShape=require('zrender/shape/Circle');这句只能放在require(['zrender','zrender/shape/Circle']后才能正确执行,否则就报错了。

关于Group类中delChildrenFromStorage方法的一点疑问

Group.prototype.delChildrenFromStorage = function(storage) {
for (var i = 0; i < this._children.length; i++) {
var child = this._children[i];
storage.delFromMap(child);
if (child.type === 'group') {
child.delChildrenFromStorage(storage);
}
}
};
这边的storage.delFromMap(child);是否应该改成storage.delFromMap(child.id);
因为delFromMap方法中的第一句 var el = this._elements[elId];有个索引查找。

新增椭圆后,text添加了 出不来。。

        zr.addShape({
                shape : 'ellipseo',
                style : {
                    x : 80,
                    y : 80,
                    a : 30,
                    b : 20,
                    color : 'rgba(255, 69, 0, 1)',// rgba supported
                    text : '开始',
                    textPosition :'inside'
                },              
                draggable : true            
            });
            zr.render();

旋转重叠问题

zr.clear()
var tenDeg = Math.PI / 18;
var origin = tenDeg;
zr.addShape({
shape : 'rectangle',
style : {
x : 100,
y : 100,
width : 160,
height : 40,
color : 'red' ,
text : 'Click to rotation!',
textPosition : 'inside'
},
rotation : [tenDeg, 180, 120],
draggable : true,
clickable : true,
onclick : function(params) {
origin += tenDeg;
zr.modShape(params.target.id, {rotation : [origin, 180, 120]});
zr.refresh();
zr.resize();
}
});
zr.addShape({
shape : 'rectangle',
style : {
x : 100,
y : 100,
width : 160,
height : 40,
color : 'red' ,
text : 'Click to rotation!',
textPosition : 'inside'
},
rotation : [tenDeg, 180, 120],
draggable : true,
clickable : true,
onclick : function(params) {
origin += tenDeg;
zr.modShape(params.target.id, {rotation : [origin, 180, 120]});
zr.refresh();
}
});
zr.render();

点击了第一个再点第二个会在第一个旋转的角度的基础上又旋转角度,如果只想在原来的基础上旋转指定角度应该怎么办?

ondragend()方法有点问题

例如:为某个shape设定拖拽结束事件
ondragend:function(){alert('test');return true;}

发现拖拽后的确会弹出一次alert,但当鼠标一旦移开图形去点击alert的‘确定’按钮时,又会弹出一次alert。
现在只能用“回车键”去点击第一次的alert‘确定’按钮来关闭警告框,才不会弹第二次alert。
有啥解决办法吗?

将高亮元素移到 hover 层配置为可选

现在所有 hover 的元素都会默认被移到 hover 层,这样有很多不方便的地方,比如因为 hover 层总在最上层所以 hover 的元素会遮挡所有其它的元素。如果 highlightStyle 设为全透明在有动画的时候也会出现问题,而且也不应该用这么trick的方法来解决这个问题。

hover 和元素置顶之间并不应该有联系,可以将 hover 的元素移到hover层作为一个优化的配置项,如果关闭,在hover和drag的时候刷新整个图形所在层。

加入PathProxy

#88 中提出过如何方便的在扩展中完成 isCover 方法,目前提出一个方案加入 PathProxy 代理 ctx 对象

PathProxy 放在 shape/tool/ 下,新建的对象可以作为 shape 的一个属性替代 ctx 对象,提供跟 ctx 一样的path操作方法,并且保存每个操作的命令到 pathArray 属性中,可以用于isInsidePath判断以及获取boundingRect

使用示例

var SomeShape = function() {
    this._pathProxy = new PathProxy();
}
SomeShape.prototype.buildPath = function(ctx, style) {
    this._pathProxy.begin(ctx);
        .moveTo(style.x, style.y);
        .lineTo(style.x1, style.y1);
    ...
        .closePath();
},
SomeShape.prototype.getRect = function(style) {
    if (!style._rect) {
        // 这里必须要在 buildPath 之后才能调用
        style._rect = this._pathProxy.getBoundingRect();
    }
    return this.style._rect;
},
SomeShape.prototype.isCover = function(x, y) {
    var rect = this.getRect(this.style);
    if (x >= rect.x
        && x <= (rect.x + rect.width)
        && y >= rect.y
        && y <= (rect.y + rect.height)
    ) {
         return require('../tool/area').isInsidePath(this._pathProxy, x, y);
    }
}

这样以后每次扩展 shape 都可以直接照着这套模板轻松高效的实现跨浏览器的hover判断

Zrender支持CMD吗

只看到amd的,如果不支持,怎么改造啊,因为我们项目用的是seajs

拖动以后

比如我在画布上画了一条线段 这个shape有start 和end对应的坐标,经过我测试 如果对这条线段进行拖动后,
ondrift : function(params) {
var x = dancer.shapTag.pos.x - dancer.content.pos.left ;
var y = dancer.shapTag.pos.y - dancer.content.pos.top;
var x1 = params.style.xStart;
var y1 = params.style.yStart;
var x2 = params.style.xEnd;
var y2 = params.style.yEnd;
//计算两点间的距离
if(((x-x1)(x-x1) + (y-y1)(y-y1)) <= 400) {
console.log(1)
return true;
}
else if(((x-x2)(x-x2) + (y-y2)(y-y2)) <= 400) {
console.log(2);
return true;
}
return false;
}
在ondrift里面通过这种方式来取值,这个start和end的值是不是会更新的
var x1 = params.style.xStart;
var y1 = params.style.yStart;
var x2 = params.style.xEnd;
var y2 = params.style.yEnd;
我看了一下api好像没有方法来更新和获取,请问如何获得最新的坐标数据呢?

SVG加载模块

能够加载解析svg文件并且挂在一个根Group下面,解析出来的结果能够保持原先的层级结构,能够保持attributes和style里的样式,css里的样式暂时忽略。
脑补用法1:

svgLoader.load('sample.svg', opts).then(function(g) {
    zr.addGroup(g);
    zr.refresh();
});

脑补用法2:

// 是对上一种的封装,通过 zr 加载可以在加载完后自动刷新,就跟图片差不多了
// 第一个参数是 svg 的路径(也可以是svg dom节点?)
// 第二个参数是挂载的根节点, 如果为空则返回新创建的根节点
// 第三个是可能会有的一些可选参数
zr.loadSVG('sample.svg', rootGroup, opts);

几个问题

  • 需要一个http模块,放在zrender/tool 下?
  • 是否需要一个 promise 模块?
  • Group 模块从 shape 目录移出来放到一个 container 目录下?

新增椭圆后 丢失了所画图形的一些默认方法比如 鼠标放上去 有边框显示,设置draggable : true等问题

// JavaScript Document
define(
function(require) {
function EllipseO() {
this.type = 'ellipseo';
}

    EllipseO.prototype =  {
        /**
         * 创建圆形路径
         * @param {Context2D} ctx Canvas 2D上下文
         * @param {Object} style 样式
         */
        buildPath : function(ctx, style) {

            ctx.font = '14px sans-serif'; 

            //BezierEllipse2(ctx, 33,21,30,18);
            BezierEllipse2(ctx, style.x, style.y, style.a, style.b);
            function BezierEllipse2(ctx, x, y, a, b)
            {
               var k = .5522848,
               ox = a * k, // 水平控制点偏移量
               oy = b * k; // 垂直控制点偏移量
               ctx.lineWidth = 3;
               //从椭圆的左端点开始顺时针绘制四条三次贝塞尔曲线
               ctx.moveTo(x - a, y);
               ctx.bezierCurveTo(x - a, y - oy, x - ox, y - b, x, y - b);
               ctx.bezierCurveTo(x + ox, y - b, x + a, y - oy, x + a, y);
               ctx.bezierCurveTo(x + a, y + oy, x + ox, y + b, x, y + b);
               ctx.bezierCurveTo(x - ox, y + b, x - a, y + oy, x - a, y);
            }
            return;
        },

        /**
         * 返回矩形区域,用于局部刷新和文字定位
         * @param {Object} style
         */
        getRect : function(style) {
            var lineWidth;
            if (style.brushType == 'stroke' || style.brushType == 'fill') {
                lineWidth = style.lineWidth || 1;
            }
            else {
                lineWidth = 0;
            }
            return {
                x : Math.round(style.x - style.a - lineWidth / 2),
                y : Math.round(style.y - style.b - lineWidth / 2),
                width : style.a * 2 + lineWidth,
                height : style.b * 2 + lineWidth
            };
        }
    };

    var base = require('./base');
    base.derive(EllipseO);

    var shape = require('../shape');
    shape.define('ellipseo', new EllipseO());
    return EllipseO;
}

);

我在zrender.js里面添加了这个文件 文件名为ellipse_1
require('./shape/ellipse_1');
现在可以正常画了 但是如title所示失去了一些默认的方法 请问这个是在哪设置呢

加载image失败时能否给出一个error回调?

RT
Image shape 如果src错误或者加载失败能否给出回调 可以外部处理下

源码是直接返回

 //图片已经加载完成
if (window.ActiveXObject) {
    if (image.readyState != 'complete') {
                            return;
                        }
                    }
                    else {
                        if (!image.complete) {
                            return;
                        }
                    }

关于update的使用

我现在到了画虚线的那个环节了,需要动态修改虚线的终点坐标,我的代码如下:
document.body.onmouseup = function(event) {
event = event || window.event;
if(dba.canMove) {
tag = getEventTag(event);
if(0 <= tag.className.indexOf("stepclick")) {
mousePos = getMousePos(event);
dancer.drawStep(mousePos.x, mousePos.y);
dancer.oprModel[1].className = "opr-model";
dancer.oprModel[0].className = "opr-model cur-model";
dancer.opreateNum = 0;
}
dba.canMove = false;
dba.moveTag.style.cursor = "";
dba.moveTag = '';
}
if(dancer.line.start) {
dancer.line.start = false;
}
//这个地方开始画起始点,线段的起始点和终点在刚开始是一样的
if(2 == dancer.opreateNum && !dancer.dotMove) {
dancer.shapTag = dancer.drawDotLine(event);
dancer.dotMove = true;
return;
}
//这个地方停止画线
if(2 == dancer.opreateNum && dancer.dotMove) {
dancer.oprModel[2].className = "opr-model";
dancer.oprModel[0].className = "opr-model cur-model";
dancer.opreateNum = 0;
dancer.dotMove = false;
}
}
//根据move 来不停的调用修改函数
document.body.onmousemove = function(event) {
event = event || window.event;
var mousePos, tempLeft, tempRight;
if(dba.canMove) {
mousePos = getMousePos(event);
dba.moveTag.style.left = mousePos.x - dba.moveTag.startLeft + "px";
dba.moveTag.style.top = mousePos.y - dba.moveTag.startTop + "px";
}

        if(dancer.dotMove) {
            mousePos = getMousePos(event);
            dancer.updateDot(mousePos);
        }   
    }
            //我尝试了refresh和update都不行,
    updateDot : function(pos) {
        pos.x = pos.x  - dancer.content.pos.left;
        pos.y = pos.y - dancer.content.pos.top;
        dancer.shapTag.style.xEnd = pos.x;
        dancer.shapTag.style.yEnd = pos.y;  
        zr.refresh();

/* zr.update(dancer.shapTag, function() {
console.log(dancer.shapTag.id)
});*/
}
//我知道你的echarts上面有这个功能,但是不晓得是如何实现,请指教

可以绘制图片吗?

类似如下的代码可以在canvas中绘制一张图片,zrender有没有相应的方法?
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
var img=document.getElementById("myImage");
ctx.drawImage(img,10,10);

看看效果

         * 鼠标悬浮刷画
         */
        function _brushHover(e) {
            var ctx = _ctxList['hover'];
            if (!e.onbrush //没有onbrush
                //有onbrush并且调用执行返回false或undefined则继续粉刷
                || (e.onbrush && !e.onbrush(ctx, e, true))
            ) {
                // Retina 优化
                if (zrender.catchBrushException) {
                    try {
                        shape.get(e.shape).brush(ctx, e, true, update);
                    }
                    catch(error) {
                        zrender.log(
                            error, 'hoverBrush error of ' + e.shape, e
                        );
                    }
                }
                else {
                    if(undefined != e.shape) {
                        shape.get(e.shape).brush(ctx, e, true, update);
                    }
                }
            }
        }

因为shape.get(e.shape).brush(ctx, e, true, update);这个地方的e,shape有时候会获取为undefined,会报错,所以我做了一下修改。但是 添加文字的效果又没出来了。代码如下
zr.clear();
zr.addShape({
shape : 'circle',
position: [300, 300],
style : {
x : 100,
y : 100,
r : 100,
color : 'rgba(135, 206, 250, 0.8)' // rgba supported
},
onmouseover: function(param) {
zr.addHoverShape({
shpae:"text",
style:{
x:80,
y:30,
color:"red",
text:"Hello"
}
})
},
draggable : true
});
zr.render();

var zrender=require('zrender'); 运行时报错

使用2.0版本,按下列方式一运行时会报错,错误如下:
Error: [MODULE_MISS]zrender is not exists!
throw new Error( '[MODULE_MISS]' + ids + ' is not exists!' );
按方式二,一切正常。

require只支持回调函数方式使用吗?

var fileLocation = './lib/zrender';
require.config({
    paths: {
        'zrender': fileLocation,
        'zrender/shape/Sector':fileLocation
    }
});

//方式一
var zrender=require('zrender');

//方式二
require([
'zrender',
'zrender/shape/Sector'
],function(zrender,SectorShape){
var zr = zrender.init(document.getElementById('main'));

    zr.clear();
 });

在iPad上拖动图形要触摸两次

在移动设备上拖动图形时,第一次触摸只是选中,第二次触摸才能拖动。能否改成第一次触摸就能拖动,增强用户体验。

使用图片后,出现的问题

我现在用一个png格式的图片来绘制,有个问题是 程序会给这个png添加一个颜色导致其显示不好看,如何才能阻止这个添加?
效果图:
正常情况下:
123
拖入一个新的图形后:
2333

API&DOC 中animate的第一个例子有误

1.例子中:
animation.animate( target, getter, setter )
animation.js源码中:
animate : function(target, options) {
options = options || {};
var deferred = new Deferred(
target,
options.loop,
options.getter,
options.setter
);
deferred.animation = this;
return deferred;
}
是否应写为
animation.animate(target,{
loop:true,
getter:getter,
setter:setter
});

2.还是这个例子中最后时候应该加上
animation.start()

[请教]render()与refresh()

根据文档,render()在addShape()之后调用,refresh()在delShape()、modShape()之后调用。如果要顺序执行一个addShape()和一个modShape(),render()、refresh()是都需要调用一次,还是只调用其中一个就够了?应该用哪一个?

copyright

第一行代码注释:

// Copyright 2006 Google Inc.

hover 判断改进

之前hover判断存在的几个问题:

  • 对不同的shape判断方式不统一
  • 复杂的 path 如果使用 isPointInPath 方法不支持IE8, 如果通过多边形判断的方式则非常不精确(在有curve的情况下),比较明显的一个例子就是和弦图中间的那几根弦。
  • 扩展shape要重写isCover方法判断很麻烦。
方案:
  1. 填充的判断,在 js重写 isPointInPath 方法,遵循 canvas的non-zero wining rule, 尽管其中三次贝塞尔曲线和弧线的相交计算很复杂,计算量比较大,但是测试下来速度还是非常快的。
  2. 描边的判断,在1中实现的一些基础函数,比如三次贝塞尔曲线的求根(在tool/curve方法下),能够快速对被赛尔曲线的描边用数学计算进行hover判断。
性能

对一个带有8条curve的path 使用重写的 isInsidePath 进行判断,chrome下能够做到 30w ops/sec 的速度,使用 buildPath再isPointInside的方法只有3k ops/sec 的速度。

方便扩展
  1. 提供一系列的isInsideXXXX函数方便判断
  2. 提供包围盒计算的方法,这点是在能够对path做出比较好的抽象的前提下,比如能够提供一个path shape里pathArray那样的描述。

同一个画布上画了40个图形后效率的问题

123
如图,当我画了这些图形后 操作起来感觉有明显的延迟,计算量应该比较大。请问如何优化?
还有就是 线段这个图形 我自己写了isCover后,zrender里面默认的判断函数还会不会计算?

zrender移动端(retina)支持

@kener

canvas在retina下如果不处理,会比较模糊(仍然走较低的分辨率)。
建议zrender支持一下retina屏,这样在移动端也可以使用了。

参考代码:

module.exports = function(canvas){
    var ctx = canvas.getContext('2d');
    var ratio = window.devicePixelRatio || 1;
    if (1 != ratio) {
        canvas.style.width = canvas.width + 'px';
        canvas.style.height = canvas.height + 'px';
        canvas.width *= ratio;
        canvas.height *= ratio;
        ctx.scale(ratio, ratio);
    }
    return canvas;
};

代码来自autoscale-canvas模块。

shpae : 'path' bug

zr.clear();
var color = require('zrender/tool/color');
var colorIdx = 0;

// 路径
zr.addShape({
shape : 'path',
id : zr.newShapeId('path'),
style : {
//path : 'M 0 0 L 0 100 L 100 100 Z',
path : 'M300 240 L300 20 A20 20 90 0 1 320 1 A300 300 90 0 1 599 280 A20 20 90 0 1 580 300 L360 300 A60 60 90 0 0 300 240',

    brushType : 'both',
    color : 'none',
    strokeColor : color.getColor(colorIdx++),
    text : 'path',
    textPosition : 'bottom'
},
clickable : true,
onclick : function() {
    alert('click on green shape!')
}

});

// 绘画
zr.render();
qq20140115103842

//只有红色区域能触发事件

Transformable 改进,event.Dispatcher独立成Eventful模块

  • Transformable 增加方法:
    • decomposeTransform, 将transform矩阵分解成SRT(scale, rotation, translation),有时候复杂的变换很难通过SRT来表示,需要直接在transform矩阵上操作,操作完后再分解成SRT
    • lookAt(position), 设置形状的朝向,在画有朝向的箭头时比较有用
  • event.Dispatcher 放到一个单独的Eventful模块里,和Transformable放在一块(两者都是作为mixin扩展对象的功能)

about path

能不能介绍一下SVG的path转换成canvas的原理,转换算法是怎么样的
看代码没看明白原理

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.