Trying to implement a speedometer in one of the components of my Vue project, but encountering an issue. When I input 0 into my progress calculation for determining the stroke fill, it overlaps with the background circle instead of staying within its boundaries. To provide better clarity, I have attached Screenshots & Code.
Desired outcome when passing 0 as fillLevel
Illustration of fully filled scenario - For better understanding of the problem
The goal is to prevent the orange circle from exceeding the boundary of the grey circle shown in the first screenshot. The orange circle should maintain the same length even when the fillLevel is set to 0.
This is the code snippet:
<script setup lang="ts">
import { ref, onMounted, watch } from 'vue';
const fillLevel = ref(0); // max value = 360
const circleRef = ref<SVGCircleElement | null>(null);
const backgroundCircleRef = ref<SVGCircleElement | null>(null);
const circleLength = ref(0);
const strokeDashoffset = ref(0);
const calculate = () => {
if (circleRef.value && backgroundCircleRef.value) {
circleLength.value = backgroundCircleRef.value.getTotalLength() * 0.8;
strokeDashoffset.value = circleLength.value * (1 - fillLevel.value / 360);
}
}
onMounted(calculate);
watch(fillLevel, calculate);
</script>
<template>
<div class="speedo-div">
<svg style="width: 24vh; height: 23vh;" viewBox="0 0 271 265" fill="none" xmlns="http://www.w3.org/2000/svg">
<!-- Some overlay content visible in the screenshots -->
</svg>
<div class="speedo">
<svg class="speedo-svg" viewBox="0 0 240 230" transform="rotate(125.5)">
<circle ref="backgroundCircleRef" class="circle" stroke="#53535399" r="35%" cy="50%" cx="50%" :stroke-dasharray="circleLength" />
<circle ref="circleRef" class="circle active" stroke="var(--primary)" r="35%" cy="50%" cx="50%" :stroke-dashoffset="strokeDashoffset" :stroke-dasharray="circleLength" />
</svg>
</div>
</div>
</template>
<style scoped>
.speedo {
position: absolute;
width: 24vh;
height: 23vh;
bottom: 0;
}
.speedo-svg {
position: absolute;
left: 0;
right: 0;
width: 24vh;
height: 23vh;
}
.speedo-svg .circle {
stroke-width: 25px;
opacity: .8;
fill: none;
transition: stroke-dashoffset .2s linear;
}
.speedo-svg .circle.active {
filter: drop-shadow(var(--primary-shadow));
}
</style>
Appreciate your attention!
Seeking assistance from someone experienced in SVG implementation. Please refrain from criticizing the use of vh for width as it's a personal preference.