当前位置: 首页 > 知识库问答 >
问题:

D3角树

崔单弓
2023-03-14

我有一个工作的D3树,我正试图转换成角。是v3树。

组件代码为:

import { Component, OnInit, ViewChild, ElementRef, AfterViewInit, ViewEncapsulation } from '@angular/core';
declare var d3: any;

@Component({
  selector: 'app-tree-view',
  template: '<div #chart id="chart"></div>',
  encapsulation: ViewEncapsulation.None,
  styleUrls: ['./tree-view.component.scss']
})
export class TreeViewComponent implements AfterViewInit, OnInit {

  ngOnInit(): void {
    this.createChart();
  }

  constructor(){

  }

  ngAfterViewInit(): void {
    this.root.update = this.update;
    this.update(this.root);
  }

private treeData: any[] = [{...data here}],

tree: any;
i = 0;
duration = 750;
root:any = {};
svg:any = {};
diagonal: any;

@ViewChild('chart')
private chartContainer: ElementRef;


private createChart(): void {
  var margin = {top: 20, right: 120, bottom: 20, left: 120},
    width = 1560 - margin.right - margin.left,
    height = 1000 - margin.top - margin.bottom;

 this.tree = d3.layout.tree()
    .size([height, width]);

  const element = this.chartContainer.nativeElement;

 this.diagonal = d3.svg.diagonal().projection((d) => { return [d.y, d.x]; });

 this.svg = d3.select(element).append("svg")
    .attr("width", width + margin.right + margin.left)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

this.root = this.treeData[0];
this.root.x0 = height / 2;
this.root.y0 = 0;

this.hideChildren(this.root);

console.log(this.root);

d3.select(self.frameElement).style("height", "1000px");
}

 private hideChildren(node) {
    if(node.children) {
        node._children = node.children;
        node.children = null;
        node._children.forEach((a) =>  { this.hideChildren});
    }
}

 private update(source) {

  // Compute the new tree layout.
  var nodes = this.tree.nodes(this.root).reverse(),
      links = this.tree.links(nodes);

  // Normalize for fixed-depth.
  nodes.forEach((d) => { d.y = d.depth * 180; });

  // Update the nodes…
  var node = this.svg.selectAll("g.node")
      .data(nodes, (d) => { return d.id || (d.id = ++this.i ); });

  // Enter any new nodes at the parent's previous position.
  var nodeEnter = node.enter().append("g")
      .attr("class", "node")
      .attr("transform", (d) => { return "translate(" + source.y0 + "," + source.x0 + ")"; })
      .on("click", this.click);

  nodeEnter.append("circle")
      .attr("r", 1e-6)
      .style("fill", (d) => { return d._children ? "lightsteelblue" : "#fff"; });

  nodeEnter.append("text")
      .attr("x", (d) => { return d.children || d._children ? -13 : 13; })
      .attr("dy", ".35em")
      .attr("text-anchor", (d) => { return d.children || d._children ? "end" : "start"; })
      .text((d) => { return d.name; })
      .style("fill-opacity", 1e-6);

  // Transition nodes to their new position.
  var nodeUpdate = node.transition()
      .duration(this.duration)
      .attr("transform", (d) => { return "translate(" + d.y + "," + d.x + ")"; });

  nodeUpdate.select("circle")
      .attr("r", 10)
      .style("fill", (d) => { return d._children ? "lightsteelblue" : "#fff"; });

  nodeUpdate.select("text")
      .style("fill-opacity", 1);

  // Transition exiting nodes to the parent's new position.
  var nodeExit = node.exit().transition()
      .duration(this.duration)
      .attr("transform", (d) => { return "translate(" + source.y + "," + source.x + ")"; })
      .remove();

  nodeExit.select("circle")
      .attr("r", 1e-6);

  nodeExit.select("text")
      .style("fill-opacity", 1e-6);

  // Update the links…
  var link = this.svg.selectAll("path.link")
      .data(links, (d) => { return d.target.id; });

  // Enter any new links at the parent's previous position.
  link.enter().insert("path", "g")
      .attr("class", "link")
      .attr("d", (d) => {
        var o = {x: source.x0, y: source.y0};
        return this.diagonal({source: o, target: o});
      });

  // Transition links to their new position.
  link.transition()
      .duration(this.duration)
      .attr("d", this.diagonal);

  // Transition exiting nodes to the parent's new position.
  link.exit().transition()
      .duration(this.duration)
      .attr("d", (d) => {
        var o = {x: source.x, y: source.y};
        return this.diagonal({source: o, target: o});
      })
      .remove();

  // Stash the old positions for transition.
  nodes.forEach((d) => {
    d.x0 = d.x;
    d.y0 = d.y;
  });

  console.log('end creating chart');
}

// Toggle children on click.
click(d, item) {
  if (d.children) {
    d._children = d.children;
    d.children = null;
  } else {
    d.children = d._children;
    d._children = null;
  }

  this.update(d);
}


}

如有任何帮助,将不胜感激

干杯KH

共有1个答案

米丰
2023-03-14

我使用内联函数而不是成员解决了这个问题

   ngOnInit(): void {
        console.log('on init');
        const createChart = () => {
            var margin = { top: 20, right: 120, bottom: 20, left: 120 },
                width = 1560 - margin.right - margin.left,
                height = 1000 - margin.top - margin.bottom;

            this.tree = d3.layout.tree()
                .size([height, width]);

            const element = this.chartContainer.nativeElement;

            this.diagonal = d3.svg.diagonal().projection((d) => { return [d.y, d.x]; });

            this.svg = d3.select(element).append("svg")
                .attr("width", width + margin.right + margin.left)
                .attr("height", height + margin.top + margin.bottom)
                .append("g")
                .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

            this.root = this.treeData[0];
            this.root.x0 = height / 2;
            this.root.y0 = 0;

            hideChildren(this.root);

            d3.select(self.frameElement).style("height", "1000px");
        };


        const update = (source) => {

            // Compute the new tree layout.
            var nodes = this.tree.nodes(this.root).reverse(),
                links = this.tree.links(nodes);

            // Normalize for fixed-depth.
            nodes.forEach((d) => { d.y = d.depth * 180; });

            // Update the nodes…
            var node = this.svg.selectAll("g.node")
                .data(nodes, (d) => { return d.id || (d.id = ++this.i); });

            // Enter any new nodes at the parent's previous position.
            var nodeEnter = node.enter().append("g")
                .attr("class", "node")
                .attr("transform", (d) => { return "translate(" + source.y0 + "," + source.x0 + ")"; })
                .on("click", click);

            nodeEnter.append("circle")
                .attr("r", 1e-6)
                .style("fill", (d) => { return d._children ? "lightsteelblue" : "#fff"; });

            nodeEnter.append("text")
                .attr("x", (d) => { return d.children || d._children ? -13 : 13; })
                .attr("dy", ".35em")
                .attr("text-anchor", (d) => { return d.children || d._children ? "end" : "start"; })
                .text((d) => { return d.name; })
                .style("fill-opacity", 1e-6);

            // Transition nodes to their new position.
            var nodeUpdate = node.transition()
                .duration(this.duration)
                .attr("transform", (d) => { return "translate(" + d.y + "," + d.x + ")"; });

            nodeUpdate.select("circle")
                .attr("r", 10)
                .style("fill", (d) => { return d._children ? "lightsteelblue" : "#fff"; });

            nodeUpdate.select("text")
                .style("fill-opacity", 1);

            // Transition exiting nodes to the parent's new position.
            var nodeExit = node.exit().transition()
                .duration(this.duration)
                .attr("transform", (d) => { return "translate(" + source.y + "," + source.x + ")"; })
                .remove();

            nodeExit.select("circle")
                .attr("r", 1e-6);

            nodeExit.select("text")
                .style("fill-opacity", 1e-6);

            // Update the links…
            var link = this.svg.selectAll("path.link")
                .data(links, (d) => { return d.target.id; });

            // Enter any new links at the parent's previous position.
            link.enter().insert("path", "g")
                .attr("class", "link")
                .attr("d", (d) => {
                    var o = { x: source.x0, y: source.y0 };
                    return this.diagonal({ source: o, target: o });
                });

            // Transition links to their new position.
            link.transition()
                .duration(this.duration)
                .attr("d", this.diagonal);

            // Transition exiting nodes to the parent's new position.
            link.exit().transition()
                .duration(this.duration)
                .attr("d", (d) => {
                    var o = { x: source.x, y: source.y };
                    return this.diagonal({ source: o, target: o });
                })
                .remove();

            // Stash the old positions for transition.
            nodes.forEach((d) => {
                d.x0 = d.x;
                d.y0 = d.y;
            });

            console.log('end creating chart');
        };


        const hideChildren = (node) => {
            if (node.children) {
                node._children = node.children;
                node.children = null;
                node._children.forEach((a) => { hideChildren(a); });
            }
        };

        const click = (d) => {
            if (d.children) {
                d._children = d.children;
                d.children = null;
            } else {
                d.children = d._children;
                d._children = null;
            }

            update(d);
        };

        createChart();
        this.root.update = update;
        update(this.root);
    }
 类似资料:
  • 视图移动以及缩放是一种将用户注意力聚焦在感兴趣区域的一种流行的交互技术。操作直接,容易理解: 点击并拖拽平移,使用滚轮进行缩放,当然也可以通过触摸进行。平移和缩放被广泛的应用在地图中,但是也可被应用到其他的可视化比如时间序列以及散点图中。 缩放行为通过 d3-zoom 模块实现,能方便且灵活到 selections 上。它处理了许多 Installing NPM 安装: npm install d

  • 这个模块实现了用来计算一组二维点 Voronoi diagram(泰森多边形) 或 Delaunay triangulation(德劳内三角剖分) 的 Steven J. Fortune’s algorithm 算法。这个模块的实现大多是基于 Raymond Hill 的工作。 泰森多边形不仅仅在视觉上具有吸引力,在交互方面也非常实用,比如在散点图中增加点的目标面积。参考 “Strikeouts

  • transition 是一个类 selection 的接口,用来对 DOM 进行动画修改。这种修改不是立即修改,而是在规定的事件内平滑过渡到目标状态。 应用过渡,首先要选中元素,然后调用 selection.transition,并且设置期望的改变,例如: d3.select("body") .transition() .style("background-color", "red")

  • 这个模块提供了一个高效的队列,能管理上千并发动画同时保证与并发或分段动画一致的同步时序。在内部使用 requestAnimationFrame 进行 fluid animation(如果支持的话),否则切换使用 setTimeout来实现。 Installing NPM 安装: npm install d3-timer. 此外还可以下载 latest release。也可以直接从 d3js.org

  • 在可视化时间序列数据、分析时间模式或处理一般时间时,常规时间单位的不规则性很快就变得明显起来。在 Gregorian calendar(公历) 中,大多数月份有 31 天但是有些月份只有 28 或者 29、30 天。大多数年份有 365 天但是 leap years(闰年) 有 366 天。在 daylight saving(夏令时) 中一天可能有 23 25 小时。更复杂的是世界各地的夏时制不同

  • 可视化通常由离散图形标记组成, 比如 symbols, arcs, lines 和 areas。虽然条形的矩形可以很容易的使用 SVG 或者 Canvas 来生成, 但是其他的比如圆形的扇形以及向心 Catmull-Rom 样条曲线就很复杂。这个模块提供了许多图形生成器以便使用。 与 D3 的其他特性一样,这些图形也是又数据驱动的: 每个图形生成器都暴露了一个如何将数据映射到可视化表现的访问器。例