d3.js:如何在翻译时围绕其中心旋转SVG?

时间:2016-08-31 05:14:21

标签: javascript html css d3.js svg

问题:

我一直试图找到一个通用的解决方案来同时使用d3.js v4.2.2旋转和翻译SVG。

我可以让SVG以正确的位置开始和结束,但中间的缓和是完全错误的。下面是一个JSFiddle,我在从DOM中拉出的同一个SVG的许多实例上进行了旋转+转换,每个实例根据数据点进行不同的旋转量。

需要注意的一点是,我需要这个解决方案在从(100,100)转换为(500,500)时以及从(0,0)开始时的工作。

https://jsfiddle.net/3jbv23em/

var serializer = new XMLSerializer();

var svgNode = serializer.serializeToString(document.querySelector('#svgs svg defs svg'));

var dataset = [1,8,15,22,29,36,43,50,57,64,71,78,85,92,99,106,113,120,127,134,141,148,155,162,169,176,183,190,197,204,211,218,225,232,239,246,253,260,267,274,281,288,295,302,309,316,323,330,337,344,351,358]

var wrapper = d3
    .select('#game svg')
        .attr('width', window.innerWidth)
        .attr('height', window.innerHeight)
    .selectAll('g')
        .data(dataset)
        .enter()
        .append('g')
            .html(function(d) { return svgNode; })
            .transition()
            .duration(1500)
            .attr('transform', function(d) { 
                return 'translate(500,300)' +
                       'rotate(' + d * 1.8 + ', 63, 54.77)';
            });

(不幸的是,我无法让D3 v4在JSFiddle中运行,所以JSFiddle在这里使用v3。但问题是相同的。)

我的预期行为:所有鸡只围绕同一个中心旋转,从不延伸到动画结束时看到的圆圈尺寸。

实际结果:所有鸡围绕左上角的平移原始位置旋转,然后返回到最后的正确位置。

对我不起作用的解决方案:

How to rotate an object around the center in d3.js

  • 这是关于在更远处的固定点周围旋转,而不是在试图旋转的物体上的某个点周围

SVG rotation anchorpoint

  • 这可能有效,但完全让我脱离了D3生态系统

How do I rotate or scale (transform) an SVG path relative to its center point?

  • 我需要解决方案从任意点开始,而不是始终是原点@(0,0)

结论:

此刻我很困惑,非常感谢任何帮助。谢谢你的时间。

1 个答案:

答案 0 :(得分:4)

因为D3过渡同时适用于翻译和旋转,所以即使最终结果是你正在寻找的东西,你也会得到一些看起来很尴尬的动画。

D3提供了一个d3.interpolateString,可以按照您希望的方式处理动画。 d3.interpolateString需要开始和结束变换。 d3.interpolateString用于attrTween。

替换

.attr('transform', function(d) { 
    return 'translate(500,300)' +
           'rotate(' + d * 1.8 + ', 63, 54.77)';
});

使用

.attrTween('transform', function(d, i, a) { 
    return d3.interpolateString('translate(0,0) rotate(0)',
                                'translate(500,300)' +
                                'rotate(' + d * 1.8 + ', 63, 54.77)');
});

这是一个更新的jsfiddle,对翻译进行了调整,以便更好地查看小屏幕。

https://jsfiddle.net/3jbv23em/16/

有相同问题的有用链接是“D3.js animate rotation”。