vue+css如何实现圆环渐变仪表盘
作者:南泉鳥
这篇文章主要介绍了vue+css如何实现圆环渐变仪表盘问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
整体效果
主要原理
渐变圆环
设置如下css代码可实现出环形渐变效果
.box{ background:conic-gradient(from 0deg at 50% 50%,#eee 0deg,yelllow 180deg,red 360deg) }
- 效果图
添加圆角以及内部圆形居中遮挡即可实现圆环效果
- 效果图
仪表盘效果
添加若干个环绕圆点旋转的元素,组成仪表盘,融合背景色将底色圆环覆盖掉,就得到了仪表盘效果。
1.div结构
<div class="scale"> <div class="s-item" v-for="item in 72" :key="'item-' + item" > </div> </div>
2.scss
.scale { border-radius: 50%; width: 100%; height: 100%; position: absolute; .s-item { position: absolute; width: 1px; height: 2px; background-color: #fff; left:50%; top: 0px; transform-origin: 0 24px; } @for $i from 0 through 72 { .s-item:nth-child(#{$i + 1}) { transform: rotate($i * 5deg); } } }
- 形式图
- 效果图
全部代码
<template> <div class="gauge" :style="{ width: diameter + 'px', height: diameter + 'px', background: bgColor, }" > <div class="cricle" ref="cricle"> <!-- 色块圈 --> <div class="s-color" :style=" follow ? { background: `conic-gradient(from 0deg at 50% 50%,${ rampColor[0] } 0deg,${rampColor[1]} ${value / 2}deg,${ rampColor[2] } ${value}deg,${defaultColor} ${value}deg)`, } : { background: `conic-gradient(from 0deg at 50% 50%,${rampColor[0]} 0deg,${rampColor[1]} 50%,${rampColor[2]}`, } " > <div class="follow" v-if="!follow" :style="{ background: `conic-gradient(from 0deg at 50% 50%,transparent 0deg,transparent ${value}deg,${defaultColor} ${value}deg)`, }" ></div> <div class="mask" :style="{ width: `calc(100% - ${dotHeight}px *2)`, height: `calc(100% - ${dotHeight}px *2)`, background: bgColor, }" ></div> </div> <!-- 拖动按钮 --> <div class="slider" :style="{ transform: `rotate(${value}deg)`, width: sliderDiameter + 'px', height: `calc(50% - ${dotHeight / 2}px + ${sliderDiameter / 2}px)`, left: `calc(50% - ${sliderDiameter / 2}px)`, top: `calc((${sliderDiameter / 2}px - ${dotHeight / 2}px) *-1)`, }" > <div class="btn" ref="slider" :style="{ width: sliderDiameter + 'px', height: sliderDiameter + 'px', background: sliderColor, }" ></div> </div> <!-- 仪表盘 --> <div class="bar scale"> <div class="s-item" v-for="item in dotCount" :key="'item-' + item" :style="{ 'transform-origin': `2px calc(${diameter}px/2 + 1px)`, width: dotWidth + 'px', height: diameter / 2 + 'px', transform: `rotate(${(item * 360) / dotCount}deg)`, background: bgColor, }" ></div> </div> </div> </div> </template>
<script> export default { name: "gauge", /** 组件参数 */ props: { /** 默认值 */ default: { type: Number, default: 0, }, /** 直径 */ diameter: { type: Number, default: 200, }, /** 点间隔 */ dotWidth: { type: Number, default: 4, }, /** 点高度 */ dotHeight: { type: Number, default: 8, }, /** 滑块直径 */ sliderDiameter: { type: Number, default: 20, }, /** 滑块颜色 */ sliderColor: { type: String, default: "red", }, /** 点数量 */ dotCount: { type: Number, default: 72, }, /** 渐变色 */ rampColor: { type: Array, default: function () { return ["#ddd", "#faba2a", "#f24c4f"]; }, }, /** 环形默认颜色 */ defaultColor: { type: String, default: "#ddd", }, /** 背景颜色 */ bgColor: { type: String, default: "#fff", }, /** 渐变跟随 */ follow: { type: Boolean, default: true, }, }, data() { return { value: 0, }; }, methods: { /** ## 组件方法 */ /** 获取进度 */ getValue(){ return this.value/360; } }, created() { this.value = this.default; }, mounted() { /** 滑块滑动功能 */ this.$refs.slider.onmousedown = (e) => { const cricle = this.$refs.cricle; /** 获取位置(坐标轴原点) */ let client = cricle.getBoundingClientRect(); let x0 = client.x + cricle.offsetWidth / 2; let y0 = client.y + cricle.offsetHeight / 2; /** 阻止默认事件 */ let ev = e || window.event; ev.preventDefault ? ev.preventDefault() : (ev.returnValue = false); /** 鼠标移动 */ document.onmousemove = (el) => { let move = el ? el : window.event; /** 鼠标位置 */ let x = move.x - x0; let y = y0 - move.y; /** 计算角度 */ let deg = (Math.atan(y / x) / 2 / Math.PI) * 360; if (x >= 0) { if (this.value >= 270) { /** 象限跳跃优化 */ this.value = 360; } else { this.value = 90 - deg; } } else { if (this.value <= 90) { this.value = 0; } else { this.value = 270 - deg; } } }; /** 鼠标松开 */ document.onmouseup = () => { /** 取消订阅鼠标移动事件 */ document.onmousemove = null; document.onmouseup = null; }; }; }, }; </script>
<style lang="scss" scoped> .box { width: 100%; height: 100%; position: absolute; } .gauge { padding: 5px; //background-color: white; position: relative; .cricle { width: calc(100% - 10px); height: calc(100% - 10px); position: absolute; left: 50%; top: 50%; transform: translateY(-50%) translate(-50%); .slider { //background-color: pink; width: 20px; height: calc(50% + 6px); position: absolute; z-index: 10; overflow: hidden; transform-origin: 50% 100%; top: -6px; transform: rotate(140deg); left: calc(50% - 10px); .btn { position: absolute; cursor: pointer; top: 0px; width: 20px; height: 20px; // background-color: red; border-radius: 50%; } } .s-color { z-index: 5; //5 position: absolute; width: 100%; height: 100%; border-radius: 50%; .follow{ @extend .box; // position: absolute; // width: calc(100% + 2px ); // height: calc(100% + 2px); left:50%; top:50%; transform: translate(-50%,-50%); z-index: 6; border-radius: 50%; } .mask { content: ""; display: block; position: absolute; //background-color: #fff; z-index: 9; left: 50%; top: 50%; transform: translate(-50%, -50%); border-radius: 50%; } } .bar { transform: rotate(0deg); transform-origin: 0 100px; } .scale { border-radius: 50%; width: calc(100% + 2px); height: calc(100% + 2px); position: absolute; z-index: 9; left: 50%; top: 50%; transform: translate(-50%, -50%); .s-item { position: absolute; //background-color: #fff; left: calc(50% - 2px); top: 0px; } // @for $i from 0 through 72 { // .s-item:nth-child(#{$i + 1}) { // transform: rotate($i * 5deg); // } // } } } } </style>
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。