концентрические излучающие круги d3

1

У меня есть массив одинаково разнесенных значений, которые я использую для рисования концентрических окружностей. Я хочу использовать эманирующий эффект, по существу, удалить самый внешний круг, как только его значение превысит максимальное значение и добавит новый в центр для компенсации. Я не уверен в манипуляции с набором данных для удаления и добавления нового круга.

<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var svg = d3.select("body").append("svg");
var w = window.innerWidth;
var h = window.innerHeight;
var separation = Math.min(50, w/12);
var n=Math.floor((w/2)/separation);
var ellipse=new Array(n);
for(var i=1;i<=n;i++){
 ellipse[i-1]=(i*separation);
}

svg.attr("width", w).attr("height", h);
var g = svg.append("g");

var e=g.selectAll("ellipse")
  .data(ellipse)
  .enter()
  .append("ellipse")
  .attr("cx", w/2)
  .attr("cy", h/2)
  .attr("rx",0)
  .attr("ry",0)
  .transition()
  .duration(5000)
  .attr("rx", function(d,i){return ellipse[i];})
  .attr("ry", function(d,i){return ellipse[i]/5;});

  loop();
  function loop(){
    e.transition()
    .attr("rx", function(d,i){
           return ellipse[i]+separation;
         })
    .attr("ry", function(d,i){
           return (ellipse[i]+separation)/5;
         })
    .on("end",loop());
    }
  </script>
Теги:
d3.js
data-visualization

1 ответ

2
Лучший ответ

Вы можете подойти к нему с помощью метода remove(). Exit() и enter(). Append() для каждого кольца - но по существу у вас всегда будет одинаковое количество звонков на экране. Почему бы просто не перерабатывать одни и те же элементы? Когда размер достигает порога, сбросьте его на ноль или какое-то другое начальное значение?

Что-то вроде:

var scale = d3.scaleLinear()
  .range(["orange","steelblue","purple"])
  .domain([0,60]);
  
var data = [0,10,20,30,40,50,60];

var width = 200;
var height = 200;

var svg = d3.select("body")
  .append("svg")
  .attr("width",width)
  .attr("height",height);
  
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","4")
  .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)
     .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(); } });
    
     
  // 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();
<script src="https://d3js.org/d3.v4.min.js"></script>

Обратите внимание, что .on("end",... триггеры на каждом конце перехода элемента - вот почему я подсчитываю, чтобы все элементы были выполнены, прежде чем снова запустить функцию перехода.

  • 0
    Это здорово, Андрей. Вы также можете рассказать, как реализовать то же самое с помощью remove (). Exit () и enter (). Append (). Я не смог понять код, хотя подход очевиден. Скоро выложу ссылку, над которой я работаю!

Ещё вопросы

Сообщество Overcoder
Наверх
Меню