使用SVG和d3展开圆,将其转换为直线
在一个项目中,我们试图使一个圆在沿线性路径旋转时变成一条线(然后再转回来),就像轮胎在道路上滚动时旋转和平移一样,或者弯曲的前指伸展并重新旋转到手掌中 在这里,我有一个静态SVG(顶部圆圈),它沿着HTML中定义的线性黑色路径(位于圆圈上方,以模拟手指延伸)旋转 我还使用d3生成一个由连接点组成的“圆”(通过@ChrisJamesC,如果你点击圆,它可以展开),并进行平移和旋转 在函数moveAlongLine中,单击紫色线时:使用SVG和d3展开圆,将其转换为直线,svg,d3.js,Svg,D3.js,在一个项目中,我们试图使一个圆在沿线性路径旋转时变成一条线(然后再转回来),就像轮胎在道路上滚动时旋转和平移一样,或者弯曲的前指伸展并重新旋转到手掌中 在这里,我有一个静态SVG(顶部圆圈),它沿着HTML中定义的线性黑色路径(位于圆圈上方,以模拟手指延伸)旋转 我还使用d3生成一个由连接点组成的“圆”(通过@ChrisJamesC,如果你点击圆,它可以展开),并进行平移和旋转 在函数moveAlongLine中,单击紫色线时: function moveAlongLine() { circ
function moveAlongLine() {
circle.data([lineData])
.attr("transform", "translate(78.5,0) rotate(-90, 257.08 70) ")
.duration(1000)
circle.on("click", transitionToCircle)
}
第一个问题是,.duration(1000)
无法识别,并抛出一个未捕获类型错误:对象[Object Array]在控制台中没有方法“duration”
,因此SVG中的dur
静态定义与JS/D3中的动态设置之间存在差异,但这是次要的
另一个问题是,转换属性是否应该像静态循环中那样相互抽象?在静态圆中,平移是一个动画,旋转是另一个动画,它们只是具有相同的星形和持续时间,所以它们一起设置动画。你将如何在d3中应用这两种方法
我无法接受的挑战是,如何让它向上展开(并重新回滚),静态点是圆的上圆心,也是直线上最左边的点
这些似乎更好:
- 我应该尝试让展开动画在旋转的同时发生?这似乎需要以逐步/顺序为基础
- 或者这让我想到了另一种方式:(在八角形的情况下),我可以有8条线路径(没有Z,只是一个额外的闭合点),并且在它们之间过渡?像这样
- 或者有什么关键帧要做?我已经用Synfig制作了一个动画,但是我不确定如何将它放到SVG中。如果您可以将synfig文件转换为SVG,那么synfig文件就可以了,但是使用
时,xsl文件不能正确地将其转换为SVGxsltproc
- 定义点所遵循的路径(可能是具有相同数量参考点的贝塞尔曲线),并使参考点动态平移。。。有关概念示例,请参见
- 让一个真实的圆圈滚动而过,前面有一个不断增长的面具,同时一条线也在不断增长
- d3圆中的点数可以在JS中调整,当前设置为较低,以便您可以在渲染中看到一点,以验证是否发生了旋转(很像顶部圆中的渐变)
- 这是为了帮助学生学习数字线和圆之间的守恒关系,特别是帮助学习分数。对于概念应用程序,请查看我们的原型,这将有助于切换表示,帮助您更好地了解
试着从SO开始。需要调整它,使角度从180开始,在相同的位置(线4-6,19)结束,并在每个交互上沿X轴(线11)移动。更改
我最终使用了与问题中相同的生成圆圈的函数,并做了一些思考,似乎我想要一个像手指这样展开的动画。这让我想到了在这个世界上实现它所需要的数学和思想
答案是数组数组,每个嵌套数组都是处于不同状态的一条线,然后通过在点之间插值来设置动画
var circleStates = [];
for (i=0; i<totalPoints; i++){
//circle portion
var circleState = $.map(Array(numberOfPoints), function (d, j) {
var x = marginleft + radius + lineDivision*i + radius * Math.sin(2 * j * Math.PI / (numberOfPoints - 1));
var y = margintop + radius - radius * Math.cos(2 * j * Math.PI / (numberOfPoints - 1));
return { x: x, y: y};
})
circleState.splice(numberOfPoints-i);
//line portion
var lineState = $.map(Array(numberOfPoints), function (d, j) {
var x = marginleft + radius + lineDivision*j;
var y = margintop;
return { x: x, y: y};
})
lineState.splice(i);
//together
var individualState = lineState.concat(circleState);
circleStates.push(individualState);
}
var circleStates=[];
对于(i=0;i更新:对于1,您可以使用
来包装路径。因此,您所需要的只是将偏移量添加到与2中的x值相匹配的线11中的x轴。因此您是说有一个随圆旋转的遮罩?我们的好处是只需为chrome开发,因为它是唯一支持web音频套件的浏览器。这很好k您也可以将相同的数组与一些push-pop-map函数一起使用,但这可能会使事情变得更难理解,并且比您实际执行的操作更慢
function all() {
for(i=0; i<numberOfPoints; i++){
circle.data([circleStates[i]])
.transition()
.delay(dur*i)
.duration(dur)
.ease("linear")
.attr('d', pathFunction)
}
}
function reverse() {
for(i=0; i<numberOfPoints; i++){
circle.data([circleStates[numberOfPoints-1-i]])
.transition()
.delay(dur*i)
.duration(dur)
.ease("linear")
.attr('d', pathFunction)
}
}