原创- react + d3.js +TS 实现冰柱图 类型优化

react + d3.js + TS 实现冰柱图

1. 结构

interface IDatum {
    name: string;
    children?: this[];
    populariy?: number;
}

2.1 类型优化

2.1.1 d3.partition<>()()

d3.json<IDatum>("./data/games.json").then(data: IDatum | undefined) => {
    let root: d3.HierarchyRectangularNode<IDatum> =  d3.partition<IDatum>.size([height, width])(
                    d3.hierarchy<IDatum>(data, (d:IDatum) => d.children? d.children : null)
                    .sum((d: IDatum) => (d.popularity ? d.popularity : 0))
                    .sort(
                        (a: d3.HierarchyNode<IDatum>, b: d3.HierarchyNode<IDatum>) =>
                            (b.data.popularity || 0) - (a.data.popularity || 0)
                    )
)

});

2.1.2 .attr('x', valueFun)

g.selectAll(".datarect")
    .data(root.descendants())
    .join("rect")
    .attr("class", "datarect")
    .attr("x", (d: d3.HierarRectangularNode<IDatum>) => d.yo / 2)
    .attr("y", (d: d3.HierarRectangularNode<IDatum>) => d.x0 / 2)
    .attr("height", (d: d3.HierarRectangularNode<IDatum>) => (d.x1 - d.x0) / 4)
    .attr("width", (d: d3.HierarchyRectangularNode<IDatum>) => (d.y1 - d.yo) / 2)
    .attr("fill", fill)

3 代码

import React, { useState, useRef, useEffect } from "react";
import * as d3 from "d3";
import { HierarchyNode } from "d3";
import { isDate } from "moment";
interface IGamesDatum {
  name: string;
  popularity: number;
}
interface IDatum {
  name: string;
  children?: this[];
  popularity?: number;
}
interface IDatumSum {
  name: string;
  children: this | IGamesDatum[];
  popularity: number;
}
const Icicle: React.FC = () => {
  const [width] = useState(1400);
  const [height] = useState(7000);
  const [margin] = useState({
    left: 150,
    top: 60,
    right: 50,
    bottom: 50,
  });
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;
  const svg = useRef<SVGSVGElement>(null);
  useEffect(() => {
    let root: d3.HierarchyRectangularNode<IDatum>;
    const svgSelection = d3.select(svg.current);
    svgSelection.attr("width", width).attr("height", height);
    const g = svgSelection
      .append("g")
      .attr("transform", `translate(${margin.left}, ${margin.right})`);
    let color: any;
    const fill = (d: any) => {
      if (d.depth === 0) return color(d.data.name);
      while (d.depth > 1) d = d.parent;
      return color(d.data.name);
    };
    const render = (data: d3.HierarchyRectangularNode<IDatum>) => {
      color = d3.scaleOrdinal(d3.schemeCategory10);
      g.selectAll(".datarect")
        .data(root.descendants())
        .join("rect")
        .attr("class", "datarect")
        .attr("x", (d: d3.HierarchyRectangularNode<IDatum>) => d.y0 / 2)
        .attr("y", (d: d3.HierarchyRectangularNode<IDatum>) => d.x0 / 4)
        .attr(
          "height",
          (d: d3.HierarchyRectangularNode<IDatum>) => (d.x1 - d.x0) / 4
        )
        .attr(
          "width",
          (d: d3.HierarchyRectangularNode<IDatum>) => (d.y1 - d.y0) / 2
        )
        .attr("fill", fill);
      g.selectAll(".datatext")
        .data(
          root
            .descendants()
            .filter(
              (d: d3.HierarchyRectangularNode<IDatum>) => d.x1 - d.x0 > 50
            )
        )
        .join("text")
        .attr("class", "datatext")
        .attr("text-anchor", "middle")
        .attr(
          "x",
          (d: d3.HierarchyRectangularNode<IDatum>) => (d.y0 + d.y1) / 4
        )
        .attr(
          "y",
          (d: d3.HierarchyRectangularNode<IDatum>) => (d.x0 + d.x1) / 8
        )
        .attr("dy", "0.35em")
        .attr("font-size", "1em")
        .text((d: d3.HierarchyRectangularNode<IDatum>) => d.data.name);
    };
    d3.json<IDatum>("./data/games.json").then((data: IDatum | undefined) => {
      if (data) {
        root = d3.partition<IDatum>().size([height, width])(
          d3
            .hierarchy<IDatum>(data, (d: IDatum) =>
              d.children ? d.children : null
            )
            .sum((d: IDatum) => (d.popularity ? d.popularity : 0))
            .sort(
              (a: d3.HierarchyNode<IDatum>, b: d3.HierarchyNode<IDatum>) =>
                (b.data.popularity || 0) - (a.data.popularity || 0)
            )
        );
        render(root);
      }
    });
  });
  return (
    <>
      <svg ref={svg}></svg>
    </>
  );
};
export { Icicle };

原文地址:https://www.cnblogs.com/xiaoxu-xmy/p/13772825.html
GitHub: https://github.com/lemon-Xu/Learning-d3.-Js
作者: lemon

posted @ 2020-10-06 10:28  lemon-Xu  阅读(256)  评论(0编辑  收藏  举报