ticks.length solves the Y axis bug.

This commit is contained in:
Cindy Chang
2024-06-17 22:32:57 +08:00
parent 541c0080aa
commit 7750f913a8
3 changed files with 173 additions and 23 deletions

View File

@@ -1,3 +1,4 @@
export const PRIME_VUE_TICKS_LIMIT = 6;
export const knownLayoutChartOption = {
padding: {
top: 16,

View File

@@ -1,5 +1,4 @@
import moment from 'moment';
const NUM_OF_PARTS_TO_SPLIT = 8;
const TOFIXED_DEICMAL = 1;
/**
@@ -8,11 +7,10 @@ const TOFIXED_DEICMAL = 1;
* @param {number} maxTimeInSecond
* @returns {object} {resultStepSize, unitToUse}
*/
export const getStepSizeOfYTicks = (maxTimeInSecond) => {
const numOfParts = NUM_OF_PARTS_TO_SPLIT;
export const getStepSizeOfYTicks = (maxTimeInSecond, numOfParts) => {
const {unitToUse, timeValue} = getTimeUnitAndValueToUse(maxTimeInSecond);
let resultStepSize;
resultStepSize = (timeValue / numOfParts);
resultStepSize = (timeValue * (1.125) / numOfParts);
return {resultStepSize, unitToUse};
}
@@ -30,17 +28,17 @@ const getTimeUnitAndValueToUse = (secondToDecide) => {
const hh = secondToDecide / hour;
const mm = secondToDecide / minutes;
if (dd > 0) {
if (dd > 0 && dd > 1) {
return {
unitToUse: "d",
timeValue: secondToDecide / day,
};
} else if (hh > 0) {
} else if (hh > 0 && hh > 1) {
return {
unitToUse: "h",
timeValue: secondToDecide / hour,
};
} else if (mm > 0) {
} else if (mm > 0 && mm > 1) {
console.log('mm > 0 && mm > 1', secondToDecide / minutes);
return {
unitToUse: "m",

View File

@@ -153,7 +153,9 @@ import { simpleTimeLabel, followTimeLabel, dateLabel,
getYTicksByIndex,
} from '@/module/timeLabel.js';
import FreqChart from './FreqChart.vue';
import { PRIME_VUE_TICKS_LIMIT } from '../../../constants/constants.js';
const primeVueTicksLimit = PRIME_VUE_TICKS_LIMIT;
const knownScaleLineChartOptions = {
x: {
type: 'time',
@@ -196,8 +198,7 @@ const knownScaleLineChartOptions = {
},
},
ticks:{
color: '#64748b',
padding: 8,
},
grid: {
color: '#64748b',
@@ -399,8 +400,7 @@ export default {
},
scales: customizedScaleOption,
};
// resultStepSize: Y 軸一個刻度的高度的純數值部分unitToUse則可能是 d,h,m,s 四者之一
const {resultStepSize, unitToUse} = getStepSizeOfYTicks(maxY);
switch (yUnit) {
case 'date':
primeVueSetOption.plugins.tooltip.callbacks.label = function(context) {
@@ -409,8 +409,12 @@ export default {
primeVueSetOption.scales.x.min = minX;
primeVueSetOption.scales.x.max = maxX;
primeVueSetOption.scales.y.ticks.callback = function (value, index, ticks) {
// resultStepSize: Y 軸一個刻度的高度的純數值部分unitToUse則可能是 d,h,m,s 四者之一
// ticks.length是動態由 PrimeVue 決定的,例如可能是 6 或是 8
const {resultStepSize, unitToUse} = getStepSizeOfYTicks(maxY, ticks.length);
return getYTicksByIndex(resultStepSize, index, unitToUse);
};
primeVueSetOption.scales.y.ticks.stepSize = resultStepSize;
break;
case 'count':
default:
@@ -526,6 +530,7 @@ export default {
ticks:{
color: '#64748b',
padding: 8,
},
grid: {
color: '#64748b',
@@ -628,6 +633,7 @@ export default {
ticks:{
color: '#64748b',
padding: 8,
},
grid: {
display:false,
@@ -755,12 +761,158 @@ export default {
return this.$moment(time).format('YYYY/M/D hh:mm:ss')
},
/**
* 建立Average Cycle Time折線圖
* 建立折線圖,其中設定值不是變數,避免同一個畫面中的設定值彼此覆蓋
* @param { object } chartData chart data
* @param { object } content titels 標題文字
* @param { string } yUnit y 軸單位 'date'
*/
getAvgCycleTimeLineChart(chartData, content, yUnit) {
getExplicitDeclaredLineChart(chartData, content, yUnit) {
const getMoment = (time)=> this.$moment(time).format('YYYY/M/D hh:mm:ss');
let datasets;
let minX = chartData.x_axis.min;
let maxX = chartData.x_axis.max;
let maxY = chartData.y_axis.max;
let xData;
let primeVueSetData = {};
let primeVueSetOption = {};
const getSimpleTimeLabel = simpleTimeLabel;
const getFollowTimeLabel = followTimeLabel;
datasets = setLineChartData(chartData.data, chartData.x_axis.max, chartData.x_axis.min, false, chartData.y_axis.max,
chartData.y_axis.min);
xData = this.setXLabelsData(chartData.x_axis);
// 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(xData, formatToSet);
primeVueSetData = {
labels: xData,
datasets: [
{
label: content.title,
data: datasets,
fill: false,
tension: 0, // 貝茲曲線張力
borderColor: '#0099FF',
}
]
};
primeVueSetOption = {
responsive: true,
maintainAspectRatio: false,
layout: {
padding: {
top: 16,
left: 8,
right: 8,
}
},
plugins: {
legend: false, // 圖例
tooltip: {
displayColors: false,
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: {
maxTicksLimit: primeVueTicksLimit,
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]
},
/**
* 建立Average Waiting Time折線圖
* @param { object } chartData chart data
* @param { object } content titels 標題文字
* @param { string } yUnit y 軸單位 'date'
*/
getAvgWaitingTimeLineChart(chartData, content, yUnit) {
const getMoment = (time)=> this.$moment(time).format('YYYY/M/D hh:mm:ss');
let datasets;
let minX = chartData.x_axis.min;
let maxX = chartData.x_axis.max;
@@ -810,7 +962,7 @@ export default {
titleFont: {weight: 'normal'},
callbacks: {
title: function(context) {
return `${content.x}: ${this.getMoment(context[0].parsed.x)}`;
return `${content.x}: ${getMoment(context[0].parsed.x)}`;
}
},
},
@@ -866,10 +1018,6 @@ export default {
},
text: content.y
},
ticks:{
color: '#64748b',
padding: 8,
},
grid: {
color: '#64748b',
},
@@ -877,15 +1025,18 @@ export default {
display: false, // 隱藏左側多出來的線
},
ticks: {
color: '#64748b',
padding: 8,
callback: function (value, index, ticks) {
// resultStepSize: Y 軸一個刻度的高度的純數值部分unitToUse則可能是 d,h,m,s 四者之一
const {resultStepSize, unitToUse} = getStepSizeOfYTicks(maxY);
const {resultStepSize, unitToUse} = getStepSizeOfYTicks(maxY, ticks.length);
return getYTicksByIndex(resultStepSize, index, unitToUse);
},
}
},
},
plugin: {
plugins: {
tooltip: {
callbacks:{
label:function(context) {
@@ -926,15 +1077,15 @@ export default {
}
this.casesByTaskHeight = await this.getHorizontalBarHeight(this.performanceData.freq.cases_by_task);
// create chart
[this.avgCycleTimeData, this.avgCycleTimeOptions] = this.getAvgCycleTimeLineChart(this.performanceData.time.avg_cycle_time,
[this.avgCycleTimeData, this.avgCycleTimeOptions] = this.getExplicitDeclaredLineChart(this.performanceData.time.avg_cycle_time,
this.contentData.avgCycleTime, 'date');
[this.avgCycleEfficiencyData, this.avgCycleEfficiencyOptions] = this.getBarChart(
this.performanceData.time.avg_cycle_efficiency, this.contentData.avgCycleEfficiency);
[this.avgProcessTimeData, this.avgProcessTimeOptions] = this.getLineChart(this.performanceData.time.avg_process_time,
[this.avgProcessTimeData, this.avgProcessTimeOptions] = this.getExplicitDeclaredLineChart(this.performanceData.time.avg_process_time,
this.contentData.avgProcessTime, 'date');
[this.avgProcessTimeByTaskData, this.avgProcessTimeByTaskOptions] = this.getHorizontalBarChart(
this.performanceData.time.avg_process_time_by_task, this.contentData.avgProcessTimeByTask, true, 'date');
[this.avgWaitingTimeData, this.avgWaitingTimeOptions] = this.getLineChart(
[this.avgWaitingTimeData, this.avgWaitingTimeOptions] = this.getExplicitDeclaredLineChart(
this.performanceData.time.avg_waiting_time, this.contentData.avgWaitingTime, 'date');
if(this.performanceData.time.avg_waiting_time_by_edge !== null) {
[this.avgWaitingTimeByEdgeData, this.avgWaitingTimeByEdgeOptions] = this.getHorizontalBarChart(