Why the value for r is negative from d3.hierarchy in circle packing in d3.js?

Kuni

I'm using https://observablehq.com/@d3/zoomable-circle-packing as an example to try d3 and circle packing in angular. I have the data which seems to be hierarchical and I'm following along the code that's presented. However, my d3.hierarchy() is giving me strange results. For some reason, all d.x, d.y and r are all negative. I couldn't figure out why. I'm still reading some guides and books trying to understand if I can figure out how d3.hierarchy works to understand why the values are negative. But I'm bit struggling with that. What's happening in the code and how can I show the circle packing with 3 circles for each object in the array?

I have the codes in stackblitz below.

StackBlitz

The code is here in stackblitz

Code

import { Component, OnInit, ElementRef, ViewChild,  VERSION, AfterViewInit } from '@angular/core';
import * as d3 from 'd3';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit, AfterViewInit  {
 
  private diameter: number;
  private margin = { top: 20, right: 20, bottom: 20, left: 20 };
  private width: number;
  private height: number;
  private svg; any;
  private g: any;
  private svgContainer: ElementRef;
  private color: any;
  private dac: any;
  private pack: any;

  @ViewChild('circleContainer', { static: false }) set content(content: ElementRef) {

    if (content) {
      this.svgContainer = content;
    }

  }

  ngOnInit() {

  
    this.dac = {
    "name": "DAC",
    "children":
    [
        {
            "name":
            [
                "Direction"
            ],
            "children":
            {
                "children":
                [
                    {"name":"leader","score":3.33,"_row":"leader"},
                    {"name":"same_sector","score":3.64,"_row":"same_sector"},
                    {"name":"senior_teams","score":3.81,"_row":"senior_teams"},
                    {"name":"team","score":3.81,"_row":"team"}
                ]
            }
        },
        {
            "title":
            [
                "Alignment"
            ],
            "children":
            {
                "children":
                [
                    {"name":"leader","score":3,"_row":"leader"},
                    {"name":"same_sector","score":3.51,"_row":"same_sector"},
                    {"name":"senior_teams","score":3.48,"_row":"senior_teams"},
                    {"name":"team","score":3.48,"_row":"team"}
                ]
            }
        },
        {
            "title":
            [
                "Commitment"
            ],
            "children":
            {
                "children":
                [
                    {"name":"leader","score":3.67,"_row":"leader"},
                    {"name":"same_sector","score":4.05,"_row":"same_sector"},
                    {"name":"senior_teams","score":3.57,"_row":"senior_teams"},
                    {"name":"team","score":3.57,"_row":"team"}
                ]
            }
        }
    ]
}
    this.createChart();
  
  }

  ngAfterViewInit() {

    this.width = 500 - this.margin.left - this.margin.right;
    this.height = 400 - this.margin.top - this.margin.bottom;

    this.color = d3.scaleLinear<string>()
      .domain([1, 5])
      .range(["hsl(152,80%,80%)", "hsl(228,30%,40%)"])
      .interpolate(d3.interpolateHcl);

    if (this.svgContainer && this.dac) {

      this.createChart()

    }

  }


    private createSVG(rect) {

    this.svg = d3.select(rect)
      .append('svg')
      .attr('viewBox', `0 0  ${this.width / 2} ${this.height / 2}`)
      .attr('preserveAspectRatio', 'xMinYMin meet')
      .style('display', 'block')
      .style('margin', "0 auto")
      .style('background', this.color(1))
      .style('cursor', 'pointer')
      .attr('class', 'bubble-chart')

    this.diameter = +this.svg.attr("width")
    console.log("diameter: ", this.diameter);

    this.pack = data => d3.pack()
      .size([this.diameter - this.margin.left, this.diameter - this.margin.right])
      .padding(2)
      (d3.hierarchy(data)
        .sum(d => d.score)
        .sort((a, b) => b.value - a.value))
      

  }

 private createChart() {

    let that = this;

    const rect = this.svgContainer.nativeElement;

    this.createSVG(rect);

    const root = this.pack(this.dac);
    let focus = root;
    let view;

    console.log(root);
    this.svg = this.svg
      .on('click', (event) => zoom(event, root));

    const node = this.svg.append('g')
      .selectAll('circle')
      .data(root.descendants().slice(1))
      .join('circle')
      .attr('fill', d => d.children ? this.color(d.depth) : "white")
      .attr('pointer-events', d => !d.children ? "none" : null)
      .on('mouseover', function () { d3.select(this).attr('stroke', '#999'); })
      .on('mouseout', function () { d3.select(this).attr('stroke', 'null'); })
      .on('click', (event, d) => focus !== d && (zoom(event, d), event.stopPropagation()));

    const label = this.svg.append('g')
      .style('font', '10px Roboto')
      .attr('pointer-events', 'none')
      .attr('text-anchor', 'middle')
      .selectAll('text')
      .data(root.descendants())
      .join('text')
      .style('fill-opacity', d => d.parent === root ? 1 : 0)
      .style('display', d => d.parent === root ? 'inline' : 'none')
      .text(d => d.data.name);


    zoomTo([root.x, root.y, root.r * 2]);

    function zoomTo(v) {
      const k = that.width / v[2];

      view = v;

      
      console.log("k: ", k);
      console.log("v:",v);

      label.attr('transform', d => {
        console.log("dx: ", d.x)
        console.log("dy: ", d.y);
        return `translate(${(d.x - v[0]) * k}, ${(d.y - v[1]) * k})`});
      node.attr('transform', d => `translate(${(d.x - v[0]) * k}, ${(d.y - v[1]) * k})`);
      node.attr('r', d => d.r * k);
    }


    function zoom(event, d) {
      const focus0 = focus;
      focus = d;

      const transition = that.svg.transition()
        .duration(event.altKey ? 7500 : 750)
        .tween('zoom', d => {
          const i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2]);
          return t => zoomTo(i(t));
        });

      label
        .filter(function (d) { return d.parent === focus || this.style.display === 'inline'; })
        .transition(transition)
        .style('fill-opacity', d => d.parent === focus ? 1 : 0)
        .on('start', function (d) { if (d.parent === focus) this.style.display = 'inline'; })
        .on('end', function (d) { if (d.parent !== focus) this.style.display = 'none' });
    }



  }

  

}
Gerardo Furtado

You have 2 problems:

  1. Your data structure is incorrect, you have objects as the value of your children properties. They should be arrays.

  2. You are setting the SVG viewBox, not its width. Therefore, this...

    this.diameter = +this.svg.attr("width")
    

    ...is just +null, which is 0. Because of that, the array in the size() method will have negative values, which explains your main issue. Use your width and height instead.

Here is the forked code: https://stackblitz.com/edit/angular-circle-packing-uyigxs?file=src/app/app.component.ts

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

From Dev

How to get an non-overlapped circle packing d3 js chart?

From Dev

How to get an non-overlapped circle packing d3 js chart?

From Dev

D3 Circle-Packing Clear Labeling Solution

From Dev

d3: svg image in zoom circle packing

From Dev

Zoomable Circle Packing with Automatic Text Sizing in D3.js

From Dev

d3.js circle packing along a line

From Dev

D3 Zoomable Circle Packing in IE11 is expanding beyond the SVG boundary

From Dev

Image within circle object causes pixelation d3 js

From Dev

stop d3 circle pack labels from overlapping

From Dev

Place text on the radii extending from the center of a circle D3

From Dev

why no gaps between bars D3 js

From Dev

Why are events from d3 in firefox not handled

From Dev

Why axis labels are not removed from the DOM in d3?

From Dev

How to send a value from D3 node to Servlet

From Dev

D3: Get nearest value from ordinal axis on mouseover

From Dev

How to get value from the element using selection in d3

From Dev

How to get value from the element using selection in d3

From Dev

Adding text to d3 circle

From Dev

D3: Simple Interaction - Circle with a click

From Dev

darken rect/circle on mouseover in d3

From Dev

D3 add zoom to circle pack

From Dev

d3 image in circle not rendering properly

From Dev

D3 circle object has no properties

From Dev

d3 line/circle chart

From Dev

D3 Histogram with negative values

From Dev

D3 - Paths with negative values

From Dev

How to create a ul-li list from d3 nodes hierarchy?

From Dev

How to create a ul-li list from d3 nodes hierarchy?

From Dev

d3 js how to select from selection