2018-12-14 19:45:23 +08:00
|
|
|
<template>
|
|
|
|
<div class="radar-chart">
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
<loading v-if="!data" />
|
|
|
|
|
2018-12-14 19:45:23 +08:00
|
|
|
<div class="canvas-container">
|
|
|
|
<canvas :ref="ref" />
|
|
|
|
</div>
|
|
|
|
|
2018-12-20 18:25:49 +08:00
|
|
|
<label-line :label="data.labelLine" :colors="drawColors" />
|
2018-12-14 19:45:23 +08:00
|
|
|
</div>
|
|
|
|
</template>
|
|
|
|
|
|
|
|
<script>
|
2018-12-15 19:16:04 +08:00
|
|
|
import defaultColors from '../../config/color.js'
|
|
|
|
|
2018-12-14 19:45:23 +08:00
|
|
|
export default {
|
|
|
|
name: 'RadarChart',
|
|
|
|
data () {
|
|
|
|
return {
|
|
|
|
ref: `radar-chart-${(new Date()).getTime()}`,
|
|
|
|
canvasDom: '',
|
|
|
|
canvasWH: [0, 0],
|
|
|
|
ctx: '',
|
|
|
|
|
|
|
|
arcOriginPos: [],
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
defaultColors,
|
2018-12-14 19:45:23 +08:00
|
|
|
defaultRadius: 0.8,
|
2018-12-15 19:16:04 +08:00
|
|
|
defaultRingNum: 4,
|
|
|
|
defaultRingType: 'circle',
|
|
|
|
defaultRingLineType: 'dashed',
|
|
|
|
defaultRingLineColor: '#666',
|
|
|
|
defaultRingFillType: 'none',
|
|
|
|
defaultRayLineType: 'line',
|
2018-12-14 19:45:23 +08:00
|
|
|
defaultRayLineColor: '#666',
|
2018-12-15 19:16:04 +08:00
|
|
|
|
2018-12-14 19:45:23 +08:00
|
|
|
defaultRayLineOffset: Math.PI * -0.5,
|
|
|
|
defaultLabelColor: '#fff',
|
|
|
|
defaultLabelFS: 10,
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
drawColors: '',
|
2018-12-14 19:45:23 +08:00
|
|
|
radius: '',
|
2018-12-15 19:16:04 +08:00
|
|
|
ringType: '',
|
2018-12-14 19:45:23 +08:00
|
|
|
rayLineRadianData: [],
|
2018-12-15 19:16:04 +08:00
|
|
|
ringRadiusData: [],
|
|
|
|
ringPolylineData: [],
|
|
|
|
ringLineDash: [],
|
|
|
|
ringlineMultipleColor: false,
|
|
|
|
ringLineColor: '',
|
|
|
|
ringFillType: '',
|
|
|
|
ringFillMultipleColor: false,
|
|
|
|
ringFillColor: '',
|
|
|
|
rayLineColor: '',
|
|
|
|
rayLineDash: '',
|
|
|
|
rayLineMultipleColor: false,
|
|
|
|
labelPosData: [],
|
|
|
|
labelColor: '',
|
|
|
|
labelFontSize: '',
|
|
|
|
labelMultipleColor: false,
|
|
|
|
|
2018-12-14 19:45:23 +08:00
|
|
|
valuePointData: []
|
|
|
|
}
|
|
|
|
},
|
|
|
|
props: ['data', 'colors'],
|
|
|
|
watch: {
|
|
|
|
data (d) {
|
|
|
|
const { reDraw } = this
|
|
|
|
|
|
|
|
reDraw(d)
|
|
|
|
},
|
|
|
|
color (d) {
|
|
|
|
const { reDraw } = this
|
|
|
|
|
|
|
|
reDraw(d)
|
|
|
|
}
|
|
|
|
},
|
|
|
|
methods: {
|
|
|
|
init () {
|
|
|
|
const { $nextTick, initCanvas, calcOriginPos, data, draw } = this
|
|
|
|
|
|
|
|
$nextTick(e => {
|
|
|
|
initCanvas()
|
|
|
|
|
|
|
|
calcOriginPos()
|
|
|
|
|
|
|
|
data && draw()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
initCanvas () {
|
|
|
|
const { $refs, ref, labelRef, canvasWH } = 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')
|
|
|
|
},
|
|
|
|
calcOriginPos () {
|
|
|
|
const { canvasWH, arcOriginPos } = this
|
|
|
|
|
|
|
|
arcOriginPos[0] = canvasWH[0] / 2
|
|
|
|
arcOriginPos[1] = canvasWH[1] / 2
|
|
|
|
},
|
|
|
|
draw () {
|
2018-12-15 19:16:04 +08:00
|
|
|
const { ctx, canvasWH } = this
|
|
|
|
|
|
|
|
ctx.clearRect(0, 0, ...canvasWH)
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { initColor, calcRadarRadius, calcRingType } = this
|
2018-12-15 19:16:04 +08:00
|
|
|
|
|
|
|
initColor()
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
calcRadarRadius()
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
calcRingType()
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { calcRayLineRadianData, calcRingRadiusData, calcRingPolylineData } = this
|
2018-12-15 19:16:04 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
calcRayLineRadianData()
|
2018-12-15 19:16:04 +08:00
|
|
|
|
|
|
|
calcRingRadiusData()
|
|
|
|
|
|
|
|
calcRingPolylineData()
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { calcRingDrawConfig, calcRingFillConfig, fillRing } = this
|
2018-12-15 19:16:04 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
calcRingDrawConfig()
|
2018-12-15 19:16:04 +08:00
|
|
|
|
|
|
|
calcRingFillConfig()
|
|
|
|
|
|
|
|
fillRing()
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { drawCircleRing, drawPolylineRing, calcRayLineConfig } = this
|
2018-12-15 19:16:04 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
drawCircleRing()
|
2018-12-15 19:16:04 +08:00
|
|
|
|
|
|
|
drawPolylineRing()
|
|
|
|
|
|
|
|
calcRayLineConfig()
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { drawRayLine, calcLabelPosData, calcLabelConfig } = this
|
|
|
|
|
2018-12-14 19:45:23 +08:00
|
|
|
drawRayLine()
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
calcLabelPosData()
|
|
|
|
|
|
|
|
calcLabelConfig()
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { drawLable, caclValuePointData, fillRadar } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
drawLable()
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
caclValuePointData()
|
2018-12-15 19:16:04 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
fillRadar()
|
2018-12-15 19:16:04 +08:00
|
|
|
},
|
|
|
|
initColor () {
|
|
|
|
const { colors, defaultColors } = this
|
|
|
|
|
|
|
|
this.drawColors = colors || defaultColors
|
2018-12-14 19:45:23 +08:00
|
|
|
},
|
|
|
|
calcRadarRadius () {
|
|
|
|
const { canvasWH, data: { radius }, defaultRadius } = this
|
|
|
|
|
|
|
|
this.radius = Math.min(...canvasWH) * (radius || defaultRadius) * 0.5
|
|
|
|
},
|
2018-12-15 19:16:04 +08:00
|
|
|
calcRingType () {
|
|
|
|
const { data: { ringType }, defaultRingType } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
this.ringType = ringType || defaultRingType
|
|
|
|
},
|
|
|
|
calcRayLineRadianData () {
|
2018-12-16 17:57:09 +08:00
|
|
|
const { data: { label, rayLineOffset }, defaultRayLineOffset } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { data } = label
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const fullRadian = Math.PI * 2
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const radianGap = fullRadian / data.length
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const radianOffset = rayLineOffset || defaultRayLineOffset
|
|
|
|
|
|
|
|
this.rayLineRadianData = data.map((t, i) => radianGap * i + radianOffset)
|
|
|
|
},
|
|
|
|
calcRingRadiusData () {
|
|
|
|
const { data: { ringNum }, defaultRingNum, radius } = this
|
|
|
|
|
|
|
|
const num = ringNum || defaultRingNum
|
|
|
|
|
|
|
|
const radiusGap = radius / num
|
|
|
|
|
|
|
|
this.ringRadiusData = new Array(num).fill(0).map((t, i) =>
|
|
|
|
radiusGap * (i + 1))
|
|
|
|
},
|
|
|
|
calcRingPolylineData () {
|
|
|
|
const { ringRadiusData, rayLineRadianData, arcOriginPos } = this
|
|
|
|
|
|
|
|
const { canvas: { getCircleRadianPoint } } = this
|
|
|
|
|
|
|
|
this.ringPolylineData = ringRadiusData.map((r, i) =>
|
|
|
|
rayLineRadianData.map(radian =>
|
|
|
|
getCircleRadianPoint(...arcOriginPos, r, radian)))
|
|
|
|
},
|
|
|
|
calcRingDrawConfig () {
|
|
|
|
const { defaultRingLineType, defaultRingLineColor } = this
|
|
|
|
|
|
|
|
const { data: { ringLineType, ringLineColor }, drawColors } = this
|
|
|
|
|
|
|
|
this.ringLineDash = (ringLineType || defaultRingLineType) === 'dashed' ? [5, 5] : [10, 0]
|
|
|
|
|
|
|
|
const trueRingLineColor = ringLineColor === 'colors' ? drawColors : ringLineColor
|
|
|
|
|
|
|
|
this.ringlineMultipleColor = typeof trueRingLineColor === 'object'
|
|
|
|
|
|
|
|
this.ringLineColor = trueRingLineColor || defaultRingLineColor
|
|
|
|
},
|
|
|
|
calcRingFillConfig () {
|
|
|
|
const { data: { ringFillType, ringFillColor }, defaultRingFillType, drawColors } = this
|
|
|
|
|
|
|
|
this.ringFillType = ringFillType || defaultRingFillType
|
|
|
|
|
|
|
|
const trueRingFillColor = this.ringFillColor = (!ringFillColor || ringFillColor === 'colors') ? drawColors : ringFillColor
|
|
|
|
|
|
|
|
this.ringFillMultipleColor = typeof trueRingFillColor === 'object'
|
|
|
|
},
|
|
|
|
fillRing () {
|
|
|
|
const { ringFillType, fillCoverRing, fillMulCoverRing, fillRingRing } = this
|
|
|
|
|
|
|
|
switch (ringFillType) {
|
|
|
|
case 'cover': fillCoverRing()
|
|
|
|
break
|
|
|
|
|
|
|
|
case 'mulCover': fillMulCoverRing()
|
|
|
|
break
|
|
|
|
|
|
|
|
case 'ring': fillRingRing()
|
|
|
|
break
|
|
|
|
}
|
|
|
|
},
|
|
|
|
fillCoverRing () {
|
|
|
|
const { ctx, arcOriginPos, ringFillColor, ringType, radius, ringPolylineData } = this
|
|
|
|
|
|
|
|
const { canvas: { getRadialGradientColor, drawPolylinePath } } = this
|
|
|
|
|
|
|
|
const color = getRadialGradientColor(ctx, arcOriginPos, 0, radius, ringFillColor)
|
|
|
|
|
|
|
|
ctx.beginPath()
|
|
|
|
|
|
|
|
ringType === 'circle' && ctx.arc(...arcOriginPos, radius, 0, Math.PI * 2)
|
|
|
|
|
|
|
|
ringType === 'polyline' && drawPolylinePath(ctx, ringPolylineData[ringPolylineData.length - 1])
|
|
|
|
|
|
|
|
ctx.closePath()
|
|
|
|
|
|
|
|
ctx.fillStyle = color
|
|
|
|
|
|
|
|
ctx.fill()
|
|
|
|
},
|
|
|
|
fillMulCoverRing () {
|
|
|
|
const { ctx, ringType, ringFillColor, arcOriginPos } = this
|
|
|
|
|
|
|
|
const { ringFillMultipleColor, ringPolylineData, ringRadiusData, deepClone } = this
|
|
|
|
|
|
|
|
const { canvas: { drawPolylinePath } } = this
|
|
|
|
|
|
|
|
!ringFillMultipleColor && (ctx.fillStyle = ringFillColor)
|
|
|
|
|
|
|
|
const colorNum = ringFillColor.length
|
|
|
|
|
|
|
|
const LastRingIndex = ringRadiusData.length - 1
|
|
|
|
|
|
|
|
ringType === 'circle' &&
|
|
|
|
deepClone(ringRadiusData).reverse().forEach((radius, i) => {
|
|
|
|
ctx.beginPath()
|
|
|
|
|
|
|
|
ctx.arc(...arcOriginPos, radius, 0, Math.PI * 2)
|
|
|
|
|
|
|
|
ringFillMultipleColor && (ctx.fillStyle = ringFillColor[(LastRingIndex - i) % colorNum])
|
|
|
|
|
|
|
|
ctx.fill()
|
|
|
|
})
|
|
|
|
|
|
|
|
ringType === 'polyline' &&
|
|
|
|
deepClone(ringPolylineData).reverse().forEach((line, i) => {
|
|
|
|
drawPolylinePath(ctx, line, true, true)
|
|
|
|
|
|
|
|
ringFillMultipleColor && (ctx.fillStyle = ringFillColor[(LastRingIndex - i) % colorNum])
|
|
|
|
|
|
|
|
ctx.fill()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
fillRingRing () {
|
|
|
|
const { ctx, ringType, ringRadiusData, rayLineRadianData, getPointToLineDistance } = this
|
|
|
|
|
|
|
|
const { ringFillMultipleColor, arcOriginPos, ringFillColor, ringPolylineData } = this
|
|
|
|
|
|
|
|
const { canvas: { drawPolylinePath, getCircleRadianPoint } } = this
|
|
|
|
|
|
|
|
let lineWidth = ctx.lineWidth = ringRadiusData[0]
|
|
|
|
|
|
|
|
const halfLineWidth = lineWidth / 2
|
|
|
|
|
|
|
|
const colorNum = ringFillColor.length
|
|
|
|
|
|
|
|
!ringFillMultipleColor && (ctx.strokeStyle = ringFillColor)
|
|
|
|
|
|
|
|
ringType === 'circle' &&
|
|
|
|
ringRadiusData.forEach((r, i) => {
|
|
|
|
ctx.beginPath()
|
|
|
|
|
|
|
|
ctx.arc(...arcOriginPos, r - halfLineWidth, 0, Math.PI * 2)
|
|
|
|
|
|
|
|
ringFillMultipleColor && (ctx.strokeStyle = ringFillColor[i % colorNum])
|
|
|
|
|
|
|
|
ctx.stroke()
|
|
|
|
})
|
|
|
|
|
|
|
|
ctx.lineCap = 'round'
|
|
|
|
|
|
|
|
ctx.lineWidth = getPointToLineDistance(arcOriginPos, ringPolylineData[0][0], ringPolylineData[0][1])
|
|
|
|
|
|
|
|
ringType === 'polyline' &&
|
|
|
|
ringRadiusData.map(r => r - halfLineWidth).map(r =>
|
|
|
|
rayLineRadianData.map(radian =>
|
|
|
|
getCircleRadianPoint(...arcOriginPos, r, radian))).forEach((line, i) => {
|
|
|
|
drawPolylinePath(ctx, line, true, true)
|
|
|
|
|
|
|
|
ringFillMultipleColor && (ctx.strokeStyle = ringFillColor[i % colorNum])
|
|
|
|
|
|
|
|
ctx.stroke()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
drawCircleRing () {
|
|
|
|
const { data: { ringType }, defaultRingType } = this
|
|
|
|
|
|
|
|
if ((ringType && ringType !== 'circle') || (!ringType && defaultRingType !== 'circle')) return
|
|
|
|
|
|
|
|
const { ctx, ringRadiusData, arcOriginPos, ringLineDash, ringlineMultipleColor, ringLineColor } = this
|
|
|
|
|
|
|
|
ctx.setLineDash(ringLineDash)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
ctx.lineWidth = 1
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
!ringlineMultipleColor && (ctx.strokeStyle = ringLineColor)
|
|
|
|
|
|
|
|
const colorNum = ringLineColor.length
|
|
|
|
|
|
|
|
ringRadiusData.forEach((r, i) => {
|
2018-12-14 19:45:23 +08:00
|
|
|
ctx.beginPath()
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
ctx.arc(...arcOriginPos, r, 0, Math.PI * 2)
|
|
|
|
|
|
|
|
ringlineMultipleColor && (ctx.strokeStyle = ringLineColor[i % colorNum])
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
ctx.stroke()
|
|
|
|
})
|
|
|
|
},
|
2018-12-15 19:16:04 +08:00
|
|
|
drawPolylineRing () {
|
|
|
|
const { data: { ringType }, defaultRingType } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
if ((ringType && ringType !== 'polyline') || (!ringType && defaultRingType !== 'polyline')) return
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const { ctx, ringPolylineData, ringLineDash, ringlineMultipleColor, ringLineColor } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const { canvas: { drawPolyline } } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const colorNum = ringLineColor.length
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
ringPolylineData.forEach((line, i) =>
|
|
|
|
drawPolyline(ctx, line, 1,
|
|
|
|
(ringlineMultipleColor ? ringLineColor[i % colorNum] : ringLineColor),
|
|
|
|
true, ringLineDash, true))
|
|
|
|
},
|
|
|
|
calcRayLineConfig () {
|
|
|
|
const { data: { rayLineType, rayLineColor }, defaultRayLineType, defaultRayLineColor, drawColors } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
this.rayLineDash = (rayLineType || defaultRayLineType) === 'line' ? [10, 0] : [5, 5]
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const trueRayLineColor = rayLineColor === 'colors' ? drawColors : (rayLineColor || defaultRayLineColor)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
this.rayLineColor = trueRayLineColor
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
this.rayLineMultipleColor = typeof trueRayLineColor === 'object'
|
2018-12-15 19:16:04 +08:00
|
|
|
},
|
|
|
|
drawRayLine () {
|
|
|
|
const { ctx, rayLineColor, rayLineDash, ringPolylineData, arcOriginPos, rayLineMultipleColor } = this
|
|
|
|
|
|
|
|
const lastRingLineIndex = ringPolylineData.length - 1
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
ctx.setLineDash(rayLineDash)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
!rayLineMultipleColor && (ctx.strokeStyle = rayLineColor)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
ctx.lineWidth = 1
|
|
|
|
|
|
|
|
const colorNum = rayLineColor.length
|
|
|
|
|
|
|
|
ringPolylineData[lastRingLineIndex].forEach((point, i) => {
|
2018-12-14 19:45:23 +08:00
|
|
|
ctx.beginPath()
|
|
|
|
|
|
|
|
ctx.moveTo(...arcOriginPos)
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
ctx.lineTo(...point)
|
|
|
|
|
|
|
|
rayLineMultipleColor && (ctx.strokeStyle = rayLineColor[i % colorNum])
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
ctx.stroke()
|
|
|
|
})
|
|
|
|
},
|
2018-12-15 19:16:04 +08:00
|
|
|
calcLabelPosData () {
|
|
|
|
const { rayLineRadianData, radius, arcOriginPos } = this
|
|
|
|
|
|
|
|
const { canvas: { getCircleRadianPoint } } = this
|
|
|
|
|
|
|
|
const labelRadius = radius + 10
|
|
|
|
|
|
|
|
this.labelPosData = rayLineRadianData.map(radian =>
|
|
|
|
getCircleRadianPoint(...arcOriginPos, labelRadius, radian))
|
|
|
|
},
|
|
|
|
calcLabelConfig () {
|
|
|
|
const { defaultLabelColor, defaultLabelFS, drawColors } = this
|
|
|
|
|
|
|
|
const { data: { label: { color, fontSize } } } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const trueLabelColor = color === 'colors' ? drawColors : (color || defaultLabelColor)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
this.labelMultipleColor = typeof trueLabelColor === 'object'
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
this.labelFontSize = fontSize || defaultLabelFS
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
this.labelColor = trueLabelColor
|
|
|
|
},
|
|
|
|
drawLable () {
|
|
|
|
const { ctx, arcOriginPos: [x], labelPosData, labelColor, labelFontSize, labelMultipleColor } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const { data: { label: { data } } } = this
|
|
|
|
|
|
|
|
ctx.font = `${labelFontSize}px Arial`
|
|
|
|
|
|
|
|
!labelMultipleColor && (ctx.fillStyle = labelColor)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
ctx.textBaseline = 'middle'
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const colorNum = labelColor.length
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
labelPosData.forEach((pos, i) => {
|
2018-12-14 19:45:23 +08:00
|
|
|
ctx.textAlign = 'start'
|
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
pos[0] < x && (ctx.textAlign = 'end')
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
labelMultipleColor && (ctx.fillStyle = labelColor[i % colorNum])
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
ctx.fillText(data[i], ...pos)
|
2018-12-14 19:45:23 +08:00
|
|
|
})
|
|
|
|
},
|
|
|
|
caclValuePointData () {
|
2018-12-16 17:57:09 +08:00
|
|
|
const { data: { data, max }, arcOriginPos, radius, rayLineRadianData } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const { canvas: { getCircleRadianPoint } } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const maxValue = max || Math.max(...data.map(({ data: td }) => Math.max(...td)))
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
const valueRadius = data.map(({ data: td }) =>
|
|
|
|
td.map(value =>
|
|
|
|
Number.isFinite(value)
|
|
|
|
? value / maxValue * radius : false))
|
|
|
|
|
|
|
|
this.valuePointData = valueRadius.map(td =>
|
|
|
|
td.map((r, i) =>
|
|
|
|
r ? getCircleRadianPoint(...arcOriginPos, r, rayLineRadianData[i]) : false))
|
|
|
|
},
|
|
|
|
fillRadar () {
|
2018-12-16 17:57:09 +08:00
|
|
|
const { ctx, data: { data }, valuePointData, drawColors, filterNull } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { canvas: { drawPolylinePath } } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
const { color: { hexToRgb } } = this
|
2018-12-14 19:45:23 +08:00
|
|
|
|
2018-12-15 19:16:04 +08:00
|
|
|
const colorNum = drawColors.length
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
valuePointData.forEach((line, i) => {
|
2018-12-16 17:57:09 +08:00
|
|
|
const currentColor = drawColors[i % colorNum]
|
|
|
|
|
|
|
|
const lineColor = data[i].lineColor
|
|
|
|
const fillColor = data[i].fillColor
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
data[i].dashed ? ctx.setLineDash([5, 5]) : ctx.setLineDash([10, 0])
|
|
|
|
|
|
|
|
drawPolylinePath(ctx, filterNull(line), 1, true, true)
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
ctx.strokeStyle = lineColor || currentColor
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
ctx.stroke()
|
|
|
|
|
2018-12-16 17:57:09 +08:00
|
|
|
ctx.fillStyle = fillColor || hexToRgb(currentColor, 0.5)
|
2018-12-14 19:45:23 +08:00
|
|
|
|
|
|
|
ctx.fill()
|
|
|
|
})
|
|
|
|
},
|
|
|
|
reDraw (d) {
|
|
|
|
const { draw } = this
|
|
|
|
|
|
|
|
d && draw()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
mounted () {
|
|
|
|
const { init } = this
|
|
|
|
|
|
|
|
init()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</script>
|
|
|
|
|
|
|
|
<style lang="less">
|
|
|
|
.radar-chart {
|
|
|
|
position: relative;
|
|
|
|
display: flex;
|
|
|
|
flex-direction: column;
|
|
|
|
|
|
|
|
.canvas-container {
|
|
|
|
flex: 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
canvas {
|
|
|
|
width: 100%;
|
|
|
|
height: 100%;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
</style>
|