我已经准备好D3径向图组件以显示某些目标的百分比值。当开始从0到chartPercentage(例如70%)绘制前景圆时,添加平滑过渡效果会很棒。

问题是-如何使用下面随附的代码准备过渡/延迟/持续时间效果?

我还想实现的第二个想法是用从0到chartValue的动画计算圆(径向内容)内的值。如何准备这样的解决方案?

谢谢 !



  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>

最佳答案

我重写了您的代码。当需要设置某些属性的动画时,应使用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>

关于javascript - D3-平滑的径向图过渡动画,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46111152/

10-11 05:29