D3JS - 优化数千个元素的补间变换

时间:2017-10-29 08:40:08

标签: javascript d3.js svg geometry

我使用D3.js在卫星项目上工作,我尝试将它们表示为根据其属性起伏的圆圈。要为它们设置动画,我在transform属性上使用补间。您可以在此处看到一个示例:https://jsfiddle.net/b7kL980y/

但我需要渲染更多元素。使用55个元素,动画仍然流畅:https://jsfiddle.net/sw9vbzgy/1/。但是当我尝试使用~1500个元素时,圆圈甚至不会渲染(https://jsfiddle.net/wgpr2ba1/1/)。我还尝试使用cycx插值而不是transform,但它既不起作用。

你有一些建议或想法吗?

var svg = d3.select('#canvas').append('svg')
    .attr('width', window.innerWidth)
    .attr('height', window.innerHeight);

var center = {
    x: window.innerWidth / 2,
    y: window.innerHeight / 2
};

d3.json('https://api.myjson.com/bins/futij', function(error, json) {
    if(error) console.error(error);

    var scaleY = d3.scaleLinear()
        .domain([-100, 62000])
        .range([0, window.innerHeight]);

    var scaleSize = d3.scaleLinear()
        .domain([1, 8000])
        .range([3, 30]);

    var scaleCosinus = d3.scaleLinear()
        .domain([0, 1])
        .range([0, Math.PI * 2]);

    var colors = {
        'Government': 'rgba(52, 152, 219, 0.6)',
        'Commercial': 'rgba(155, 89, 182, 0.6)',
        'Military': 'rgba(46, 204, 113, 0.6)',
        'Civil': 'rgba(231, 76, 60, 0.6)',
        'Military/Government': 'rgba(241, 196, 15, 0.6)',
        'Government/Commercial': 'rgba(26, 188, 156, 0.6)',
        'Military/Commercial': 'rgba(52, 73, 94, 0.6)',
        'Government/Civil': 'rgba(149, 165, 166, 0.6)',
    };

    var circles = svg.selectAll('circle')
        .data(json)
        .enter()
        .append('circle')
        .attr('cx', function(d) {
            var size = d.launch_mass != "" && d.launch_mass != undefined ? scaleSize(d.launch_mass) : 3;
            return -1 * scaleSize(size) - 1;
        })
        .attr('cy', function(d) { return scaleY(d.perigee) })
        .attr('r', function(d) { return d.launch_mass != "" && d.launch_mass != undefined ? scaleSize(d.launch_mass) : 3 })
        .style('fill', function(d) { return colors[d.users] });

    circles.transition()
        .each(animate);

    function animate(d) {
        var circle = d3.select(this);
        circle.attr('cx', parseFloat(circle.attr('r') + 1) * - 1)
            .attr('cy', scaleY(d.perigee))
            .transition()
            .ease(d3.easeLinear)
            .duration(d.period * 20)
            .attrTween('transform', function(d) {
               return function(t) {
                   return "translate(" + t * (window.innerWidth + parseFloat(circle.attr('r')) + 1) + ", " + scaleY(Math.cos(scaleCosinus(t)) * -1  * ((d.apogee - d.perigee) / 2) + d.perigee * 2) + ")";
               }
            })
            .on('end', animate);
    }
});

谢谢!

0 个答案:

没有答案