如何在d3.js中像gif这样的gif一样盘旋动画?

时间:2018-03-08 04:07:20

标签: javascript d3.js

我是d3.js的新手。这是我喜欢的圈子动画。它就像一个无限的动画。

enter image description here

我想复制这个动画以在d3.js中生成它,但我认为我的知识不足,这段代码是我能够复制动画的最接近的。

然后我的想法是,我可以在图像中看到鼠标悬停效果。我该怎么做?非常感谢你。

这是我的代码,这是我目前的结果:

enter image description here

var width = document.getElementById('circles').offsetWidth-70;
  var height =(width/2)+100;     
  var scale = d3.scale.linear()
    .range(["yellow","orange","red"])
    .domain([0,60]);

  var data = [0,10,20,30,40,50,60];

  var svg = d3.select("#circles").append("svg")
      .attr("width", width+"px")
      .attr("height", height+"px");

  //circle orange
  svg.append("circle")
  .attr("cx",80)
  .attr("cy",80)
  .attr("r",30)
   .attr("fill","orange")
  .style("stroke-width","1")
  .style("stroke","orange")    
  .on('mouseover', function(){
    d3.select(this).transition().ease("bounce").duration(500).attr("r",32)
  })
  .on('mouseout', function(){
    d3.select(this).transition().ease("bounce").duration(500).attr("r",30)
  })

  //circle yellow
   svg.append("circle")
  .attr("cx",80)
  .attr("cy",80)
  .attr("r",22)
  .attr("fill","yellow")
  .style("stroke-width","1")
  .style("stroke","yellow")
  .style("opacity","0.9")    

  .on('mouseover', function(){
    d3.select(this).transition().ease("bounce").duration(500).attr("r",24).style("opacity","1")  
  })
  .on('mouseout', function(){
    d3.select(this).transition().ease("bounce").duration(500).attr("r",22).style("opacity","0.9")
  })      

     var circles = svg.selectAll("circle")
    .data(data)
    .enter()
    .append("circle")
    .attr("r",function(d) { return d; })
    .attr("transform","translate(80,80)")
    .attr("fill","none")
    .style("stroke-width","1")
    .style("stroke",function(d) { return scale(d) });  

  function transition() {
    // Update data, max d is 60:
    data = data.map(function(d) { return d == 60 ? 0 : d + 10});

    var i = 0;
    // Grow circles
    circles
       .data(data)
       .filter(function(d) { return d > 0 })
       .transition()
       //.ease(d3.easeLinear)
       .ease("linear")//set the ease here
       .attr("r", function(d) { return d; })
       .style("stroke", function(d) { return scale(d) })
       .style("opacity",function(d) { return d == 60 ? 0 : 1 }) 
       .duration(1000)
       //.on("end",function(){if(++i==circles.size()-1) { transition(); } });
        .each("end", function (d,i) {
          //.on("end", function (d,i) {
           if(++i==circles.size()-1) { transition(); } 
        });

    // Reset circles where r == 0
    circles
      .filter(function(d) { return d == 0 })
      .attr("r", 0)
      .style("opacity",1)
      .style("stroke",function(d) { return scale(d); });

  }
  transition();

http://plnkr.co/edit/kz2tbxoS9lsfy2oMDzhY?p=preview

1 个答案:

答案 0 :(得分:4)

这是学习 d3.transition 功能的好例子。 就像@AndrewReid的参考资料一样,您的代码已经存在,以达到预期的效果。

在你的代码中(如果我理解正确的话),你直接产生散发效果,数据更新圆半径并直接用选择组编号控制每个圆的生命周期。

实际上,您可以直接使用 d3.transition属性来控制圆形过渡生命周期以产生直观效果。

这里有一些d3.transition生命周期的阅读材料

  1. A Life of a transition
  2. Working with Transition
  3. 这是我的代码
    在我的实现中,我使用数据来决定emananting圈数和 使用transition.on来监听每个完成的转换周期并重置属性。

    //DOM.svg is the syntax in observablhq, in browser, replace with your way
    const svg = d3.select(DOM.svg(250,250));
    
    const data = Array.from(Array(CircleNumber).keys());
    
    // use this emanating function to control the execution cycles
    function emananting(num){
    
            svg.selectAll('circle.emanting')
             .transition() 
             .duration((d,i)=>{
              return 2500;
            })  // duration to control each circle emananting duration
             .delay((d,i)=>{
              return i*500; 
              }) // delay to control between each circle's space
             .attr('opacity',0)
             .attr('r',50)
             .on('end',(d,i,g)=>{
                // after each transition end, trigger these codes
                d3.select(g[i])
                  .attr('r', 10)
                  .attr('opacity',1);
                   // control flow from listening to the last transition    done!
                   // remove the num < 10 condition , it will be infinite
                   if (i===5 && num < 2){
                        console.log(num);
                        emananting(num+1);
    
                    }
                });
     }
     // Here create the center circle body
     svg.append('circle')
     .classed('CircleBody',true)
     .attr('r',10)
     .attr('stroke','yellow')
     .attr('fill','orange')
     .attr('opacity',1)
     .attr('cx',125)
     .attr('cy',125);
    
    // Here create the emanting circle
    svg.selectAll('circle.emanting')
                .data(data)
                .enter()
                .append('circle')
                .attr('class','emanting')
                .attr('id', (d,i)=>{
                    return 'number' + i;
                                })
                .attr('r',10)
                .attr('stroke','orange')
                .attr('fill','none')
                .attr('opacity',1)
                .attr('cx',125)
                .attr('cy',125);
     // control flow 
     emananting(0);
    

    这里有一些关于@observablehq的演示 https://beta.observablehq.com/@weitinglin/demo-how-can-i-make-the-animation-of-a-circle-continous-with-h