abtract label line component
This commit is contained in:
parent
4ea8a84ba4
commit
f8c2ada869
|
@ -7,14 +7,7 @@
|
|||
<canvas :ref="ref" />
|
||||
</div>
|
||||
|
||||
<div class="label-line">
|
||||
<div class="label-item"
|
||||
v-for="(label, i) in data.labelLine"
|
||||
:key="label">
|
||||
<div :style="`background-color: ${drawColors[i % drawColors.length]};`"></div>
|
||||
<div>{{ label }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<label-line :label="data.labelLine" :colors="drawColors" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
@ -539,27 +532,5 @@ export default {
|
|||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.label-line {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
justify-content: center;
|
||||
font-size: 10px;
|
||||
|
||||
.label-item {
|
||||
height: 20px;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin: 0px 5px 5px 5px;
|
||||
|
||||
:nth-child(1) {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -0,0 +1,305 @@
|
|||
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)',
|
||||
|
||||
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: [],
|
||||
valueTagGap: 0,
|
||||
labelTagGap: 0,
|
||||
xTagColor: '',
|
||||
yTagColor: '',
|
||||
xTagColorMul: false,
|
||||
yTagColorMul: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initAxis () {
|
||||
const { calcMaxMinValue, calcValueAxisTag, calcLabelAxisTag, calcXYAxisFS } = this
|
||||
|
||||
calcMaxMinValue()
|
||||
|
||||
calcValueAxisTag()
|
||||
|
||||
calcLabelAxisTag()
|
||||
|
||||
calcXYAxisFS()
|
||||
|
||||
const { calcXYLabelMaxWidth, calcAxisMargin, calcAxisOriginPos } = this
|
||||
|
||||
calcXYLabelMaxWidth()
|
||||
|
||||
calcAxisMargin()
|
||||
|
||||
calcAxisOriginPos()
|
||||
|
||||
const { calcAxisWH, calcValueTagPos, calcLabelTagPos, calcTagGap, calcTagColor } = this
|
||||
|
||||
calcAxisWH()
|
||||
|
||||
calcValueTagPos()
|
||||
|
||||
calcLabelTagPos()
|
||||
|
||||
calcTagGap()
|
||||
|
||||
calcTagColor()
|
||||
},
|
||||
calcMaxMinValue () {
|
||||
const { data: { data }, multipleSum, filterNull, getArrayMaxMin } = this
|
||||
|
||||
const trueValue = data.map(item =>
|
||||
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`
|
||||
|
||||
this.labelXYMaxWidth[0] = Math.max(...getTextsWidth(ctx, horizon ? labelAxisTag : valueAxisTag))
|
||||
|
||||
this.xyAxisUnitWidth[0] = ctx.measureText(xUN || '').width
|
||||
|
||||
ctx.font = `${xyAxisFS[1]}px Arial`
|
||||
|
||||
this.labelXYMaxWidth[1] = Math.max(...getTextsWidth(ctx, horizon ? valueAxisTag : labelAxisTag))
|
||||
|
||||
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]
|
||||
|
||||
this.ctx.arc(...this.axisOriginPos, 3, 0, Math.PI * 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 () {
|
||||
const { axisWH, labelAxisTag, horizon, axisOriginPos: [x, y], data, axisType } = this
|
||||
|
||||
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
|
||||
|
||||
this.labelTagPos = tempArray.map((t, i) =>
|
||||
horizon ? [x - 5, y - gapWidth * i - halfGapWidth] : [x + gapWidth * i + halfGapWidth, y + 5])
|
||||
}
|
||||
|
||||
if (axisType === 'line' && !boundaryGap) {
|
||||
const gapWidth = gapAllWidth / (labelNum - 1)
|
||||
|
||||
this.labelTagPos = tempArray.map((t, i) =>
|
||||
horizon ? [x - 5, y - gapWidth] : [x + gapWidth * i, y + 5])
|
||||
}
|
||||
},
|
||||
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
|
||||
},
|
||||
drawAxis () {
|
||||
const { drawAxisLine, drawAxisTag } = this
|
||||
|
||||
drawAxisLine()
|
||||
|
||||
drawAxisTag()
|
||||
},
|
||||
drawAxisLine () {
|
||||
const { ctx, defaultXAxisLineColor, defaultYAxisLineColor, axisOriginPos, axisWH, data } = this
|
||||
|
||||
const { x: { lineColor: xlc }, y: { lineColor: ylc } } = data
|
||||
|
||||
ctx.lineWidth = 1
|
||||
|
||||
ctx.strokeStyle = xlc || defaultXAxisLineColor
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(...axisOriginPos)
|
||||
ctx.lineTo(axisOriginPos[0] + axisWH[0], axisOriginPos[1])
|
||||
ctx.stroke()
|
||||
|
||||
ctx.strokeStyle = ylc || defaultYAxisLineColor
|
||||
ctx.beginPath()
|
||||
ctx.moveTo(...axisOriginPos)
|
||||
ctx.lineTo(axisOriginPos[0], axisOriginPos[1] - axisWH[1])
|
||||
|
||||
ctx.stroke()
|
||||
},
|
||||
drawAxisTag () {
|
||||
const { ctx, horizon, valueTagPos, labelTagPos, valueAxisTag, labelAxisTag } = this
|
||||
|
||||
const { xTagColor, xTagColorMul, yTagColor, yTagColorMul, xyAxisFS } = this
|
||||
|
||||
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'
|
||||
|
||||
xAxisData.forEach((pos, i) => {
|
||||
xTagColorMul && (ctx.fillStyle = xTagColor[i % xTagColorNum])
|
||||
|
||||
ctx.fillText(xTagData[i], ...pos)
|
||||
})
|
||||
|
||||
!yTagColorMul && (ctx.fillStyle = yTagColor)
|
||||
|
||||
const yTagColorNum = yTagColor.length
|
||||
|
||||
ctx.font = `${xyAxisFS[1]}px Arial`
|
||||
|
||||
ctx.textAlign = 'right'
|
||||
ctx.textBaseline = 'middle'
|
||||
|
||||
yAxisData.forEach((pos, i) => {
|
||||
xTagColorMul && (ctx.fillStyle = yTagColor[i % yTagColorNum])
|
||||
|
||||
ctx.fillText(yTagData[i], ...pos)
|
||||
})
|
||||
|
||||
this.ctx.fill()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
export default {
|
||||
data () {
|
||||
return {
|
||||
canvasDom: '',
|
||||
canvasWH: [0, 0],
|
||||
ctx: '',
|
||||
centerPos: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initCanvas () {
|
||||
const { $nextTick } = this
|
||||
|
||||
return new Promise(resolve => {
|
||||
$nextTick(e => {
|
||||
const { $refs, ref, labelRef, canvasWH, centerPos } = this
|
||||
|
||||
const canvas = this.canvasDom = $refs[ref]
|
||||
|
||||
this.labelDom = $refs[labelRef]
|
||||
|
||||
canvasWH[0] = canvas.clientWidth
|
||||
canvasWH[1] = canvas.clientHeight
|
||||
|
||||
canvas.setAttribute('width', canvasWH[0])
|
||||
canvas.setAttribute('height', canvasWH[1])
|
||||
|
||||
this.ctx = canvas.getContext('2d')
|
||||
|
||||
centerPos[0] = canvasWH[0] / 2
|
||||
centerPos[1] = canvasWH[1] / 2
|
||||
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
clearCanvas () {
|
||||
const { ctx, canvasWH } = this
|
||||
|
||||
ctx.clearRect(0, 0, ...canvasWH)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
import defaultColors from '../config/color.js'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
defaultColors,
|
||||
|
||||
drawColors: ''
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
initColors () {
|
||||
const { colors, defaultColors } = this
|
||||
|
||||
this.drawColors = colors || defaultColors
|
||||
}
|
||||
}
|
||||
}
|
|
@ -169,6 +169,12 @@ export function getCircleRadianPoint (x, y, radius, radian) {
|
|||
return [x + cos(radian) * radius, y + sin(radian) * radius]
|
||||
}
|
||||
|
||||
export function getTextsWidth (ctx, texts) {
|
||||
if (!ctx || !texts) return
|
||||
|
||||
return texts.map(text => ctx.measureText(text).width)
|
||||
}
|
||||
|
||||
const canvas = {
|
||||
drawLine,
|
||||
drawPolylinePath,
|
||||
|
@ -180,7 +186,8 @@ const canvas = {
|
|||
drawPoints,
|
||||
getLinearGradientColor,
|
||||
getRadialGradientColor,
|
||||
getCircleRadianPoint
|
||||
getCircleRadianPoint,
|
||||
getTextsWidth
|
||||
}
|
||||
|
||||
export default function (Vue) {
|
||||
|
|
|
@ -62,6 +62,26 @@ export function getPointToLineDistance (point, linePointOne, linePointTwo) {
|
|||
return 0.5 * Math.sqrt((a + b + c) * (a + b - c) * (a + c - b) * (b + c - a)) / c
|
||||
}
|
||||
|
||||
export function getArrayMaxMin (array) {
|
||||
if (!array) return false
|
||||
|
||||
return [getArrayMax(array), getArrayMin(array)]
|
||||
}
|
||||
|
||||
export function getArrayMax (array) {
|
||||
if (!array) return false
|
||||
|
||||
return Math.max(...filterNull(array).map(n =>
|
||||
n instanceof Array ? getArrayMax(n) : n))
|
||||
}
|
||||
|
||||
export function getArrayMin (array) {
|
||||
if (!array) return false
|
||||
|
||||
return Math.min(...filterNull(array).map(n =>
|
||||
n instanceof Array ? getArrayMin(n) : n))
|
||||
}
|
||||
|
||||
export default function (Vue) {
|
||||
Vue.prototype.deepClone = deepClone
|
||||
Vue.prototype.deleteArrayAllItems = deleteArrayAllItems
|
||||
|
@ -71,4 +91,7 @@ export default function (Vue) {
|
|||
Vue.prototype.filterNull = filterNull
|
||||
Vue.prototype.getPointDistance = getPointDistance
|
||||
Vue.prototype.getPointToLineDistance = getPointToLineDistance
|
||||
Vue.prototype.getArrayMaxMin = getArrayMaxMin
|
||||
Vue.prototype.getArrayMax = getArrayMax
|
||||
Vue.prototype.getArrayMin = getArrayMin
|
||||
}
|
||||
|
|
|
@ -36,6 +36,23 @@ colors: ['#9cf4a7', '#66d7ee', '#eee966', '#a866ee', '#ee8f66', '#ee66aa']
|
|||
</div>
|
||||
</border-box-7>
|
||||
|
||||
<border-box-7 class="chart-item" id="column-chart">
|
||||
<column-chart :data="columnChartData1" :colors="colors" class="chart" />
|
||||
|
||||
<div class="config-info">
|
||||
<div class="title">Column-Chart</div>
|
||||
<highlight-code>
|
||||
<column-chart :data="data" :colors="colors" />
|
||||
</highlight-code>
|
||||
|
||||
<highlight-code>
|
||||
data: {
|
||||
data: []
|
||||
}
|
||||
</highlight-code>
|
||||
</div>
|
||||
</border-box-7>
|
||||
|
||||
<border-box-7 class="chart-item" id="radar-chart">
|
||||
<radar-chart :data="radarChartData1" :colors="colors" class="chart" />
|
||||
|
||||
|
@ -483,12 +500,41 @@ export default {
|
|||
title: 'Attention',
|
||||
target: 'attention'
|
||||
},
|
||||
{
|
||||
title: 'Column-Chart',
|
||||
target: 'column-chart'
|
||||
},
|
||||
{
|
||||
title: 'Radar-Chart',
|
||||
target: 'radar-chart'
|
||||
}
|
||||
],
|
||||
|
||||
columnChartData1: {
|
||||
data: [
|
||||
[180, 290, 420, 200, 350, 219],
|
||||
[
|
||||
[45, 32, 66],
|
||||
[122, 49, 218],
|
||||
[40, 129, 216],
|
||||
[45, 66, 45],
|
||||
[110, 120, 201],
|
||||
[23, 40, 12]
|
||||
]
|
||||
],
|
||||
x: {
|
||||
data: ['西峡', '周口', '南阳', '驻马店', '郑州', '洛阳']
|
||||
},
|
||||
y: {
|
||||
grid: true,
|
||||
unit: '次',
|
||||
min: 0,
|
||||
max: 600
|
||||
},
|
||||
columnBG: 'rgba(250, 250, 250, 0.2)',
|
||||
roundColumn: true
|
||||
},
|
||||
|
||||
radarChartData1: {
|
||||
data: [
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue