
html
<template>
<div id="app">
<svg width="400" height="400" viewBox="0 0 400 400">
<defs>
<filter id="shadow" x="-20%" y="-20%" width="140%" height="140%">
<feDropShadow dx="0" dy="0" stdDeviation="5" flood-color="rgba(0, 0, 0, 0.5)" />
</filter>
</defs>
<!-- 外层圆环 -->
<circle cx="200" cy="200" r="180" stroke="lightgray" stroke-width="20" fill="none" />
<circle
class="progress-circle"
cx="200"
cy="200"
r="180"
stroke="red"
stroke-width="20"
fill="none"
:stroke-dasharray="outerCircumference"
:stroke-dashoffset="outerOffset"
stroke-linecap="round"
transform="rotate(-90 200 200)"
filter="url(#shadow)"
/>
<!-- 中层圆环 -->
<circle cx="200" cy="200" r="140" stroke="lightgray" stroke-width="20" fill="none" />
<circle
class="progress-circle"
cx="200"
cy="200"
r="140"
stroke="green"
stroke-width="20"
fill="none"
:stroke-dasharray="middleCircumference"
:stroke-dashoffset="middleOffset"
stroke-linecap="round"
transform="rotate(-90 200 200)"
filter="url(#shadow)"
/>
<!-- 内层圆环 -->
<circle cx="200" cy="200" r="100" stroke="lightgray" stroke-width="20" fill="none" />
<circle
class="progress-circle"
cx="200"
cy="200"
r="100"
stroke="blue"
stroke-width="20"
fill="none"
:stroke-dasharray="innerCircumference"
:stroke-dashoffset="innerOffset"
stroke-linecap="round"
transform="rotate(-90 200 200)"
filter="url(#shadow)"
/>
</svg>
<div>
<label>外层进度: </label>
<input
type="number"
v-model="outerProgress"
@input="updateProgress('outer')"
min="0"
max="100"
/>
</div>
<div>
<label>中层进度: </label>
<input
type="number"
v-model="middleProgress"
@input="updateProgress('middle')"
min="0"
max="100"
/>
</div>
<div>
<label>内层进度: </label>
<input
type="number"
v-model="innerProgress"
@input="updateProgress('inner')"
min="0"
max="100"
/>
</div>
</div>
</template>
<script>
export default {
data() {
return {
outerProgress: 0,
middleProgress: 0,
innerProgress: 0,
outerCircumference: 2 * Math.PI * 180,
middleCircumference: 2 * Math.PI * 140,
innerCircumference: 2 * Math.PI * 100
}
},
computed: {
outerOffset() {
return this.outerCircumference - (this.outerProgress / 100) * this.outerCircumference
},
middleOffset() {
return this.middleCircumference - (this.middleProgress / 100) * this.middleCircumference
},
innerOffset() {
return this.innerCircumference - (this.innerProgress / 100) * this.innerCircumference
}
},
methods: {
updateProgress(type) {
if (type === "outer" && this.outerProgress >= 0 && this.outerProgress <= 100) {
this.outerProgress = this.outerProgress
} else if (type === "middle" && this.middleProgress >= 0 && this.middleProgress <= 100) {
this.middleProgress = this.middleProgress
} else if (type === "inner" && this.innerProgress >= 0 && this.innerProgress <= 100) {
this.innerProgress = this.innerProgress
}
}
}
}
</script>
<style scoped>
#app {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
input {
margin-top: 10px;
width: 60px;
text-align: center;
}
.progress-circle {
transition: stroke-dashoffset 0.5s ease;
}
</style>