簡體   English   中英

d3 按弧動畫路徑

[英]d3 animate path by arc

我開始使用 d3。 有一個問題,我怎樣才能沿着填充路徑正確地設置三角形的動畫? 我為儀表圖創建了一個基礎並對其進行了動畫處理。

 var chart = d3.select("#speedometer"); const arc = d3 .arc() .outerRadius(120) .innerRadius(90) .startAngle(-Math.PI / 2); chart .append("path") .datum({ endAngle: Math.PI / 2 }) .attr("transform", "translate(160, 180)") .attr("class", "background") .style("fill", "#495270") .attr("d", arc); const triangle = chart .append('g') .attr('transform', 'translate(30, 180) rotate(90)') .style('width', '100%') .append("path").attr("d", "M3.937,0,7.873,14H0Z"); const newAngle = (70 / 100) * Math.PI - Math.PI / 2; const foreground = chart .append("path") .datum({ endAngle: -Math.PI / 2 }) .style("fill", "rgb(50, 188, 228)") .attr("transform", "translate(160, 180)") .attr("d", arc); foreground .transition() .duration(3000) .attrTween("d", function (d) { const interpolate = d3.interpolate(d.endAngle, newAngle); return function (t) { d.endAngle = interpolate(t); return arc(d); }; }); triangle .transition() .duration(3000) function pathTween(path) { const length = path.node().getTotalLength(); // Get the length of the path const r = d3.interpolate(0, length); // Set up interpolation from 0 to the path length return function (t) { const point = path.node().getPointAtLength(r(t)); // Get the next point along the path d3 .select(this) // Select the circle .attr("transform", `translate(${point.x}, ${point.y})`); }; }
 .main-wrapper{ max-width: 80%; margin: 20px auto; } .element{ display: flex; flex-flow: column nowrap; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.4); padding: 20px; border-radius: 6px; } .title{ margin-bottom: 4px; font-weight: 500; } .description{ margin-bottom: 10px; color: rgba(0,0,0,.4); } #speedometer { width: 300px; height: 300px; } canvas{ width: 100%; height: 100%; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <div class="main-wrapper"> <section class="ui-section"> <div class="element"> <div class="title"> Speedometr </div> <div class="content"> <svg id="speedometer" viewbox="0 0 300 300"></svg> </div> </div> </section> </div>

問題是,如何將三角形鏈接到圖片中的動畫弧的邊緣?

我知道我應該使用

tween('path'....)

但不確定

在此處輸入圖片說明

我會使用 SVG transform: rotate ,因為它允許您指定相對於您應該旋轉的內容,並且因為您可以鏈接轉換。 在這種情況下,我將角度轉換為圓弧的中心,然后將其旋轉到正確的方向,然后將其向上移動到比外半徑大一點的位置,以便平滑地沿着線移動。

它不是像素完美的,我認為這是因為三角形不是整數像素寬。

 var chart = d3.select("#speedometer"); const arc = d3 .arc() .outerRadius(120) .innerRadius(90) .startAngle(-Math.PI / 2); chart .append("path") .datum({ endAngle: Math.PI / 2 }) .attr("transform", "translate(160, 180)") .attr("class", "background") .style("fill", "#495270") .attr("d", arc); const triangle = chart .append('g') .datum({ endAngle: -Math.PI / 2 }) .style('width', '100%') .append("path").attr("d", "M3.937,0,7.873,14H0Z"); const newAngle = (70 / 100) * Math.PI - Math.PI / 2; const foreground = chart .append("path") .datum({ endAngle: -Math.PI / 2 }) .style("fill", "rgb(50, 188, 228)") .attr("transform", "translate(160, 180)") .attr("d", arc); foreground .transition() .duration(3000) .attrTween("d", function (d) { const interpolate = d3.interpolate(d.endAngle, newAngle); return function (t) { d.endAngle = interpolate(t); return arc(d); }; }); triangle .transition() .duration(3000) .attrTween("transform", function (d) { const interpolate = d3.interpolate(d.endAngle, newAngle); return function (t) { const angleRadians = interpolate(t); const angleDegrees = 360 * angleRadians / (2 * Math.PI); return ` translate(158 176) rotate(${angleDegrees + 180} 3.5 7) translate(0 132) `; }; }); function pathTween(path) { const length = path.node().getTotalLength(); // Get the length of the path const r = d3.interpolate(0, length); // Set up interpolation from 0 to the path length return function (t) { const point = path.node().getPointAtLength(r(t)); // Get the next point along the path d3 .select(this) // Select the circle .attr("transform", `translate(${point.x}, ${point.y})`); }; }
 .main-wrapper{ max-width: 80%; margin: 20px auto; } .element{ display: flex; flex-flow: column nowrap; margin-bottom: 20px; border: 1px solid rgba(0,0,0,.4); padding: 20px; border-radius: 6px; } .title{ margin-bottom: 4px; font-weight: 500; } .description{ margin-bottom: 10px; color: rgba(0,0,0,.4); } #speedometer { width: 300px; height: 300px; } canvas{ width: 100%; height: 100%; }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.min.js"></script> <div class="main-wrapper"> <section class="ui-section"> <div class="element"> <div class="title"> Speedometr </div> <div class="content"> <svg id="speedometer" viewbox="0 0 300 300"></svg> </div> </div> </section> </div>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM