Как уменьшить размер внутреннего круга солнечных лучей в d3 - PullRequest
0 голосов
/ 24 сентября 2019

Я создал свой собственный прототип https://jsfiddle.net/liilii_ii/9co8h4La/ из этого кода https://vizhub.com/ahlev/d77c2d3bd9a34d8c98791b89f47517fa

Моя проблема в том, что я не могу уменьшить внутренний радиус.Размер солнечных лучей должен оставаться неизменным, только белый корневой узел должен быть немного меньше.У кого-нибудь есть идея?Спасибо за вашу помощь!

<svg id="partitionSVG" width="932" height="480" viewBox="0 0 932 932"></svg>
    const format = d3.format(',d');
    const width = 932;
    const radius = width / 6;

    const arc = d3.arc()
      .startAngle((d: any) => d.x0)
      .endAngle((d: any) => d.x1)
      .padAngle((d: any) => Math.min((d.x1 - d.x0) / 2, 0.005))
      .padRadius(radius * 1.5)
      .innerRadius((d: any) => (d.y0 * radius))
      .outerRadius((d: any) => Math.max(d.y0 * radius, d.y1 * radius - 1));

    const partition = data1 => {
      const root3 = d3.hierarchy(data1)
        .sum(d => d.value)
        .sort((a, b) => b.value - a.value);
      return d3.partition()
        .size([2 * Math.PI, root3.height + 1])
        (root3);
    };

    const data = getData();
    const root = partition(data);
    const color = d3.scaleOrdinal(d3.quantize(d3.interpolateRainbow, data.children.length + 1));

    root.each((d: any) => d.current = d);

    const svg = d3.select('#partitionSVG')
      .style('width', '100%')
      .style('height', 'auto')
      .style('font', '15px sans-serif');

    const g = svg.append('g')
      .attr('transform', `translate(${width / 2},${width / 2})`);

    const path = g.append('g')
      .selectAll('path')
      .data(root.descendants().slice(1))
      .join('path')
      .attr('fill-opacity', (d: any) => arcVisible(d.current) ? (d.children ? 0.6 : 0.4) : 0)
      .attr('d', (d: any) => arc(d.current))
      .style('fill', (d: any) => {
        while (d.depth > 1) {
          d = d.parent;
        }
        return color(d.data.name);
      });

    path
      .style('cursor', 'pointer')
      .on('click', clicked);

    path.append('title')
      .text(d => `${d.ancestors().map((d2: any) => d2.data.name).reverse().join('/')}\n${format(d.value)}`);

    const label = g.append('g')
      .attr('pointer-events', 'none')
      .attr('text-anchor', 'middle')
      .style('user-select', 'none')
      .selectAll('text')
      .data(root.descendants().slice(1))
      .join('text')
      .attr('dy', '0.35em')
      .attr('fill-opacity', (d: any) => +labelVisible(d.current))
      .attr('transform', (d: any) => labelTransform(d.current))
      .text((d: any) => d.data.name);

    let val;
    label.each(getSize)
      .style('font-size', (d: any) => {
        if (d.scale > 0) {
          val = true;
          return 15 + 'px';
        }
      })
      .text((d: any) => {
        if (val) {
          if (d.data.name.length >= 20) {
            return d.data.name.substring(0, 16) + '...';
          } else {
            return d.data.name;
          }
        }
        val = false;
      });

    const parent = g.append('circle')
      .datum(root)
      .attr('r', radius)
      .attr('fill', 'none')
      .attr('pointer-events', 'all')
      .on('click', clicked);

    function clicked(p) {
      parent.datum(p.parent || root);

      root.each((d: any) => d.target = {
        x0: Math.max(0, Math.min(1, (d.x0 - p.x0) / (p.x1 - p.x0))) * 2 * Math.PI,
        x1: Math.max(0, Math.min(1, (d.x1 - p.x0) / (p.x1 - p.x0))) * 2 * Math.PI,
        y0: Math.max(0, d.y0 - p.depth),
        y1: Math.max(0, d.y1 - p.depth)
      });

      const t = g.transition().duration(750);

      // Transition the data on all arcs, even the ones that aren’t visible,
      // so that if this transition is interrupted, entering arcs will start
      // the next transition from the desired position.
      path.transition(t)
        .tween('data', (d: any) => {
          const i = d3.interpolate(d.current, d.target);
          return t2 => d.current = i(t2);
        })
        .filter((d: any, i: number, n: any) => {
          return n[i].getAttribute('fill-opacity') || arcVisible(d.target);
        })
        .attr('fill-opacity', (d: any) => arcVisible(d.target) ? (d.children ? 0.6 : 0.4) : 0)
        .attrTween('d', (d: any) => () => arc(d.current));

      label
        .filter((d: any, i: number, n: any) => {
          return n[i].getAttribute('fill-opacity') || labelVisible(d.target);
        })
        .transition(t)
        .attr('fill-opacity', (d: any) => +labelVisible(d.target))
        .attrTween('transform', (d: any) => () => labelTransform(d.current));
    }

    function arcVisible(d) {
      return d.y1 <= 3 && d.y0 >= 0 && d.x1 > d.x0;
    }

    function labelVisible(d) {
      return d.y1 <= 3 && d.y0 >= 0 && (d.y1 - d.y0) * (d.x1 - d.x0) > 0.03;
    }

    function labelTransform(d) {
      const x = (d.x0 + d.x1) / 2 * 180 / Math.PI;
      const y = (d.y0 + d.y1) / 2 * radius;
      return `rotate(${x - 90}) translate(${y},0) rotate(${x < 180 ? 0 : 180})`;
    }

    function getSize(d: any, i: number, n: any) {
      const bbox = n[i].getBBox();
      const cbbox = n[i].parentNode.getBBox();
      const scale = Math.min(cbbox.width / bbox.width, cbbox.height / bbox.height);
      d.scale = scale;
    }

    function getData(): any {
      return {
        name: 'TOPICS',
        children: [
          {
            name: 'Smart Mobility',
            children: [
              { name: 'Zugang zu internationlem Verkehr', value: 1 },
              { name: 'Bevorzugung von effizienten Transportmitteln', value: 1 },
              { name: 'Integration von IT im Verkehrsmittel und Infratsruktur', value: 1 }
            ]
          },
          {
            name: 'Smart People',
            children: [
              { name: 'Inklusive und partizipative Gesellscahft', value: 1 },
              { name: 'Moderene Bildungsangebote im Hochschulbereich', value: 1 },
              { name: 'Offenheit gegenüber Kreativität', value: 1 },
            ]
          },
          {
            name: 'Smart Economy',
            children: [
              { name: 'Unternehmerisches und innovatives Daenken und Handeln', value: 1 },
              { name: 'Produktivität', value: 1 },
              { name: 'Lokale und globale Vernetzung', value: 1 },
            ]
          },
          {
            name: 'Smart Energy und Environment',
            children: [
              { name: 'Nachhaltige Stadtplanung und - entwicklung', value: 1 },
              { name: 'Ressourcenschonung und erneurbare Energien', value: 1 },
              { name: 'Smarte und nachhaltige Gebäude', value: 1 },
            ]
          },
          {
            name: 'Smart Government',
            children: [
              { name: 'Open Government', value: 1 },
              { name: 'Bereitstellung technologischer Infrastruktur', value: 1 },
              { name: 'Anbieten von Online Services durch die Verwaltung', value: 1 },
            ]
          },
          {
            name: 'Smart Living',
            children: [
              { name: 'Gesundheit', value: 1, },
              { name: 'Sicherheit', value: 1, },
              { name: 'Lebensqualität und kultrelle Angebote', value: 1, }
            ]
          }
        ]
      };
    }
  }

Здесь вы можете увидеть, как выглядит моя диаграмма солнечных лучей

...