D3/Raphael js 以慢帧率绘制 1000+ 动画圆圈

D3/Raphael js draws 1000+ animated circle with slow fps

本文关键字:1000+ 绘制 动画 帧率 Raphael js D3      更新时间:2023-09-26

我在Raphael JS v2.1上编写了脚本,绘制了1000+个圆圈和许多路径。圆圈沿该路径进行动画处理,然后删除。在 ~100 圈时,fps 为 40。在 1000+ fps 是 1-10。代码示例:

var r = Raphael("diagram", "100%", "100%");
setInterval(function () {
    r.moveCircle(lines[Math.floor(Math.random() * 20)]);
}, 100);
Raphael.fn.moveCircle = function (path) {
    var circle = this.circle(0, 0, 4).attr({fill: '#000'});
    circle.animateAlong({
        path: path,
        duration: 1000
    },
    function() {
        circle.remove();
    });
};
Raphael.el.animateAlong = function (params, props, callback) {
    var element = this,
        paper = element.paper,
        path = params.path,
        rotate = params.rotate,
        duration = params.duration,
        easing = params.easing,
        debug = params.debug,
        isElem = typeof path !== 'string';
    element.path = 
        isElem
            ? path
            : paper.path(path);
    element.pathLen = element.path.getTotalLength();
    element.rotateWith = rotate;
    element.path.attr({
        stroke: debug ? 'red' : isElem ? path.attr('stroke') : 'rgba(0,0,0,0)',
        'stroke-width': debug ? 2 : isElem ? path.attr('stroke-width') : 0
    });
    paper.customAttributes.along = function(v) {
        var point = this.path.getPointAtLength(v * this.pathLen),
            attrs = {
                cx: point.x,
                cy: point.y 
            };
        this.rotateWith && (attrs.transform = 'r'+point.alpha);
        return attrs;
    };
    if(props instanceof Function) {
        callback = props;
        props = null;
    }
    if(!props) {
        props = {
            along: 1
        };
    } else {
        props.along = 1;    
    }
    var startAlong = element.attr('along') || 0;
    element.attr({along: startAlong}).animate(props, duration, easing, function() {
        !isElem && element.path.remove();
        callback && callback.call(element);
    });
};

问题:

1) 是否有可能提高 Raphael JS 的性能/速度/fps?

2) 在 D3 上.js FPS 会是贝特吗?10,000+动画圈呢?

3)是否有任何解决方案可以沿着具有良好FPS的路径可视化10,000 +动画圆圈?

可能的瓶颈是 DOM 操作(添加/删除节点、编辑属性等),因此 d3 将有同样的问题。如果你有很多东西要画,使用画布而不是SVG(特别是在WebGL上下文中)会快得多。

坚持使用 SVG 的同时加快速度的方法:

  • 重用 DOM 节点,而不是删除它们并添加新节点
  • 使用 CSS 提前定义动画。

沿路径对圆进行动画处理的另一种方法是使用 stroke-dasharraystroke-dashoffsetstroke-linecap:round 。任何零长度的破折号都将呈现为圆形。然后,您可以使用stroke-dashoffset沿路径移动圆圈。不过,这仅适用于单个圆半径,可通过 stroke-width 进行控制。

这种方法的好处是你可以消除一堆圆形元素。