In d3.js, what is the purpose of using svg.node()?

Viewed 4259

I'm trying to understand the code I got. I think I kind of went through the details. But still, there are something I really can't understand.

Things that I can't understand are

1) svg.node()

2) bisect/ bisector part

3) for (let i = 0; i < n; ++i) { if (i % 1 ==0 || 1 ) yield svg.node();



1) svg.node()

In the generator 'gen()', it yields svg.node(). and it is literally drawing things on my svg ( I checked it just uncomment the line only)

What is svg.node() and why do I need to use that argument to draw something? because, normally, when I want to draw something, I just need to d3.select('svg').append('###').... then I could draw something on my 'svg' however, in this generator, it is using 'svg.node()' to draw something. I wonder why and what is 'svg.node()

function* gen() {
  var random = d3.randomNormal(); // Try randomUniform?

  const n = 2000;
  const width = window.innerWidth;
  const height = 400;
  const radius = 2;
  const dodge = dodger(radius * 2 + 1);
  const margin = { top: 0, right: 10, bottom: 20, left: 10 };

  const values = Float64Array.from({ length: n }, random);

  const x = d3.scaleLinear(d3.extent(values), [
    margin.left,
    width - margin.right
  ]);
  const svg = d3
    .select("body")
    .append("svg")
    .attr("width", width)
    .attr("height", height)
    .style("overflow", "visible");

  // var fillScale = d3.scaleSequentialLog(chroma.interpolateSinebow)

  svg
    .append("g")
    .attr("transform", `translate(0,${height - margin.bottom})`)
    .call(d3.axisBottom(x));

  function dodger(radius) {
    const radius2 = radius ** 2;
    const bisect = d3.bisector(d => d.x);
    const circles = [];

    return function(x) {
      const l = bisect.left(circles, x - radius);
      const r = bisect.right(circles, x + radius);
      let y = 0;
      for (let i = l; i < r; ++i) {
        const { x: xi, y: yi } = circles[i];
        const x2 = (xi - x) ** 2;
        const y2 = (yi - y) ** 2;
        if (radius2 > x2 + y2) {
          y = yi + Math.sqrt(radius2 - x2) + 1e-6;
          i = l - 1;
          continue;
        }
      }
      circles.splice(bisect.left(circles, x, l, r), 0, { x, y }); 
      return y;
    };
  }

  for (let i = 0; i < n; ++i) {
    if (i % 5 === 0) yield svg.node();
    const cx = x(values[i]); // x(values[i]);
    const cy = height - margin.bottom - dodge(cx) - radius - 1;

    svg
      .append("circle")
      .attr("cx", cx)
      .attr("cy", -400)
      .attr("r", radius)
      .attr("fill", "red")
      .attr("fill", "#9e0dd7") //purple
      .transition()
      .duration(650)
      .ease(d3.easeBounce)
      .attr("cy", cy);
  }

  yield svg.node();
}


const genratorAnimation = gen(); 

let result = genratorAnimation.next();
//genratorAnimation.next();
let interval = setInterval(function(){
   if(!result.done) {
     genratorAnimation.next();
   }
   else {
    clearInterval(interval)
   }
}, 50);

2)bisect/ bisector /splice

I don't get the logic that the code uses for placing balls using bisect, bisector and splice. I understand bisect is spitting the index number that new entity would go into the array.(based on ascending order) splice is replacing or insert entities in the array. However, I don't get how the code enables the arrangement of dropping balls desired.

3) for (let i = 0; i < n; ++i) { if (i % 1 ==0 || 1 ) yield svg.node();

I played with the number by changing 1==0 to 2==0 and 10==0. It seems like the equation defines the number of balls that would drop each time. Why?

I know I asked too many question and I'm open to ask several time by posting many questions one by one. But it would be very grateful if someone could answer.

Thank you in advance.

2 Answers

if you console.log(svg.node()),you can find a object contains total element nodes of svg in your console.

return svg.node() is usually used to show or update svg figure.

svg.node() returns the svg value. But, I don't know why it draws something by putting the argument.

Related