diff --git a/src/views/Compare/Dashboard/index.vue b/src/views/Compare/Dashboard/index.vue index dc33a78..72df81c 100644 --- a/src/views/Compare/Dashboard/index.vue +++ b/src/views/Compare/Dashboard/index.vue @@ -406,8 +406,8 @@ export default { }; primeVueSetOption.scales.x.min = minX; primeVueSetOption.scales.x.max = maxX; - const {resultStepSize: YTickStepSize, unitToUse} = getStepSizeOfYTicks(maxY); // Stepsize only needs to be calculated once primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) { + const {resultStepSize: YTickStepSize, unitToUse} = getStepSizeOfYTicks(maxY, ticks.length); // Stepsize only needs to be calculated once return getYTicksByIndex(YTickStepSize, index, unitToUse); } break; @@ -738,6 +738,178 @@ export default { }, }; }, + /** + * 建立Compare頁面的折線圖,並且避免同一個畫面中的設定值彼此覆蓋 + * @param { object } chartData chart data + * @param { object } content titels 標題文字 + * @param { string } yUnit y 軸單位 'date' | 'count',可傳入以上任一。 + * @returns { [primeVueSetData, primeVueSetOption] } 這兩者為符合 primeVue 圖表格式的數據資料 + */ + getLineChart(chartData, content, yUnit) { + let datasetsPrimary; + let datasetsSecondary; + let minX = chartData.x_axis.min; + let maxX = chartData.x_axis.max; + let maxY = chartData.y_axis.max; + let xLabelData; + let labelPrimary = chartData.data[0].label; + let labelSecondary = chartData.data[1].label; + let primeVueSetData = {}; + let primeVueSetOption = {}; + const getMoment = (time)=> { + return this.$moment(time).format('YYYY/M/D hh:mm:ss') + }; + const getSimpleTimeLabel = simpleTimeLabel; + const getFollowTimeLabel = followTimeLabel; + + // fabricate x label according to y unit + switch (yUnit) { + case 'date': + datasetsPrimary = setLineChartData(chartData.data[0].data, chartData.x_axis.max, chartData.x_axis.min, false, + chartData.y_axis.max, chartData.y_axis.min); + datasetsSecondary = setLineChartData(chartData.data[1].data, chartData.x_axis.max, chartData.x_axis.min, false, + chartData.y_axis.max, chartData.y_axis.min); + xLabelData = this.setXLabelsData(chartData.x_axis); + break; + case 'count': // 次數 10 個點 + datasetsPrimary = chartData.data[0].data; + datasetsSecondary = chartData.data[1].data; + xLabelData = chartData.data[0].data.map(item => new Date(item.x).getTime()); + break; + } + + // Customize X axis ticks due to different differences between min and max of data group + // Compare page and Performance page share the same logic + const formatToSet = setTimeStringFormatBaseOnTimeDifference(minX, maxX); + const ticksOfXAxis = mapTimestampToAxisTicksByFormat(xLabelData, formatToSet); + + primeVueSetData = { + labels: xLabelData, + datasets: [ + { + label: labelPrimary, + data: datasetsPrimary, + fill: false, + tension: 0, // 貝茲曲線張力 + borderColor: this.colorPrimary, + pointBackgroundColor: this.colorPrimary, + }, + { + label: labelSecondary, + data: datasetsSecondary, + fill: false, + tension: 0, // 貝茲曲線張力 + borderColor: this.colorSecondary, + pointBackgroundColor: this.colorSecondary, + } + ] + }; + primeVueSetOption = { + responsive: true, + maintainAspectRatio: false, + layout: { + padding: { + top: 16, + left: 8, + right: 8, + } + }, + plugins: { + legend: false, // 圖例 + tooltip: { + // displayColors: false, + mode: 'index', + titleFont: {weight: 'normal'}, + callbacks: { + title: function(context) { + return `${content.x}: ${getMoment(context[0].parsed.x)}`; + }, + }, + }, + title: { + display: false, + }, + }, + scales: { + x: { + min: minX, + max: maxX, + type: 'time', + title: { + display: true, + color: '#334155', + font: { + size: 12, + lineHeight: 2 + }, + text: content.x, + }, + time: { + displayFormats: { + second: 'h:mm:ss', // ex: 1:11:11 + minute: 'M/d h:mm', // ex: 1/1 1:11 + hour: 'M/d h:mm', // ex: 1/1 1:11 + day: 'M/d h', // ex: 1/1 1 + month: 'y/M/d', // ex: 1911/1/1 + }, + round: true + }, + ticks: { + padding: 8, + display: true, + maxRotation: 0, // 不旋轉 lable 0~50 + color: '#64748b', + source: 'labels', // 依比例彈性顯示 label 數量 + callback: function(value, index) { + return ticksOfXAxis[index]; + }, + }, + border: { + color: '#64748b', + }, + }, + y: { + beginAtZero: true, // scale 包含 0 + title: { + display: true, + color: '#334155', + font: { + size: 12, + lineHeight: 2 + }, + text: content.y + }, + grid: { + color: '#64748b', + }, + border: { + display: false, // 隱藏左側多出來的線 + }, + ticks: { + + color: '#64748b', + padding: 8, + callback: function (value, index, ticks) { + // resultStepSize: Y 軸一個刻度的高度的純數值部分,unitToUse則可能是 d,h,m,s 四者之一 + const {resultStepSize, unitToUse} = getStepSizeOfYTicks(maxY, ticks.length); + return getYTicksByIndex(resultStepSize, index, unitToUse); + }, + } + }, + }, + plugins: { + tooltip: { + callbacks:{ + label:function(context) { + return `${content.y}: ${getSimpleTimeLabel(context.parsed.y, 2)}`; + }, + }, + }, + }, + }; + + return [primeVueSetData, primeVueSetOption]; + }, }, async created() { this.isLoading = true; // moubeted 才停止 loading diff --git a/src/views/Discover/Performance/index.vue b/src/views/Discover/Performance/index.vue index 1dfb35a..8e2d2fc 100644 --- a/src/views/Discover/Performance/index.vue +++ b/src/views/Discover/Performance/index.vue @@ -761,7 +761,7 @@ export default { return this.$moment(time).format('YYYY/M/D hh:mm:ss') }, /** - * 建立折線圖,其中設定值不是變數,避免同一個畫面中的設定值彼此覆蓋 + * 建立Performance頁面的折線圖,並且避免同一個畫面中的設定值彼此覆蓋 * @param { object } chartData chart data * @param { object } content titels 標題文字 * @param { string } yUnit y 軸單位 'date'