DemuMesDataV/src/mixins/axisMixin.js

435 lines
12 KiB
JavaScript
Raw Normal View History

2018-12-20 18:25:49 +08:00
export default {
data () {
return {
defaultHorizon: false,
defaultXAxisFS: 10,
defaultYAxisFS: 10,
defaultXOffset: 30,
defaultRotateAngel: 30,
defaultXAxisLineColor: 'rgba(255, 255, 255, 0.3)',
defaultYAxisLineColor: 'rgba(255, 255, 255, 0.3)',
2018-12-20 22:36:22 +08:00
defaultGridColor: 'rgba(255, 255, 255, 0.3)',
defaultGridType: 'line',
2018-12-21 14:46:55 +08:00
defaultAxisLabelGap: 5,
2018-12-20 18:25:49 +08:00
horizon: false,
// user data's max and min value
valueMaxMin: [],
// axis's max and min value
axisMaxMin: [],
// label's max width where x and y Axis
labelXYMaxWidth: [],
valueAxisTag: [],
labelAxisTag: [],
xyAxisFS: [],
xyAxisUnitWidth: [],
axisMargin: [],
axisOriginPos: [],
axisWH: [],
valueTagPos: [],
labelTagPos: [],
2018-12-21 14:46:55 +08:00
labelAxisPos: [],
2018-12-20 18:25:49 +08:00
valueTagGap: 0,
labelTagGap: 0,
xTagColor: '',
yTagColor: '',
xTagColorMul: false,
2018-12-20 22:36:22 +08:00
yTagColorMul: false,
xGridColor: '',
yGridColor: '',
xGridColorMul: false,
yGridColorMul: false
2018-12-20 18:25:49 +08:00
}
},
methods: {
initAxis () {
const { calcMaxMinValue, calcValueAxisTag, calcLabelAxisTag, calcXYAxisFS } = this
calcMaxMinValue()
calcValueAxisTag()
calcLabelAxisTag()
calcXYAxisFS()
const { calcXYLabelMaxWidth, calcAxisMargin, calcAxisOriginPos } = this
calcXYLabelMaxWidth()
calcAxisMargin()
calcAxisOriginPos()
2018-12-20 22:36:22 +08:00
const { calcAxisWH, calcValueTagPos, calcLabelTagPos, calcTagGap, calcTagColor, calcGridColor } = this
2018-12-20 18:25:49 +08:00
calcAxisWH()
calcValueTagPos()
calcLabelTagPos()
calcTagGap()
calcTagColor()
2018-12-20 22:36:22 +08:00
calcGridColor()
2018-12-20 18:25:49 +08:00
},
calcMaxMinValue () {
const { data: { data }, multipleSum, filterNull, getArrayMaxMin } = this
2018-12-20 22:36:22 +08:00
const valueData = data.map(item => item.data)
const trueValue = valueData.map(item =>
2018-12-20 18:25:49 +08:00
item.map(v =>
v ? (typeof v === 'number' ? v : multipleSum(...filterNull(v))) : false))
this.valueMaxMin = getArrayMaxMin(trueValue)
},
calcValueAxisTag () {
const { valueMaxMin: [ valueMax, valueMin ], data, defaultHorizon } = this
const { horizon } = data
this.horizon = horizon || defaultHorizon
let { max, min, num, fixed } = data[horizon ? 'x' : 'y']
let [trueMax, trueMin] = [max, min]
const thirdValueMinus = parseInt((valueMax - valueMin) / 3)
!max && (max !== 0) && (trueMax = valueMax + thirdValueMinus)
!min && (min !== 0) && (trueMin = valueMin - thirdValueMinus)
const trueMinus = trueMax - trueMin
!num && trueMinus < 9 && (num = trueMinus + 1)
!num && (num = 10)
const valueGap = trueMinus / (num - 1)
const valueAxisTag = this.valueAxisTag = Array(num).fill(0).map((t, i) =>
(trueMin + i * valueGap).toFixed(fixed))
const lastValueAxisTagIndex = valueAxisTag.length - 1
this.axisMaxMin = [parseFloat(valueAxisTag[lastValueAxisTagIndex]), parseFloat(valueAxisTag[0])]
},
calcLabelAxisTag () {
const { data, horizon } = this
this.labelAxisTag = data[horizon ? 'y' : 'x'].data
},
calcXYAxisFS () {
const { defaultXAxisFS, defaultYAxisFS } = this
const { data: { x: { fontSize: xfs }, y: { fontSize: yfs } } } = this
this.xyAxisFS = [xfs || defaultXAxisFS, yfs || defaultYAxisFS]
},
calcXYLabelMaxWidth () {
const { ctx, valueAxisTag, labelAxisTag, horizon, xyAxisFS } = this
const { canvas: { getTextsWidth } } = this
const { data: { x: { unit: xUN }, y: { unit: yUN } } } = this
ctx.font = `${xyAxisFS[0]}px Arial`
2018-12-21 14:46:55 +08:00
this.labelXYMaxWidth[0] = Math.max(...getTextsWidth(ctx, horizon ? valueAxisTag : labelAxisTag))
2018-12-20 18:25:49 +08:00
this.xyAxisUnitWidth[0] = ctx.measureText(xUN || '').width
ctx.font = `${xyAxisFS[1]}px Arial`
2018-12-21 14:46:55 +08:00
this.labelXYMaxWidth[1] = Math.max(...getTextsWidth(ctx, horizon ? labelAxisTag : valueAxisTag))
2018-12-20 18:25:49 +08:00
this.xyAxisUnitWidth[1] = ctx.measureText(yUN || '').width
},
calcAxisMargin () {
const { defaultXOffset, labelXYMaxWidth, data, xyAxisUnitWidth } = this
const { offset: xOF, unitWidth: xUW } = data.x
const { offset: yOF, unitHeight: yUH } = data.y
this.axisMargin[0] = yUH || defaultXOffset
this.axisMargin[1] = xUW || xyAxisUnitWidth[0] + 10
this.axisMargin[2] = xOF || defaultXOffset
this.axisMargin[3] = yOF || labelXYMaxWidth[1] + 10
},
calcAxisOriginPos () {
const { axisMargin, canvasWH } = this
this.axisOriginPos[0] = axisMargin[3]
this.axisOriginPos[1] = canvasWH[1] - axisMargin[2]
},
calcAxisWH () {
const { axisMargin, canvasWH } = this
this.axisWH[0] = canvasWH[0] - axisMargin[1] - axisMargin[3]
this.axisWH[1] = canvasWH[1] - axisMargin[0] - axisMargin[2]
},
calcValueTagPos () {
const { axisWH, valueAxisTag, horizon, axisOriginPos: [x, y] } = this
const valueTagNum = valueAxisTag.length
const gapWidth = (horizon ? axisWH[0] : axisWH[1]) / (valueTagNum - 1)
this.valueTagPos = new Array(valueTagNum).fill(0).map((t, i) =>
horizon ? [x + gapWidth * i, y + 5] : [x - 5, y - gapWidth * i])
},
calcLabelTagPos () {
2018-12-21 14:46:55 +08:00
const { axisWH, labelAxisTag, horizon, axisOriginPos: [x, y], data } = this
const { defaultAxisLabelGap, axisType } = this
2018-12-20 18:25:49 +08:00
const { boundaryGap } = data
const labelNum = labelAxisTag.length
const gapAllWidth = horizon ? axisWH[1] : axisWH[0]
const tempArray = new Array(labelNum).fill(0)
if (axisType === 'column' || (axisType === 'line' && boundaryGap)) {
const gapWidth = gapAllWidth / labelNum
const halfGapWidth = gapWidth / 2
2018-12-21 14:46:55 +08:00
this.labelAxisPos = tempArray.map((t, i) =>
horizon ? [x, y - gapWidth * i - halfGapWidth]
: [x + gapWidth * i + halfGapWidth, y])
2018-12-20 18:25:49 +08:00
this.labelTagPos = tempArray.map((t, i) =>
2018-12-21 14:46:55 +08:00
horizon ? [x - defaultAxisLabelGap, y - gapWidth * i - halfGapWidth]
: [x + gapWidth * i + halfGapWidth, y + defaultAxisLabelGap])
2018-12-20 18:25:49 +08:00
}
if (axisType === 'line' && !boundaryGap) {
const gapWidth = gapAllWidth / (labelNum - 1)
2018-12-21 14:46:55 +08:00
this.labelAxisPos = tempArray.map((t, i) =>
horizon ? [x, y - gapWidth]
: [x + gapWidth * i, y])
2018-12-20 18:25:49 +08:00
this.labelTagPos = tempArray.map((t, i) =>
2018-12-21 14:46:55 +08:00
horizon ? [x - defaultAxisLabelGap, y - gapWidth]
: [x + gapWidth * i, y + defaultAxisLabelGap])
2018-12-20 18:25:49 +08:00
}
},
calcTagGap () {
const { horizon, valueTagPos, labelTagPos } = this
const v = horizon ? '0' : '1'
this.valueTagGap = Math.abs(valueTagPos[0][v] - valueTagPos[1][v])
const l = horizon ? '1' : '0'
this.labelTagGap = Math.abs(labelTagPos[0][l] - labelTagPos[1][l])
},
calcTagColor () {
const { defaultXAxisLineColor, defaultYAxisLineColor, drawColors, data } = this
const { x: { color: xc }, y: { color: yc } } = data
let xTagColor = xc || defaultXAxisLineColor
xTagColor === 'colors' && (xTagColor = drawColors)
let yTagColor = yc || defaultYAxisLineColor
yTagColor === 'colors' && (yTagColor = drawColors)
this.xTagColor = xTagColor
this.xTagColorMul = xTagColor instanceof Array
this.yTagColor = yTagColor
this.yTagColorMul = yTagColor instanceof Array
},
2018-12-20 22:36:22 +08:00
calcGridColor () {
const { drawColors, data, defaultGridColor } = this
const { x: { gridColor: xgc }, y: { gridColor: ygc } } = data
let xGridColor = xgc || defaultGridColor
let yGridColor = ygc || defaultGridColor
xGridColor === 'colors' && (xGridColor = drawColors)
yGridColor === 'colors' && (yGridColor = drawColors)
this.xGridColor = xGridColor
this.yGridColor = yGridColor
this.xGridColorMul = xGridColor instanceof Array
this.yGridColorMul = yGridColor instanceof Array
},
2018-12-20 18:25:49 +08:00
drawAxis () {
2018-12-21 14:46:55 +08:00
const { drawAxisLine, drawAxisTag, drawUnit, drawGrid } = this
2018-12-20 18:25:49 +08:00
drawAxisLine()
drawAxisTag()
2018-12-20 22:36:22 +08:00
2018-12-21 14:46:55 +08:00
drawUnit()
2018-12-20 22:36:22 +08:00
drawGrid()
2018-12-20 18:25:49 +08:00
},
drawAxisLine () {
const { ctx, defaultXAxisLineColor, defaultYAxisLineColor, axisOriginPos, axisWH, data } = this
2018-12-21 14:46:55 +08:00
const { x: { lineColor: xlc, noAxisLine: xNAL }, y: { lineColor: ylc, noAxisLine: yNAL } } = data
2018-12-20 18:25:49 +08:00
2018-12-21 14:46:55 +08:00
if (xNAL && yNAL) return
2018-12-20 18:25:49 +08:00
2018-12-21 14:46:55 +08:00
ctx.lineWidth = 1
2018-12-20 18:25:49 +08:00
2018-12-21 14:46:55 +08:00
if (!xNAL) {
ctx.strokeStyle = xlc || defaultXAxisLineColor
ctx.beginPath()
ctx.moveTo(...axisOriginPos)
ctx.lineTo(axisOriginPos[0] + axisWH[0], axisOriginPos[1])
ctx.stroke()
}
2018-12-20 18:25:49 +08:00
2018-12-21 14:46:55 +08:00
if (!yNAL) {
ctx.strokeStyle = ylc || defaultYAxisLineColor
ctx.beginPath()
ctx.moveTo(...axisOriginPos)
ctx.lineTo(axisOriginPos[0], axisOriginPos[1] - axisWH[1])
ctx.stroke()
}
2018-12-20 18:25:49 +08:00
},
drawAxisTag () {
const { ctx, horizon, valueTagPos, labelTagPos, valueAxisTag, labelAxisTag } = this
const { xTagColor, xTagColorMul, yTagColor, yTagColorMul, xyAxisFS } = this
2018-12-21 14:46:55 +08:00
const { data: { x: { noAxisTag: xNAT, rotate }, y: { noAxisTag: yNAT } } } = this
if (xNAT && yNAT) return
2018-12-20 18:25:49 +08:00
const xAxisData = horizon ? valueTagPos : labelTagPos
const yAxisData = horizon ? labelTagPos : valueTagPos
const xTagData = horizon ? valueAxisTag : labelAxisTag
const yTagData = horizon ? labelAxisTag : valueAxisTag
!xTagColorMul && (ctx.fillStyle = xTagColor)
const xTagColorNum = xTagColor.length
ctx.font = `${xyAxisFS[0]}px Arial`
ctx.textAlign = 'center'
ctx.textBaseline = 'top'
2018-12-21 14:46:55 +08:00
if (rotate) ctx.textAlign = 'left'
!xNAT && xAxisData.forEach((pos, i) => {
if (!xTagData[i]) return
if (rotate) {
ctx.save()
ctx.translate(...pos)
ctx.rotate(Math.PI / 4)
}
2018-12-20 18:25:49 +08:00
xTagColorMul && (ctx.fillStyle = xTagColor[i % xTagColorNum])
2018-12-21 14:46:55 +08:00
ctx.fillText(xTagData[i], ...(rotate ? [0, 0] : pos))
if (rotate) ctx.restore()
2018-12-20 18:25:49 +08:00
})
!yTagColorMul && (ctx.fillStyle = yTagColor)
const yTagColorNum = yTagColor.length
ctx.font = `${xyAxisFS[1]}px Arial`
ctx.textAlign = 'right'
ctx.textBaseline = 'middle'
2018-12-21 14:46:55 +08:00
!yNAT && yAxisData.forEach((pos, i) => {
if (!yTagData[i]) return
2018-12-20 18:25:49 +08:00
xTagColorMul && (ctx.fillStyle = yTagColor[i % yTagColorNum])
ctx.fillText(yTagData[i], ...pos)
})
this.ctx.fill()
2018-12-20 22:36:22 +08:00
},
2018-12-21 14:46:55 +08:00
drawUnit () {
const { ctx, data, axisOriginPos, canvasWH, defaultAxisLabelGap } = this
const { x: { unit: xUN, fontSize: xFS }, y: { unit: yUN, fontSize: yFS } } = data
ctx.font = `${xFS}px Arial`
ctx.textAlign = 'right'
ctx.textBaseline = 'top'
ctx.fillText(xUN || '', canvasWH[0], axisOriginPos[1] + defaultAxisLabelGap)
ctx.font = `${yFS}px Arial`
ctx.fillText(yUN || '', axisOriginPos[0], 0)
},
2018-12-20 22:36:22 +08:00
drawGrid () {
const { horizon, labelTagPos, valueTagPos, axisOriginPos, ctx, data, axisWH } = this
const { xGridColor, xGridColorMul, yGridColor, yGridColorMul, axisType } = this
const { x: { grid: xG, gridType: xT }, y: { grid: yG, gridType: yT }, boundaryGap } = data
const xAxisData = horizon ? valueTagPos : labelTagPos
const yAxisData = horizon ? labelTagPos : valueTagPos
ctx.lineWidth = 1
!xGridColorMul && (ctx.strokeStyle = xGridColor)
const xGridColorNum = xGridColor.length
ctx.setLineDash(xT === 'dashed' ? [5, 5] : [10, 0])
xG && xAxisData.forEach(([x, y], i) => {
xGridColorMul && (ctx.strokeStyle = xGridColor[i % xGridColorNum])
if (!horizon && i === 0 && axisType === 'line' && !boundaryGap) return
if (horizon && i === 0) return
ctx.beginPath()
ctx.moveTo(x, axisOriginPos[1])
ctx.lineTo(x, axisOriginPos[1] - axisWH[1])
ctx.stroke()
})
!yGridColorMul && (ctx.strokeStyle = yGridColor)
const yGridColorNum = yGridColor.length
ctx.setLineDash(yT === 'dashed' ? [5, 5] : [10, 0])
yG && yAxisData.forEach(([x, y], i) => {
yGridColorMul && (ctx.strokeStyle = yGridColor[i % yGridColorNum])
if (!horizon && i === 0) return
if (horizon && i === 0 && axisType === 'line' && !boundaryGap) return
ctx.beginPath()
ctx.moveTo(axisOriginPos[0], y)
ctx.lineTo(axisOriginPos[0] + axisWH[0], y)
ctx.stroke()
})
2018-12-20 18:25:49 +08:00
}
}
}