add radar chart and new decoration

This commit is contained in:
jiaming 2018-12-14 19:45:23 +08:00
parent 0981b9e6e8
commit 8e06964260
6 changed files with 338 additions and 11 deletions

View File

@ -275,22 +275,24 @@ export default {
polyline[0] && drawPolyline(ctx, polyline, 2, color[i % colorNum], false, [10, 0], true))
},
drawLabelText () {
const { ctx, labelLinePoints, data: { data, labelFontSize }, totalValue, defaultLabelFontSize, arcOriginPos: [x] } = this
const { ctx, labelLinePoints, data: { data, labelFontSize, fixed }, totalValue, defaultLabelFontSize, arcOriginPos: [x] } = this
ctx.font = `${labelFontSize || defaultLabelFontSize}px Arial`
ctx.fillStyle = '#fff'
let totalPercent = 0
const dataLast = data.length - 1
data.forEach(({ value, title }, i) => {
if (!value && totalValue) return
let currentPercent = value / totalValue * 100
let currentPercent = (value / totalValue * 100).toFixed(fixed || 1)
currentPercent = (currentPercent > 1 ? Math.trunc(currentPercent) : currentPercent.toFixed(2))
i === dataLast && (currentPercent = (100 - totalPercent).toFixed(fixed || 1))
currentPercent += '%'
!totalValue && (currentPercent = '0%')
!totalValue && (currentPercent = 0)
const textPos = labelLinePoints[i][2]
@ -300,11 +302,13 @@ export default {
ctx.textBaseline = 'bottom'
ctx.fillText(currentPercent, ...textPos)
ctx.fillText(`${currentPercent}%`, ...textPos)
ctx.textBaseline = 'top'
ctx.fillText(title, ...textPos)
totalPercent += Number(currentPercent)
})
}
},

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

@ -0,0 +1,22 @@
<template>
<div class="decoration-5">
<img src="./img/decoration.gif" />
</div>
</template>
<script>
export default {
name: 'Decoration5'
}
</script>
<style lang="less">
.decoration-5 {
img {
width: 100%;
margin-top: -21%;
margin-bottom: -25%;
}
}
</style>

View File

@ -1,7 +1,9 @@
<template>
<pre><code class="highlight-code" :ref="ref">
<div class="highlight-code">
<pre><code :ref="ref">
<slot></slot>
</code></pre>
</code></pre>
</div>
</template>
<script>
@ -41,7 +43,10 @@ export default {
<style lang="less">
.highlight-code {
font-family: 'code';
background-color: transparent;
code {
font-family: 'code';
background-color: transparent;
}
}
</style>

View File

@ -10,12 +10,14 @@ import decoration1 from './decoration1/index'
import decoration2 from './decoration2/index'
import decoration3 from './decoration3/index'
import decoration4 from './decoration4/index'
import decoration5 from './decoration5/index'
import capsuleChart from './capsuleChart/index.vue'
import ringChart from './ringChart/index.vue'
import polylineChart from './polylineChart/index.vue'
import concentricArcChart from './concentricArcChart/index.vue'
import arcRingChart from './arcRingChart/index.vue'
import radarChart from './radarChart/index.vue'
import numberShow from './numberShow/index.vue'
@ -33,15 +35,20 @@ export default function (Vue) {
Vue.component('borderBox5', borderBox5)
Vue.component('borderBox6', borderBox6)
Vue.component('borderBox7', borderBox7)
Vue.component('decoration1', decoration1)
Vue.component('decoration2', decoration2)
Vue.component('decoration3', decoration3)
Vue.component('decoration4', decoration4)
Vue.component('decoration5', decoration5)
Vue.component('capsuleChart', capsuleChart)
Vue.component('polylineChart', polylineChart)
Vue.component('ringChart', ringChart)
Vue.component('concentricArcChart', concentricArcChart)
Vue.component('arcRingChart', arcRingChart)
Vue.component('radarChart', radarChart)
Vue.component('numberShow', numberShow)
Vue.component('scrollBoard', scrollBoard)
Vue.component('loading', loading)

View File

@ -0,0 +1,289 @@
<template>
<div class="radar-chart">
<div class="canvas-container">
<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: ${colors[i % colors.length]};`"></div>
<div>{{ label }}</div>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'RadarChart',
data () {
return {
ref: `radar-chart-${(new Date()).getTime()}`,
canvasDom: '',
canvasWH: [0, 0],
ctx: '',
arcOriginPos: [],
defaultRadius: 0.8,
defaultCircleNum: 4,
defaultCircleColor: '#666',
defaultRayLineColor: '#666',
defaultRayLineOffset: Math.PI * -0.5,
defaultLabelColor: '#fff',
defaultLabelFS: 10,
radius: '',
rayLineRadianData: [],
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 () {
const { calcRadarRadius, drawRadarCircle, drawRayLine } = this
calcRadarRadius()
drawRadarCircle()
drawRayLine()
const { drawLable, caclValuePointData, fillRadar } = this
drawLable()
caclValuePointData()
fillRadar()
},
calcRadarRadius () {
const { canvasWH, data: { radius }, defaultRadius } = this
this.radius = Math.min(...canvasWH) * (radius || defaultRadius) * 0.5
},
drawRadarCircle () {
const { ctx, arcOriginPos, radius, data, defaultCircleNum, defaultCircleColor } = this
const { circleNum, circleColor } = data
const trueCircleNum = circleNum || defaultCircleNum
const gap = radius / trueCircleNum
ctx.strokeStyle = circleColor || defaultCircleColor
ctx.setLineDash([5, 5])
ctx.lineWidth = 1
new Array(trueCircleNum).fill(0).forEach((t, i) => {
ctx.beginPath()
ctx.arc(...arcOriginPos, gap * (i + 1), 0, Math.PI * 2)
ctx.stroke()
})
},
drawRayLine () {
const { ctx, radius, arcOriginPos, data: td, defaultRayLineColor, defaultRayLineOffset, canvas } = this
const { label: { data }, rayLineColor, rayLineOffset } = td
const { getCircleRadianPoint } = canvas
const labelNum = data.length
const gapRadian = Math.PI * 2 / labelNum
const radianOffset = rayLineOffset || defaultRayLineOffset
ctx.strokeStyle = rayLineColor || defaultRayLineColor
ctx.lineWidth = 1
ctx.setLineDash([10, 0])
const rayLineRadianData = this.rayLineRadianData = []
new Array(labelNum).fill(0).forEach((t, i) => {
const currentRadian = gapRadian * (i + 1) + radianOffset
rayLineRadianData.push(currentRadian)
ctx.beginPath()
ctx.moveTo(...arcOriginPos)
ctx.lineTo(...getCircleRadianPoint(...arcOriginPos, radius, currentRadian))
ctx.stroke()
})
},
drawLable () {
const { ctx, radius, arcOriginPos, canvas, data: td, defaultLabelColor, defaultLabelFS, rayLineRadianData } = this
const { label: { data, color, fontSize } } = td
const { getCircleRadianPoint } = canvas
const endRadius = radius + 10
ctx.font = `${fontSize || defaultLabelFS}px Arial`
ctx.fillStyle = color || defaultLabelColor
ctx.textBaseline = 'middle'
data.forEach((label, i) => {
const currentEndPointPos = getCircleRadianPoint(...arcOriginPos, endRadius, rayLineRadianData[i])
ctx.textAlign = 'start'
currentEndPointPos[0] < arcOriginPos[0] && (ctx.textAlign = 'end')
ctx.fillText(label, ...currentEndPointPos)
ctx.fill()
})
},
caclValuePointData () {
const { data: { data }, arcOriginPos, radius, canvas, rayLineRadianData } = this
const { getCircleRadianPoint } = canvas
const maxValue = Math.max(...data.map(({ data: td }) => Math.max(...td)))
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 () {
const { ctx, data: { data }, valuePointData, colors, canvas, color, filterNull } = this
const { drawPolylinePath } = canvas
const { hexToRgb } = color
const colorNum = colors.length
valuePointData.forEach((line, i) => {
const lineColor = data[i].color || colors[i % colorNum]
data[i].dashed ? ctx.setLineDash([5, 5]) : ctx.setLineDash([10, 0])
drawPolylinePath(ctx, filterNull(line), 1, true, true)
ctx.strokeStyle = lineColor
ctx.stroke()
ctx.fillStyle = hexToRgb(lineColor, 0.5)
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%;
}
.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>