D3's first attempt -- bubble

d3 version 5.9.2

The bubble graph of d3 mainly uses d3.pack(), which is a kind of data processing. All the bubbles are not overlapped by calculation.

d3.pack() will return the x,y coordinates and radius r of each data, so that you can layout according to the returned data.

Pit encountered in this process:

1. Many functions have been reporting errors due to version problems. There are many differences between versions 3 and 4 or above

2. The effect I want is a rectangle, but it is always rendered as a square

The reason is that the package layout has a root node, which will package all the sub nodes together, so its calculation range is still a circle, so it is impossible to render it into a rectangle, but you can manually calculate it by yourself

3. When setting the style, it is also different from ordinary css

Line: stroke

Background color: fill

Effect:

html:

<section id="graph" style="width: 100%; height: 150px"></section>

style:

.add-green-color {
    stroke: #50E3C2;
    fill: #50E3C2;
    fill-opacity: 0.25;
  }

js:

const data = [{
      name: 'I feel good',
      value: 185,
    }, {
      name: 'Have fun',
      value: 88,
    }, {
      name: 'Scenic beauty',
      value: 35,
    }, {
      name: 'well-mannered',
      value: 63,
    }, {
      name: 'I feel good',
      value: 185,
    }, {
      name: 'Have fun',
      value: 88,
    }, {
      name: 'Scenic beauty',
      value: 35,
    }, {
      name: 'well-mannered',
      value: 63,
    }];
    data.forEach((t: any, index: number) => {
      t.id = index;
    });
    const elementGraph = document.getElementById('graph');
    const boxWidth = elementGraph === null ? 0 : elementGraph.clientWidth;
    const packs = (wordData: any) => d3.pack()
    .size([boxWidth, 150])
    .padding(3)
    (d3.hierarchy({children: wordData})
    .sum((d: any) => d.value));
    const root = packs(data);

    const svg = d3.select('#graph').append('svg')
    .style('width', '100%')
    .style('height', '100%')
    .attr('font-family', 'sans-serif')
    .attr('font-weight', 'bold')
    .attr('text-anchor', 'middle');

    const leaf = svg.selectAll('g')
    .data(root.leaves())
    .join('g')
    .attr('transform', (d: any) => `translate(${(d.x - 70) * 2},${d.y})`);

    leaf.append('circle')
    .attr('r', (d: any) => d.r)
    .attr('class', 'add-green-color');

    leaf.append('clipPath')
    .attr('id', (d: any) => 'cover-' + d.data.id)
    .append('circle')
    .attr('fill', '#ffffff')
    .attr('r', (d: any) => d.r);


    leaf.append('text')
    .attr('clip-path', (d: any) => 'url(#cover-' + d.data.id + ')')
    .attr('font-size', (d: any) => {
      const num = Math.ceil(d.data.value / 15);
      return num > 18 ? 18 : num < 8 ? 8 : num;
    })
    .selectAll('tspan')
    .data((d: any) => d.data.name.split(/(?=[A-Z][^A-Z])/g))
    .join('tspan')
    .attr('x', 0)
    .attr('y', (d: any, i: any, nodes: any) => `${i - nodes.length / 2 + 0.8}em`)
    .attr('fill', '#ffffff')
    .text((d: any) => d);
    return svg.node();

Mask (clipPath) reference: https://www.cnblogs.com/kbnet/p/8041910.html

Tags: Front-end

Posted on Sat, 09 Nov 2019 15:41:08 -0500 by eleven0