简体   繁体   English

D3-平滑的径向图过渡动画

[英]D3 - smooth radial chart transition animation

I've prepared D3 Radial Chart component to show percentage value of some target. 我已经准备好D3径向图组件以显示某些目标的百分比值。 It would be great to add smoothy transition effect when start drawing foreground circle from 0 to chartPercentage (eg. 70%). 当从0开始绘制前景圆到chartPercentage(例如70%)时,添加平滑过渡效果会很棒。

The question is - how to prepare transition / delay / duration effect with code which is attached below ? 问题是-如何使用下面随附的代码准备过渡/延迟/持续时间效果?

Second idea which I also want to implement is to count value inside of the circle (radial-content) with animation from 0 to chartValue. 我还想实现的第二个想法是用从0到chartValue的动画对圆(径向内容)内的值进行计数。 How to prepare such solution? 如何准备这样的解决方案?

Thank you ! 谢谢 !

  const chartPercentage = 70; const chartValue = 1.1242 const radius = 75; const border = 7; const padding = 0; const width = 400; const height = 400; const twoPi = Math.PI * 2; const boxSize = (radius + padding) * 2; let svg; function setArc() { return d3.arc() .startAngle(0) .innerRadius(radius) .outerRadius(radius - border) .cornerRadius(50); } function draw() { svg = d3.select(".chart").append("svg") .attr('width', width) .attr('height', height); svg.append("foreignObject") .attr("width", boxSize) .attr("height", boxSize) .append("xhtml:div") .attr('class', 'radial-wrapper') .html(`<div class="radial-content">${chartValue}</div>`); const field = svg.append('g') .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')'); const meter = field.append('g') .attr('class', 'progress-meter'); const background = meter.append("path") .datum({endAngle: twoPi}) .attr('class', 'background') .attr('fill', '#2D2E2F') .attr('fill-opacity', 0.1) .attr("d", setArc()); const foreground = meter.append("path") .datum({endAngle: (chartPercentage/100) * twoPi}) .attr('class', 'foreground') .attr('fill', 'red') .attr('fill-opacity', 1) .attr('d', setArc()); } draw(); 
  body { margin:30px;position:fixed;top:0;right:0;bottom:0;left:0; } .radial-wrapper{ display: flex; align-items: center; justify-content: center;width: 100%; height: 100%;} 
 <script src="https://d3js.org/d3.v4.min.js"></script> <div class="chart"></div> 

Make a function for attribute tween. 使属性补间功能。

function arcTween(a) {
  var j = {"endAngle":0};//start angle
  var i = d3.interpolateObject(j, a);
  return function(t) {
    d3.select(".radial-content").text(d3.format(".4n")(chartValue*t));
    return arc(i(t));
  };
}

In the above function 在上面的功能

d3.select(".radial-content").text(d3.format(".4n")(chartValue*t));

this will change the text(and output it in the format) in the radial content as the transition runs. 这将在过渡运行时更改径向内容中的文本(并以格式输出)。

now add the tween function to the foreground path. 现在将补间功能添加到前景路径。

  const foreground = meter.append("path")
    .datum({
      endAngle: (chartPercentage / 100) * twoPi
    })
    .attr('class', 'foreground')
    .attr('fill', 'red')
    .attr('fill-opacity', 1)
  .transition().duration(750).attrTween("d", arcTween);

working code here 这里的工作代码

I rewrote your code. 我重写了您的代码。 When you need to animate some attribute, you should use attrTween not attr method. 当需要设置某些属性的动画时,应使用attrTween而不是attr方法。

 const chartPercentage = 70; const chartValue = 1.1242 const radius = 75; const border = 7; const padding = 0; const width = 400; const height = 400; const twoPi = Math.PI * 2; const boxSize = (radius + padding) * 2; let svg; const setArc = d3.arc() .startAngle(0) .innerRadius(radius) .outerRadius(radius - border) .cornerRadius(50); const arcParams = {}; function draw() { svg = d3.select(".chart").append("svg") .attr('width', width) .attr('height', height); svg.append("foreignObject") .attr("width", boxSize) .attr("height", boxSize) .append("xhtml:div") .attr('class', 'radial-wrapper') .html(`<div class="radial-content"></div>`); const field = svg.append('g') .attr('transform', 'translate(' + boxSize / 2 + ',' + boxSize / 2 + ')'); const meter = field.append('g') .attr('class', 'progress-meter'); const background = meter .append("path") .attr('class', 'background') .attr('fill', '#2D2E2F') .attr('fill-opacity', 0.1) .attr("d", setArc({ endAngle: twoPi })); const foreground = meter .append("path") .transition() .ease(d3.easeBounce) .duration(1500) .attr('class', 'foreground') .attr('fill', 'red') .attr('fill-opacity', 1) .attrTween("d", function() { return arcTween({ endAngle: 0 }, chartPercentage/100 ) }) } function arcTween(d, new_score) { var new_startAngle = 0 var new_endAngle = new_startAngle + new_score * 2 * Math.PI var interpolate_start = d3.interpolate(d.startAngle, new_startAngle) var interpolate_end = d3.interpolate(d.endAngle, new_endAngle) return function(t) { d.endAngle = interpolate_end(t) d3.select('.radial-content') .text((d.endAngle / new_endAngle * chartValue).toFixed(4)); return setArc(d) } } draw(); 
 body { margin: 30px; position: fixed; top: 0; right: 0; bottom: 0; left: 0; } .radial-wrapper { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; } 
 <script src="https://d3js.org/d3.v4.min.js"></script> <div class="chart"></div> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM