文章分類/Highcharts
Highcharts 做為一家專業圖表視覺化工具,在巨量資料的呈現,以及效能的表現,可算是佼佼者,並且在圖表上的視覺設定,或是需要客製化的部份,都有很多可以調整的設定,並在社群上可以找到大量的範例,不論是官方或是使用者,讓新進的使用者可以較快上手 Highcharts 的使用。
此次的範例為使用 Angular,並套用 HIghcharts 的方式建立多個 Charts ,可以讓數值進行同步顯示。
npm install highcharts highcharts-angular
在 Module 中加入 Highcharts 模組
import { HighchartsChartModule } from 'highcharts-angular'; @NgModule({ imports: [ ... HighchartsChartModule
在 Component 中加入 Highcharts 套件
import * as Highcharts from 'highcharts';
透過 ngFor 將多個 Chart Config 進行迴圈,呈現多組 Charts,並在最外層包一個 synchronizeTooltips 處理同步事件。
<div (mousemove)="synchronizeTooltips($event)"> <highcharts-chart [Highcharts]="Highcharts" style="width: 100%;display: block;margin:10px 0;" [options]="chartOption" *ngFor="let chartOption of chartOptions"> </highcharts-chart></div>
在 component 中將 Highcharts 實體化,並實作 synchronizeTooltips 的事件。
export class SyncHighchartComponent implements OnInit { Highcharts: typeof Highcharts = Highcharts; @Input() public chartOptions: Array = []; constructor() { } synchronizeTooltips = e => { for (let i = 0; i < Highcharts.charts.length; ++i) { if (!Highcharts.charts[i]) continue; let chart = Highcharts.charts[i]; let event = chart.pointer.normalize((e as (MouseEvent | PointerEvent | TouchEvent))); let point = undefined; for (let j = 0; j < chart.series.length && !point; ++j) { point = chart.series[j].searchPoint(event, true); } if (!point) return; if (e.type === "mousemove") { point.onMouseOver(); // console.log(chart.xAxis[0]); chart.xAxis[0].drawCrosshair(event, point); } else { point.onMouseOut(); chart.tooltip.hide(point); chart.xAxis[0].hideCrosshair(); } } }; ngOnInit(): void { } }
套用上面建立的 highcharts component,selector 為 app-sync-highchart,並將整理好的 chart config list 指給 input 參數。
<app-sync-highchart [chartOptions]="shortSeriesChartOption"></app-sync-highchart>
接著在程式中,整理好需要的設定值,像是 title、xAxis type、tooltip 等等的格式或樣式。
{ chart: { height: 200, zoomType: 'x', marginLeft: 40, // Keep all charts left aligned spacingTop: 20, spacingBottom: 20, className: "chart-short" }, loading: { hideDuration: 1000, showDuration: 1000 }, title: { text: 'CPU', align: 'left', margin: 0, x: 30, style: { fontSize: '18px' } }, credits: { enabled: false }, legend: { enabled: false }, plotOptions: { series: { stacking: 'normal', states: { inactive: { opacity: 1 } }, }, areaspline: { fillOpacity: 0.5 } }, xAxis: { crosshair: true, events: { setExtremes: function (e) { var thisChart = this.chart; if (e.trigger !== "syncExtremes") { // Prevent feedback loop Highcharts.each(Highcharts.charts, function (chart) { if (!chart) { return; } if (chart !== thisChart && chart.options.chart.className === thisChart.options.chart.className) { if (!chart) return; if (chart.xAxis[0].setExtremes) { // It is null while updating chart.xAxis[0].setExtremes(e.min, e.max, undefined, false, { trigger: "syncExtremes" }); } } }); } } }, labels: { format: '{value:%m-%d}' }, type: "datetime" }, yAxis: { title: { text: null } }, tooltip: { shared: true, positioner: function () { return { x: this.chart.chartWidth - 200, // right aligned y: 10 // align to title }; }, borderWidth: 0, backgroundColor: 'none', pointFormat: '{series.name}: {point.y}', headerFormat: '', shadow: false, style: { fontSize: '12px' }, valueDecimals: 2, valueSuffix: '%', }, series: series }
最重要是將資料放入到 series 設定中,也可以同步設定透明度、顏色、chart type 等等。
[ { "name": "bytes_recv", "type": "areaspline", "fillOpacity": 0.3, "data": [ [ 1659715260000, 0.08 ], [ 1659715320000, 0.04 ], [ 1659715380000, 0.04 ] ], "color": "#FAA50C" }, { "name": "bytes_sent", "type": "areaspline", "fillOpacity": 0.3, "data": [ [ 1659715260000, 0 ], [ 1659715320000, 0 ], [ 1659715380000, 0 ] ], "color": "#AB4BEB" } ]