通过使用SVG和d3展开圆圈将其转换为直线(transition a circle into a line by unrolling it with SVG and d3)

编程入门 行业动态 更新时间:2024-10-27 20:36:41
通过使用SVG和d3展开圆圈将其转换为直线(transition a circle into a line by unrolling it with SVG and d3)

对于一个项目,我们试图在沿着直线路径旋转时将圆形成一条线(并且再次返回),就像轮胎在道路上滚动时旋转和平移,或者卷曲的前指伸展并重新进入掌心。

在这个小提琴中 ,我有一个静态SVG(顶部圆圈),它沿着HTML中定义的线性黑色路径(在圆圈上方,模仿手指伸展)旋转。

我还使用d3生成一个由连接点组成的“圆圈”(如果你在这里点击/在圆圈中可以展开,感谢@ChrisJamesC),并且当你点击它时,它会在函数moveAlongLine中被翻译和旋转。紫线:

function moveAlongLine() { circle.data([lineData]) .attr("transform", "translate(78.5,0) rotate(-90, 257.08 70) ") .duration(1000) circle.on("click", transitionToCircle) }

第一个问题是.duration(1000)无法识别并抛出Uncaught TypeError: Object [object Array] has no method 'duration'在控制台中Uncaught TypeError: Object [object Array] has no method 'duration' ,因此SVG中dur的静态定义与动态之间存在差异在JS / D3中设置它,但这是次要的。

另一个是变换属性是否应该像静态圆一样相互抽象? 在静态圆中,平移是一个动画,旋转是另一个,它们只有相同的星和持续时间,因此它们一起动画。 你如何在d3中同时申请?

我无法获得的挑战是如何让它向上展开(并且还重新回滚),静态点是圆的顶部中心也与线上最左边的点相同。

这似乎更好:

我应该尝试在旋转的同时获得展开的动画吗? 这似乎需要逐步/顺序... 或者考虑一个octogon(定义为路径),如果要旋转7个边,那么6,然后是5 ....对多面体上相当多的点进行此操作? (圆圈只需要大约50个左右的像素,所以100个点就足够了)这是小提琴中的中间例子。 也许以编程方式这样做? 或者这让我想到了一个不同的方式:(在octogon的情况下),我可以有8个线路径(没有Z,只有一个额外的关闭点),以及它们之间的过渡? 喜欢这个小提琴 或者关键帧的任何东西? 我在Synfig制作了动画片,但我不确定是否可以使用SVG。 如果您可以转换为SVG,则synfig文件位于http://specialorange.org/filedrop/unroll.sifz ,但此处的xsl文件无法使用xsltproc正确转换它。

这看起来很复杂但有潜力:

定义点跟随的路径(可能是具有相同参考点数的贝塞尔曲线),并使参考点动态转换...请参阅此概念示例

这似乎很复杂和笨重:

制作一个真正的圆圈,在它前面有一个不断增长的面具,同时一条线长度增加

几个笔记:

d3圆中的点数可以在JS中调整,当前设置为低,这样您就可以在渲染中看到一点来验证旋转是否已经发生(很像渐变位于顶部圆圈中) 。 这是为了帮助学生学习数字线和圆圈之间的保守,特别是帮助学习分数。 对于概念应用,请查看compthink.cs.vt.edu:3000以查看我们的原型,这将有助于切换表示,以帮助您获得更好的想法......

For a project we are trying to make a circle into a line (and back again) while it is rotating along a linear path, much like a tire rotates and translates when rolling on a road, or a curled fore finger is extended and recurled into the palm.

In this Fiddle, I have a static SVG (the top circle) that rotates along the linear black path (which is above the circle, to mimic a finger extending) that is defined in the HTML.

I also use d3 to generate a "circle" that is made up of connected points (and can unfurl if you click on/in the circle thanks to @ChrisJamesC here ), and is translated and rotated in the function moveAlongLine when you click on the purple Line:

function moveAlongLine() { circle.data([lineData]) .attr("transform", "translate(78.5,0) rotate(-90, 257.08 70) ") .duration(1000) circle.on("click", transitionToCircle) }

The first problem is that the .duration(1000) is not recognized and throws a Uncaught TypeError: Object [object Array] has no method 'duration' in the console, so there is a difference between the static definition of dur in SVG and dynamically setting it in JS/D3, but this is minor.

The other is should the transform attributes be abstracted from one another like in the static circle? in the static circle, the translate is one animation, and the rotation is another, they just have the same star and duration, so they animate together. How would you apply both in d3?

The challenge that I can not get, is how to let it unroll upwards(and also re-roll back), with the static point being the top center of the circle also being the same as the leftmost point on the line.

these seem better:

I should try to get the unfurl animation to occur while also rotating? This seems like it would need to be stepwise/sequential based... Or Consider an octogon (defined as a path), and if it were to rotate 7 of the sides, then 6, then 5.... Do this for a rather large number of points on a polyhedron? (the circle only needs to be around 50 or so pixels, so 100 points would be more than enough) This is the middle example in the fiddle. Maybe doing this programmatically? Or This makes me think of a different way: (in the case of the octogon), I could have 8 line paths (with no Z, just an additional closing point), and transition between them? Like this fiddle Or anything todo with keyframes? I have made an animation in Synfig, but am unsure ho get it to SVG. The synfig file is at http://specialorange.org/filedrop/unroll.sifz if you can convert to SVG, but the xsl file here doesn't correctly convert it for me using xsltproc.

this seems really complicated but potential:

Define a path (likely a bézier curve with the same number of reference points) that the points follow, and have the reference points dynamically translate as well... see this for an concept example

this seems complicated and clunky:

Make a real circle roll by, with a growing mask in front of it, all while a line grows in length

A couple of notes:

The number of points in the d3 circle can be adjusted in the JS, it is currently set low so that you can see a bit of a point in the rendering to verify the rotation has occurred (much like the gradient is in the top circle). this is to help students learn what is conserved between a number line and a circle, specifically to help learn fractions. For concept application, take a look at compthink.cs.vt.edu:3000 to see our prototype, and this will help with switching representations, to help you get a better idea...

最满意答案

我最终使用了与问题中生成圆圈相同的功能,并做了一些思考,似乎我想要一个看起来像手指展开的动画像这个小提琴 。 这让我想到了在这个小提琴中实现它所需要的数学和思想。

答案是一个数组数组,每个嵌套数组都是一个处于不同状态的行,然后通过在这些点之间插值来设置动画。

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); }

和动画

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) } }

I ended up using the same function that generates the circle as in the question, and did a bit of thinking, and it seemed like I wanted an animation that looked like a finger unrolling like this fiddle. This lead me to the math and idea needed to make it happen in this fiddle.

The answer is an array of arrays, with each nested array being a line in the different state, and then animate by interpolating between the points.

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); }

and the animation(s)

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) } }

更多推荐

本文发布于:2023-08-07 03:24:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1460064.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:将其   圆圈   转换为   直线   SVG

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!