带有viewBox和preserveAspectRatio的响应式图表仪表板

时间:2018-12-19 15:10:58

标签: angular d3.js svg

我正在尝试使用D3制作的具有多个图表的仪表板。我的问题是,我似乎无法使图表响应并调整容器大小。

首先,仪表板的基本结构:

dashboard.html

<div id="graphs-container">
  <div class="widget-container">
    <div class="widget-container-header">
      Some text
    </div>
    <div class="widget-container-body big">
      <div class="spinner-container" *ngIf="!loopsByTruckAndHour">
        <mat-spinner></mat-spinner>
      </div>
      <div *ngIf="loopsByTruckAndHour">
        <app-linechart [data]="loopsByTruckAndHourData"
        xWIDTH="1100" xHEIGHT="450"></app-linechart>
      </div>
    </div>
  </div>

  <div class="widget-container grow1">
    <div class="widget-container-header">
      Some other text
    </div>
    <div class="widget-container-body medium">
      <div class="spinner-container" *ngIf="!productionByTruckAndHour">
        <mat-spinner></mat-spinner>
      </div>
      <div *ngIf="productionByTruckAndHour">
        <app-barchart [data]="productionByTruckAndHourData"></app-barchart>
      </div>
    </div>
  </div>
{...}
</div>

dashboard.css

#graphs-container {
    background-color: #ffffff;
    display: flex;
    flex-wrap: wrap;
    justify-content: space-evenly;
}
.small {
    max-width: 400px;
}

.medium {
    max-width: 450px;
}

.medium-table {
    max-width: 500px;
}
.medium-big {
    min-width: 500px;
    max-width: 1000px;
}

.big {
    min-width: 700px;
    max-width: 1100px;
}

.widget-container {
    margin: 10px;
    flex-grow: 1;
    -webkit-box-shadow: 0px 2px 10px 4px rgba(230,230,230,1);
    -moz-box-shadow: 0px 2px 10px 4px rgba(230,230,230,1);
    box-shadow: 0px 2px 10px 4px rgba(230,230,230,1);
    border-radius: 0px 0px 8px 8px;
    border: 1px solid #e6e6e6;
}

.widget-container-header {
    background-color: #E6E6E6;
    color: #3F3F3F;
    font-family: 'Open Sans';
    font-size: 1.08vw;
    padding: 0.2rem 0rem 0.2rem 1rem;
}

.widget-container-body {
    padding: 10px;
    font-family: 'Open Sans';
    max-height: 450px !important;
}

在这里,我试图使用Flexbox显示所有不同的小部件或图表,以便它们在屏幕中进行组织。每个小部件的最大高度为450像素,我根据每个小部件应具有的大小为它们设置了max-width,并为每个小部件设置了flex-grow: 1,以便它们很好地填充屏幕,而不要不要在两者之间留出空白。

现在,到现在为止,一切正常。问题来自图表和SVG。

我的仪表板中有不同类型的图表,例如折线图和条形图,因此每种图表都是一个Angular组件,您将数据传递给该Angular组件,并且它会用{{1}呈现一个<div> }放在图表中。

由于我希望这是响应性的,因此我的d3图表是使用svgviewBox制作的,并且组件具有preserveAspectRatioxWIDTH属性以在构建svg,这将有助于设置宽度和高度之间的比率(例如,并非每个折线图都必须具有相同的宽度)。

对我的图表组件的一些引用:

xHEIGHT

linechart.component.ts

div_id = '_' + Math.random().toString(36).substr(2, 9); @Input() data; @Input() xWIDTH: number = 800; // default value @Input() xHEIGHT: number = 300; margin = { left: this.xWIDTH / 16, top: this.xHEIGHT / 8, bottom: this.xHEIGHT / 8, right: this.xWIDTH / 80 } width = this.xWIDTH - this.margin.left - this.margin.right; height = this.xHEIGHT - this.margin.top - this.margin.bottom; drawChart() { const svg = d3.select(`#${this.div_id}`) .append('svg') .attr("width", '100%') .attr("height", '100%') .attr('viewBox', `0 0 ${this.xWIDTH} ${this.xHEIGHT}`) .attr('preserveAspectRatio', 'xMinYMin meet') .append('g') .attr('transform', `translate(${this.margin.left},${this.margin.top})`); // make the rest of the chart }

linechart.component.html

我的问题是:我的<div [attr.id]="div_id"> </div> 元素保持宽高比,但是当我给组件提供{{1}的较小值时,内部的SVG元素并没有尊重其父SVG元素的大小。 }和<g>xWIDTH元素非常大,然后xHEIGHTg的值很大,比xWIDTH元素小得多。我怎样才能解决这个问题?如何使xHEIGHTSVG元素适应其父容器?

此外,SVGg似乎无视其父母的SVG,有时他们只是在容器外生长。

两张图像可能有助于了解正在发生的事情: https://i.imgur.com/yq9BJWX.png https://i.imgur.com/fbGqDXM.png

0 个答案:

没有答案