Skip to content

Instantly share code, notes, and snippets.

@cahyowhy
Created April 17, 2019 07:07
Show Gist options
  • Save cahyowhy/ffdd1ca7250291db6ece5ea8ad975f41 to your computer and use it in GitHub Desktop.
Save cahyowhy/ffdd1ca7250291db6ece5ea8ad975f41 to your computer and use it in GitHub Desktop.
<!--suppress ALL -->
<template>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" :view-box.camel="viewBox" :style="style">
<defs>
<slot></slot>
</defs>
<g :style="stageStyle">
<d3-axis v-if="displayAxis" v-for="(axis, index) in axisPosition" :key="`axis-${index}`"
:axis="axis" :layout="layout" :scale="scale">
</d3-axis>
<g v-for="(seriesData, index) in chartData"
:key="'series-'+index">
<rect v-if="showBackground" width="500px" height="250px" :fill="backgroundColor"></rect>
<d3-line-area v-if="displayArea" type="area" :layout="layout" :lineAreaStyle="lineAreaStyle"
:series-data="seriesData" :scale="scale" :xAxisKey="xAxisKey" :yAxisKey="yAxisKey"
:lineAreaColor="lineAreaColor">
</d3-line-area>
<d3-line-area :scale="scale" :yAxisKey="yAxisKey" :xAxisKey="xAxisKey"
:layout="layout" :series-data="seriesData">
</d3-line-area>
<d3-scatter v-if="displayScatter" :layout="layout" :series-data="seriesData"
:scale="scale" :xAxisKey="xAxisKey" :yAxisKey="yAxisKey" :pointStyle="pointStyle">
</d3-scatter>
</g>
</g>
</svg>
</template>
<script lang="ts">
import {Component, Prop, Vue, Watch} from '../../../common/Annotation';
import {maxBy, minBy} from 'lodash';
@Component
export default class D3LineChart extends Vue {
@Prop({default: [], type: Array})
public chartData: Array<any>;
@Prop({default: ['left', 'bottom']})
public axisPosition: Array<any>;
@Prop({default: true, type: Boolean})
public displayArea: boolean;
@Prop({default: true, type: Boolean})
public displayScatter: boolean;
@Prop({default: true, type: Boolean})
public displayAxis: boolean;
@Prop({default: false, type: Boolean})
public showBackground: boolean;
@Prop({default: '#F99034', type: String})
public backgroundColor: string;
@Prop({type: String})
public lineAreaColor: string;
@Prop({default: 'timestamp', type: String})
public xAxisKey: string;
@Prop({default: 'value', type: String})
public yAxisKey: string;
@Prop({
default: {
width: 700, height: 350,
marginTop: 30, marginRight: 30,
marginBottom: 30, marginLeft: 30,
},
type: Object
})
public layout: any;
@Prop({default: {}, type: Object})
public lineAreaStyle: any;
@Prop({default: {}, type: Object})
public pointStyle: any;
public scale: any = {};
@Watch('layout', {deep: true})
public onLayoutChange() {
this.scale.x = this.getScaleX();
this.scale.y = this.getScaleY();
}
@Watch('chartData', {deep: true})
public onChartDataChange() {
this.scale.x = this.getScaleX();
this.scale.y = this.getScaleY();
}
public get domainValues() {
let datas = this.chartData.reduce((accu, item) => {
return accu.concat(item.values || []);
}, []);
let maxYAxis = maxBy(datas, this.yAxisKey);
let minYAxis = minBy(datas, this.yAxisKey);
let maxXAxis = maxBy(datas, this.xAxisKey);
let minXAxis = minBy(datas, this.xAxisKey);
const valMaxYAxis = ((maxYAxis && maxYAxis[this.yAxisKey]) || 0);
const valMinYAxis = ((minYAxis && minYAxis[this.yAxisKey]) || 0);
const valMaxXAxis = ((maxXAxis && maxXAxis[this.xAxisKey]) || 0);
const valMinXAxis = ((minXAxis && minXAxis[this.xAxisKey]) || 0);
return {
x: [valMinXAxis, valMaxXAxis],
y: [valMinYAxis, valMaxYAxis],
};
}
public get viewBox() {
let {layout} = this;
if (layout.width && layout.height && layout.marginTop && layout.marginLeft && layout.marginBottom && layout.marginRight) {
let outerWidth = layout.width + layout.marginLeft + layout.marginRight,
outerHeight = layout.height + layout.marginTop + layout.marginBottom;
return '0 0 ' + outerWidth + ' ' + outerHeight;
}
return '0 0';
}
public get style() {
const {layout} = this;
if (layout.width && layout.height && layout.marginTop && layout.marginLeft && layout.marginBottom && layout.marginRight) {
return {
width: layout.width + layout.marginLeft + layout.marginRight,
height: layout.height + layout.marginTop + layout.marginTop
}
}
return '';
}
public get stageStyle() {
let {layout} = this;
if (layout.marginLeft && layout.marginTop) {
return {
'transform': 'translate(' + layout.marginLeft + 'px,' + layout.marginTop + 'px)'
}
}
return {};
}
public created() {
this.scale = {
x: this.getScaleX(), y: this.getScaleY(),
color: (window as any).d3.scaleOrdinal().range(['#ff3860', '#ffdd57', '#23d160', '#209cee', '#3273dc', '#00d1b2'])
};
}
public getScaleX() {
const x = (window as any).d3.scaleTime().range([0, this.layout.width]);
x.domain(this.domainValues.x);
return x;
}
public getScaleY() {
const y = (window as any).d3.scaleLinear().range([this.layout.height, 0]);
y.domain(this.domainValues.y);
return y;
}
}
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment