Created
April 17, 2019 07:07
-
-
Save cahyowhy/ffdd1ca7250291db6ece5ea8ad975f41 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!--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