I work on the Nuxt.js (v.2.15.0) app. I have a component like a donut with 3 sectors divided to 4 another sub-sectors (here). I change the colors of the sectors dynamically depending on values I recieve via websockets. My code for component:
<template>
<div class="lap is-flex is-flex-direction-column">
<div class="live-label is-flex is-justify-content-center" v-text="title" />
<div class="lap-content">
<div class="circle">
<ul class="circle__wrapper">
<li v-for="index in count" :key="index" class="circle__section" />
</ul>
<div
class="
circle__center
is-flex is-align-items-center is-justify-content-center
"
>
<div class="live-label--large" v-text="speedValue" />
</div>
</div>
</div>
</div>
</template>
<script>
import { msToLapTime } from '@/utils'
export default {
props: {
title: {
type: String,
default: 'Lap',
},
value: {
type: Number,
default: 0,
},
currentSector: {
type: Number,
default: 0,
},
sectors: {
type: Object,
default: () => {},
},
count: {
type: Number,
default: 12,
},
},
computed: {
speedValue() {
return this.value > 0
? msToLapTime(this.value, this.$dateFns).slice(0, 7)
: '00:00.0'
},
},
watch: {
currentSector() {
this.setSegmentColour()
},
},
mounted() {
this.setSegmentColour()
},
methods: {
setSegmentColour() {
const sectionArr = document.querySelectorAll('.circle__section')
if (this.currentSector === 1) {
for (let i = 0; i < this.count; i++) {
if (i < 4) {
sectionArr[i].classList = 'circle__section filled'
} else {
sectionArr[i].className = 'circle__section'
}
}
} else if (this.currentSector === 2) {
for (let i = 0; i < 12; i++) {
if (i < 4) {
sectionArr[i].classList.add(this.sectors.s1Colour)
} else if (i >= 4 && i < 8) {
sectionArr[i].classList = 'circle__section filled'
} else {
sectionArr[i].className = 'circle__section'
}
}
} else if (this.currentSector === 3) {
for (let i = 0; i < 12; i++) {
if (i < 4) {
sectionArr[i].classList.add(this.sectors.s1Colour)
} else if (i >= 4 && i < 8) {
sectionArr[i].classList.add(this.sectors.s2Colour)
} else {
sectionArr[i].classList = 'circle__section filled'
}
}
}
},
},
}
</script>
And the style for this donut is here:
.circle {
position: relative;
&__wrapper {
border-radius: 50%;
position: relative;
padding: 0;
margin: 1em auto;
list-style: none;
overflow: hidden;
&::before {
content: '';
position: absolute;
z-index: 2;
width: calc(100% + 2px);
height: calc(100% + 2px);
top: -1px;
left: -1px;
border-radius: 50%;
mask-image: radial-gradient(farthest-side, transparent calc(100% - 2px), #fff 100%);
transform: rotate(1deg);
}
@include grid-elem-size('height', 2.5);
@include grid-elem-size('width', 2.5);
}
&__section {
position: absolute;
top: 0;
right: 0;
width: 50%;
height: 50%;
background-color: #656565;
transform-origin: 0% 100%;
@include circle-fraction(12);
&.filled {
background-color: #d0cfcf;
animation-name: color;
animation-duration: 2s;
animation-iteration-count: infinite;
}
}
&__center {
position: absolute;
top: calc(50% - #{$grid-size} * 1.1);
left: calc(50% - #{$grid-size} * 1.1);
border-radius: 50%;
background-color: var(--background-color);
@include grid-elem-size('height', 2.2);
@include grid-elem-size('width', 2.2);
&::before {
content: '';
position: absolute;
width: 100%;
height: 100%;
border-radius: 50%;
mask-image: radial-gradient(farthest-side, transparent calc(100% - 1px), #fff 100%);
transform: rotate(1.5deg);
}
}
}
To divide the chart to 12 elements I use a mixin (and include below the mixin I use in the code above in case if someone wants to reproduce it):
$grid-size: #{'(100vh - 185px) / 8'}
@mixin grid-elem-size($property, $size){
#{$property}: calc(#{$grid-size} * #{$size})!important;
}
@mixin circle-fraction($size) {
@for $i from 1 through $size {
&:nth-child(#{$i}) {
transform: rotate(calc((#{$i} - 1) * (calc(360deg / #{$size})))) skewY(calc(-360deg / #{$size / 2})) translate(4px,-4px);
}
}
}
It works well enough for me. And now requirements have been changed.
I need to divide the element dynamically, because now we work with more tracks and some of them possibly has more than 3 sectors, so I should receive the variable (which can be 3~10) and divide the donut to this amount of sectors and every sector divide to 4 sub-sectors. Also every sub-sector needs to keep a space around, as it is now (maybe reduce the space).I'd appreciate any help, even some library would be very helpful. Thanks in advance!