D3 svg 组件不可调整大小

Posted

技术标签:

【中文标题】D3 svg 组件不可调整大小【英文标题】:D3 svg components not resizable 【发布时间】:2019-01-25 17:25:20 【问题描述】:

我正在使用Angular 4D3 创建一个应用程序。当我通过将组件注入另一个组件从组件内部创建svg 组件时,它会显示该组件,但调整大小和移动功能不起作用(即使在悬停时也不会显示调整大小和移动光标)。 如果我使用相同的组件并通过路由导航到组件,则调整大小和移动功能会起作用。知道为什么。

以下是我使用的组件。

import  Component, OnInit  from '@angular/core';
import * as d3 from 'd3';

@Component(
  selector: 'app-function-box',
  templateUrl: './function-box.component.html',
  styleUrls: ['./function-box.component.css']
)
export class FunctionBoxComponent implements OnInit 

  constructor()  

  ngOnInit() 
  

  w = 500;
  h = 350;
  r = 120;

  width = 200;
  height = 100;
  dragbarw = 10;

  svg = d3.select("body").append("svg")
    .attr("width", this.w)
    .attr("height", this.h);

  newg = this.svg.append("g")
    .data([x: 400, y: 100]); //position

  dragrect = this.newg.append("rect")
    .attr("id", "active")
    .attr("x", (d) =>  return d.x;  )
    .attr("y", (d) =>  return d.y; )
    .attr("height", this.height)
    .attr("width", this.width)
    .attr("fill-opacity", .5)
    .attr("cursor", "move")
    .call(d3.drag()
      .on("drag", this.dragmove.bind(this)));

  dragbarleft = this.newg.append("rect")
    .attr("x", (d) =>  return d.x - (this.dragbarw/2); )
    .attr("y", (d) =>  return d.y + (this.dragbarw/2); )
    .attr("height", this.height - this.dragbarw)
    .attr("id", "dragleft")
    .attr("width", this.dragbarw)
    .attr("fill", "lightblue")
    .attr("fill-opacity", .5)
    .attr("cursor", "ew-resize")
    .call(d3.drag()
      .on("drag", this.ldragresize.bind(this)));

  dragbarright = this.newg.append("rect")
    .attr("x", (d) =>  return d.x + this.width - (this.dragbarw/2); )
    .attr("y", (d) =>  return d.y + (this.dragbarw/2); )
    .attr("id", "dragright")
    .attr("height", this.height - this.dragbarw)
    .attr("width", this.dragbarw)
    .attr("fill", "lightblue")
    .attr("fill-opacity", .5)
    .attr("cursor", "ew-resize")
    .call(d3.drag()
      .on("drag", this.rdragresize.bind(this)));

  dragbartop = this.newg.append("rect")
    .attr("x", (d) =>  return d.x + (this.dragbarw/2);)
    .attr("y", (d) =>  return d.y - (this.dragbarw/2); )
    .attr("height", this.dragbarw)
    .attr("id", "dragleft")
    .attr("width", this.width - this.dragbarw)
    .attr("fill", "lightgreen")
    .attr("fill-opacity", .5)
    .attr("cursor", "ns-resize")
    .call(d3.drag()
      .on("drag", this.tdragresize));

  dragbarbottom = this.newg.append("rect")
    .attr("x", (d) =>  return d.x + (this.dragbarw/2); )
    .attr("y", (d) =>  return d.y + this.height - (this.dragbarw/2); )
    .attr("id", "dragright")
    .attr("height", this.dragbarw)
    .attr("width", this.width - this.dragbarw)
    .attr("fill", "lightgreen")
    .attr("fill-opacity", .5)
    .attr("cursor", "ns-resize")
    .call(d3.drag()
      .on("drag", this.bdragresize.bind(this)));

  dragmove(d) 

    this.dragrect
      .attr("x", d.x = Math.max(0, Math.min(this.w - this.width, d3.event.x)));
    this.dragbarleft
      .attr("x", (d) =>  return d.x - (this.dragbarw/2); );
    this.dragbarright
      .attr("x", (d) =>  return d.x +this.width - (this.dragbarw/2); );
    this.dragbartop
      .attr("x", (d) =>  return d.x + (this.dragbarw/2); );
    this.dragbarbottom
      .attr("x", (d) =>  return d.x + (this.dragbarw/2); )

    this.dragrect
      .attr("y", d.y = Math.max(0, Math.min(this.h - this.height, d3.event.y)));
    this.dragbarleft
      .attr("y", (d) =>  return d.y + (this.dragbarw/2); );
    this.dragbarright
      .attr("y", (d) =>  return d.y + (this.dragbarw/2); );
    this.dragbartop
      .attr("y", (d) =>  return d.y - (this.dragbarw/2); );
    this.dragbarbottom
      .attr("y", (d) =>  return d.y + this.height - (this.dragbarw/2); );

  

  ldragresize(d) 
    let oldx = d.x;
    //Max x on the right is x + width - dragbarw
    //Max x on the left is 0 - (dragbarw/2)
    d.x = Math.max(0, Math.min(d.x + this.width - (this.dragbarw / 2), d3.event.x));
    this.width = this.width + (oldx - d.x);
    this.dragbarleft
      .attr("x", (d) =>  return d.x - (this.dragbarw / 2); );

    this.dragrect
      .attr("x", (d) =>  return d.x; )
      .attr("width", this.width);

    this.dragbartop
      .attr("x", (d) =>  return d.x + (this.dragbarw/2); )
      .attr("width", this.width - this.dragbarw)
    this.dragbarbottom
      .attr("x", (d) =>  return d.x + (this.dragbarw/2); )
      .attr("width", this.width - this.dragbarw)
  ;

  rdragresize(d) 
    //Max x on the left is x - width
    //Max x on the right is width of screen + (dragbarw/2)
    let dragx = Math.max(d.x + (this.dragbarw/2), Math.min(this.w, d.x + this.width + d3.event.dx));

    //recalculate width
    this.width = dragx - d.x;

    //move the right drag handle
    this.dragbarright
      .attr("x", (d) =>  return dragx - (this.dragbarw/2) );

    //resize the drag rectangle
    //as we are only resizing from the right, the x coordinate does not need to change
    this.dragrect
      .attr("width", this.width);
    this.dragbartop
      .attr("width", this.width - this.dragbarw)
    this.dragbarbottom
      .attr("width", this.width - this.dragbarw)
  

  tdragresize(d) 

    let oldy = d.y;
    //Max x on the right is x + width - dragbarw
    //Max x on the left is 0 - (dragbarw/2)
    d.y = Math.max(0, Math.min(d.y + this.height - (this.dragbarw / 2), d3.event.y));
    this.height = this.height + (oldy - d.y);
    this.dragbartop
      .attr("y", (d) =>  return d.y - (this.dragbarw / 2); );

    this.dragrect
      .attr("y", (d) =>  return d.y; )
      .attr("height", this.height);

    this.dragbarleft
      .attr("y", (d) =>  return d.y + (this.dragbarw/2); )
      .attr("height", this.height - this.dragbarw);
    this.dragbarright
      .attr("y", (d) =>  return d.y + (this.dragbarw/2); )
      .attr("height", this.height - this.dragbarw);

  

  bdragresize(d) 
    //Max x on the left is x - width
    //Max x on the right is width of screen + (dragbarw/2)
    let dragy = Math.max(d.y + (this.dragbarw/2), Math.min(this.h, d.y + this.height + d3.event.dy));

    //recalculate width
    this.height = dragy - d.y;

    //move the right drag handle
    this.dragbarbottom
      .attr("y", (d) =>  return dragy - (this.dragbarw/2) );

    //resize the drag rectangle
    //as we are only resizing from the right, the x coordinate does not need to change
    this.dragrect
      .attr("height", this.height);
    this.dragbarleft
      .attr("height", this.height - this.dragbarw);
    this.dragbarright
      .attr("height", this.height - this.dragbarw);
  

【问题讨论】:

如果你能提供你的代码可运行的sn-p就好了。 也许这会对你有所帮助:***.com/questions/16265123/… 【参考方案1】:

可以在 Angular 中使用 ViewChild 访问子组件、指令或 DOM 元素来回答您的问题。

如果给定组件是您的子组件,那么您可以在 html 代码中添加一些引用变量,如下所示(此处为 #chartbar)

<div #chartbar class="someclass"></div>

现在您需要在子组件中使用 ViewChild

import  Component, OnInit, ViewChild, ElementRef from '@angular/core';  //Imported ViewChild, ElementRef
import * as d3 from 'd3';

@Component(
  selector: 'app-function-box',
  templateUrl: './function-box.component.html',
  styleUrls: ['./function-box.component.css']
)
export class FunctionBoxComponent implements OnInit 
  @ViewChild('chartbar') private chartContainer: ElementRef;  //Provider defined here

  constructor()  

  ngOnInit() 
  

  w = 500;
  h = 350;
  r = 120;

  const element = that.chartContainer.nativeElement;     //To use DOM element of html
  width = 200;
  height = 100;
  dragbarw = 10;

  svg = d3.select(element).append("svg")          //select DOM element instead of body
    .attr("width", this.w)
    .attr("height", this.h);

对于调整大小你会得到很好的选择here。

【讨论】:

以上是关于D3 svg 组件不可调整大小的主要内容,如果未能解决你的问题,请参考以下文章

D3 在调整大小窗口上更改 SVG 尺寸

d3js:Svg元素在更改窗口大小时未调整大小

d3.js Map (<svg>) 自动适应父容器并随窗口调整大小

调整全屏世界地图 D3JS 的大小

如何根据文本宽度动态调整 SVG 矩形的大小?

使D3堆积条形图填充父SVG容器