Skip to content

Instantly share code, notes, and snippets.

@web-crab
Created October 28, 2018 14:15
Show Gist options
  • Save web-crab/dd0ae19296cb659b404c4e9356a13908 to your computer and use it in GitHub Desktop.
Save web-crab/dd0ae19296cb659b404c4e9356a13908 to your computer and use it in GitHub Desktop.
<template>
<svg class="donut">
<transition-group tag="g" name="circle" appear>
<circle
ref="circle"
v-for="(circle, i) in circles" :key="i"
:r="radius"
:stroke="colors[i]"
:stroke-dasharray="circle.dashArray"
:stroke-dashoffset="circle.dashOffset"
@mouseover="hoverOnChart(i, true)"
@mouseout="hoverOnChart(i, false)"
/>
</transition-group>
</svg>
</template>
<script>
const COLORS = ['#e74c3c', '#f1c40f', '#2ecc71', '#3498db']
const RADIUS = 80
// Затемнение/осветление цвета
const switchColor = (color, amount) => {
const num = parseInt(color.slice(1), 16)
const [r, g, b] = [
(num >> 16) + amount,
(num & 0x0000FF) + amount,
((num >> 8) & 0x00FF) + amount
].map(c => c > 255 ? 255 : c < 0 ? 0 : c)
return '#' + (g | (b << 8) | (r << 16)).toString(16)
}
export default {
props: {
stats: { // [{ name: String, value: Number (%) }, ...]
type: Array,
required: true,
validator: _ => _.length
}
},
data() {
return {
colors: COLORS,
radius: RADIUS
}
},
computed: {
// Процентное соотношение всех сумм к общей
percents() {
const total = this.stats.reduce((res, _) => res += _.value, 0)
return total
? this.stats.map(_ => (_.value * 100 / total) || 0)
: [25, 25, 25, 25] // Если общая сумма === 0, то рисуем график с одинаковыми отрезками
},
// Размеры и отступы отрезков графика
circles() {
const circleLength = 2 * Math.PI * this.radius // Длина круга
let summOfLengths = 0
return this.percents.map(p => {
const length = p * circleLength / 100 // Длина отрезка
const offset = circleLength - length // Оставшееся место
const styles = {
dashArray : length + ' ' + offset,
dashOffset: -summOfLengths // Сдвиг по кругу = сумма длин предыдущих элементов
}
summOfLengths += length
return styles
})
}
},
methods: {
// При наведении на отрезок подсвечиваем его
hoverOnChart(i, isHover) {
this.$refs.circle[i].style.stroke = isHover
? switchColor(this.colors[i], -25)
: this.colors[i]
}
}
}
</script>
<style lang="sass" scoped>
.circle-enter
stroke-dasharray: 0 500px
stroke-dashoffset: 0
.donut
width: 270px
height: 270px
transform: rotate(-90deg)
& g
stroke-width: 40px
fill: none
& circle
cx: 135px
cy: 135px
transition: all .5s ease
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment