Pull the Area chart primitive out of the LineChart component
This commit is contained in:
parent
ce8b9c42f2
commit
7512fcbf0a
|
@ -0,0 +1,13 @@
|
|||
<defs>
|
||||
<linearGradient x1="0" x2="0" y1="0" y2="1" class="{{this.colorClass}}" id="{{this.fillId}}">
|
||||
<stop class="start" offset="0%" />
|
||||
<stop class="end" offset="100%" />
|
||||
</linearGradient>
|
||||
<clipPath id="{{this.maskId}}">
|
||||
<path class="fill" d="{{this.area}}" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g class="area {{this.colorClass}}" ...attributes>
|
||||
<path class="line" d="{{this.line}}" />
|
||||
<rect class="fill" x="0" y="0" width="{{@width}}" height="{{@height}}" fill="url(#{{this.fillId}})" clip-path="url(#{{this.maskId}})" />
|
||||
</g>
|
|
@ -0,0 +1,37 @@
|
|||
import Component from '@glimmer/component';
|
||||
import { default as d3Shape, area, line } from 'd3-shape';
|
||||
import uniquely from 'nomad-ui/utils/properties/uniquely';
|
||||
|
||||
export default class ChartPrimitiveArea extends Component {
|
||||
get colorClass() {
|
||||
return this.args.colorClass || `${this.args.colorScale}-${this.args.index}`;
|
||||
}
|
||||
|
||||
@uniquely('area-mask') maskId;
|
||||
@uniquely('area-fill') fillId;
|
||||
|
||||
get line() {
|
||||
const { xScale, yScale, xProp, yProp, curveMethod } = this.args;
|
||||
|
||||
const builder = line()
|
||||
.curve(d3Shape[curveMethod])
|
||||
.defined(d => d[yProp] != null)
|
||||
.x(d => xScale(d[xProp]))
|
||||
.y(d => yScale(d[yProp]));
|
||||
|
||||
return builder(this.args.data);
|
||||
}
|
||||
|
||||
get area() {
|
||||
const { xScale, yScale, xProp, yProp, curveMethod } = this.args;
|
||||
|
||||
const builder = area()
|
||||
.curve(d3Shape[curveMethod])
|
||||
.defined(d => d[yProp] != null)
|
||||
.x(d => xScale(d[xProp]))
|
||||
.y0(yScale(0))
|
||||
.y1(d => yScale(d[yProp]));
|
||||
|
||||
return builder(this.args.data);
|
||||
}
|
||||
}
|
|
@ -4,14 +4,12 @@ import { computed } from '@ember/object';
|
|||
import { assert } from '@ember/debug';
|
||||
import { observes } from '@ember-decorators/object';
|
||||
import { computed as overridable } from 'ember-overridable-computed';
|
||||
import { guidFor } from '@ember/object/internals';
|
||||
import { run } from '@ember/runloop';
|
||||
import { htmlSafe } from '@ember/template';
|
||||
import d3 from 'd3-selection';
|
||||
import d3Scale from 'd3-scale';
|
||||
import d3Axis from 'd3-axis';
|
||||
import d3Array from 'd3-array';
|
||||
import d3Shape from 'd3-shape';
|
||||
import d3Format from 'd3-format';
|
||||
import d3TimeFormat from 'd3-time-format';
|
||||
import WindowResizable from 'nomad-ui/mixins/window-resizable';
|
||||
|
@ -73,16 +71,6 @@ export default class LineChart extends Component.extend(WindowResizable) {
|
|||
|
||||
isActive = false;
|
||||
|
||||
@computed()
|
||||
get fillId() {
|
||||
return `line-chart-fill-${guidFor(this)}`;
|
||||
}
|
||||
|
||||
@computed()
|
||||
get maskId() {
|
||||
return `line-chart-mask-${guidFor(this)}`;
|
||||
}
|
||||
|
||||
activeDatum = null;
|
||||
|
||||
@computed('activeDatum', 'timeseries', 'xProp')
|
||||
|
@ -252,35 +240,6 @@ export default class LineChart extends Component.extend(WindowResizable) {
|
|||
return this.width - this.yAxisWidth;
|
||||
}
|
||||
|
||||
@computed('data.[]', 'xScale', 'yScale', 'curveMethod')
|
||||
get line() {
|
||||
const { xScale, yScale, xProp, yProp, curveMethod } = this;
|
||||
|
||||
const line = d3Shape
|
||||
.line()
|
||||
.curve(d3Shape[curveMethod])
|
||||
.defined(d => d[yProp] != null)
|
||||
.x(d => xScale(d[xProp]))
|
||||
.y(d => yScale(d[yProp]));
|
||||
|
||||
return line(this.data);
|
||||
}
|
||||
|
||||
@computed('data.[]', 'xScale', 'yScale', 'curveMethod')
|
||||
get area() {
|
||||
const { xScale, yScale, xProp, yProp, curveMethod } = this;
|
||||
|
||||
const area = d3Shape
|
||||
.area()
|
||||
.curve(d3Shape[curveMethod])
|
||||
.defined(d => d[yProp] != null)
|
||||
.x(d => xScale(d[xProp]))
|
||||
.y0(yScale(0))
|
||||
.y1(d => yScale(d[yProp]));
|
||||
|
||||
return area(this.data);
|
||||
}
|
||||
|
||||
@computed('annotations.[]', 'xScale', 'xProp', 'timeseries')
|
||||
get processedAnnotations() {
|
||||
const { xScale, xProp, annotations, timeseries } = this;
|
||||
|
@ -319,7 +278,7 @@ export default class LineChart extends Component.extend(WindowResizable) {
|
|||
didInsertElement() {
|
||||
this.updateDimensions();
|
||||
|
||||
const canvas = d3.select(this.element.querySelector('.canvas'));
|
||||
const canvas = d3.select(this.element.querySelector('.hover-target'));
|
||||
const updateActiveDatum = this.updateActiveDatum.bind(this);
|
||||
|
||||
const chart = this;
|
||||
|
|
|
@ -14,16 +14,18 @@
|
|||
overflow: visible;
|
||||
}
|
||||
|
||||
.canvas {
|
||||
.line {
|
||||
fill: transparent;
|
||||
stroke-width: 1.25;
|
||||
}
|
||||
.hover-target {
|
||||
fill: transparent;
|
||||
stroke: transparent;
|
||||
}
|
||||
|
||||
.hover-target {
|
||||
fill: transparent;
|
||||
stroke: transparent;
|
||||
}
|
||||
.line {
|
||||
fill: transparent;
|
||||
stroke-width: 1.25;
|
||||
}
|
||||
|
||||
.area {
|
||||
fill: none;
|
||||
}
|
||||
|
||||
.axis {
|
||||
|
@ -60,7 +62,7 @@
|
|||
@each $name, $pair in $colors {
|
||||
$color: nth($pair, 1);
|
||||
|
||||
.canvas.is-#{$name} {
|
||||
.area.is-#{$name} {
|
||||
.line {
|
||||
stroke: $color;
|
||||
}
|
||||
|
|
|
@ -8,23 +8,20 @@
|
|||
and Y-axis values range from {{this.yRange.firstObject}} to {{this.yRange.lastObject}}.
|
||||
{{/if}}
|
||||
</description>
|
||||
<defs>
|
||||
<linearGradient x1="0" x2="0" y1="0" y2="1" class="{{this.chartClass}}" id="{{this.fillId}}">
|
||||
<stop class="start" offset="0%" />
|
||||
<stop class="end" offset="100%" />
|
||||
</linearGradient>
|
||||
<clipPath id="{{this.maskId}}">
|
||||
<path class="fill" d="{{this.area}}" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g class="y-gridlines gridlines" transform="translate({{this.yAxisOffset}}, 0)"></g>
|
||||
<g class="canvas {{this.chartClass}}">
|
||||
<path class="line" d="{{this.line}}" />
|
||||
<rect class="area" x="0" y="0" width="{{this.yAxisOffset}}" height="{{this.xAxisOffset}}" fill="url(#{{this.fillId}})" clip-path="url(#{{this.maskId}})" />
|
||||
<rect class="hover-target" x="0" y="0" width="{{this.yAxisOffset}}" height="{{this.xAxisOffset}}" />
|
||||
</g>
|
||||
<ChartPrimitives::Area
|
||||
@data={{this.data}}
|
||||
@colorClass={{this.chartClass}}
|
||||
@xScale={{this.xScale}}
|
||||
@yScale={{this.yScale}}
|
||||
@xProp={{this.xProp}}
|
||||
@yProp={{this.yProp}}
|
||||
@width={{this.yAxisOffset}}
|
||||
@height={{this.xAxisOffset}}
|
||||
@curveMethod={{this.curveMethod}} />
|
||||
<g aria-hidden="true" class="x-axis axis" transform="translate(0, {{this.xAxisOffset}})"></g>
|
||||
<g aria-hidden="true" class="y-axis axis" transform="translate({{this.yAxisOffset}}, 0)"></g>
|
||||
<rect class="hover-target" x="0" y="0" width="{{this.yAxisOffset}}" height="{{this.xAxisOffset}}" />
|
||||
</svg>
|
||||
<div data-test-annotations class="line-chart-annotations" style={{this.chartAnnotationsStyle}}>
|
||||
{{#each this.processedAnnotations key=this.annotationKey as |annotation|}}
|
||||
|
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.3 KiB |
Loading…
Reference in New Issue