シンプルなドーナツチャートが必要になったのでvue+svgで作りました
成果物
See the Pen donut-chart vue component by sqrt3 (@sqrt3) on CodePen.
内容
template.pug
.donutChart(:style="{ width: `${width}px`, height: `${height}px` }")
svg.donutChart_circleWrapper(:width="width" :height="height" viewBox="0 0 42 42")
circle(v-if="border" :cx="cxy" :cy="cxy" :r="radius" fill="transparent" stroke="grey" :stroke-width="borderStrokeWidth")
circle.donutChart_circle(
v-for="(e, i) in chartData"
:cx="cxy"
:cy="cxy"
:r="radius"
fill="transparent"
:stroke="e.color"
:stroke-width="strokeWidth"
:data-fill="e.value")
svg(:width="width" :height="height" viewBox="0 0 42 42")
text.donutChart_text(x="50%" y="50%" text-anchor="middle" dominant-baseline="central") {{ text }}
css.styl
.donutChart
position relative
&_circleWrapper
position absolute
transform-origin center
transform rotate(-90deg)
transform-box fill-box
&_circle
transform-box fill-box
&_text
font-size 0.4em
script.js
export default DonutChart {
props: {
value: {
type: Array,
required: true
},
width: {
type: Number,
default: 100
},
height: {
type: Number,
default: 100
},
strokeWidth: {
type: Number,
default: 6
},
text: String,
border: {
type: Boolean,
default: false
}
},
data () {
return {
radius: 15.91549430918954,
cxy: 21
}
},
computed: {
totalValue () {
return this.value.map(e => e.value).reduce((prev, e) => prev + e)
},
criteriaValue () {
return 100 / this.totalValue
},
chartData () {
return this.value.filter(e => (e.value > 0)).map(e => {
return {
value: e.value * this.criteriaValue,
color: e.color
}
})
},
borderStrokeWidth () {
return this.strokeWidth + 0.5
}
},
mounted () {
this.draw()
},
methods: {
draw () {
const elms = this.$el.querySelectorAll(".donutChart_circle")
let offset = 0
elms.forEach((e, i) => {
const val = parseFloat(e.getAttribute('data-fill'))
const dasharray = [val, 100 - val]
e.setAttribute("stroke-dasharray", dasharray)
e.setAttribute("stroke-dashoffset", offset * -1)
offset = offset + val
})
}
}
})
stroke-dasharrayで点線の間隔をうまく調整してstroke-dashoffsetでずらして描画していく感じですね
数値を出したいところですが大変そうなのでとりあえずここまで