1、真实效果是这样的
2、实现 的思路,
一开始想用背景图片来解决,但发现设计图上的东西也是切图粘上去的,背景图没法搞,那就用 css 来实现吧
1、确定圆,把每个点做成一个元素,用定位的方法定点。
2、每一个图标是找来的水滴状的字体图标,然后把它们的尖角对上圆心就可以了
3、开始实现
1、
如何得到圆上每个点的坐标?
来自 https://www.cnblogs.com/myclovers/p/6406383.html 的方法
如何得到圆上每个点的坐标?
解决思路:根据三角形的正玄、余弦来得值;
假设一个圆的圆心坐标是(a,b),半径为r,
则圆上每个点的X坐标=a + Math.sin(2*Math.PI / 360) * r ;Y坐标=b + Math.cos(2*Math.PI / 360) * r ;
如何求时钟的秒针转动一圈的轨迹?
假设秒针的初始值(起点)为12点钟方向,圆心的坐标为(a,b)。
解决思路:一分钟为60秒,一个圆为360°,所以平均每秒的转动角度为 360°/60 = 6°;
for(var times=0; times<60; times++) {
var hudu = (2*Math.PI / 360) * 6 * times;
var X = a + Math.sin(hudu) * r;
var Y = b – Math.cos(hudu) * r // 注意此处是“-”号,因为我们要得到的Y是相对于(0,0)而言的。
}
2、根据以上方法,先把一个圈的点全搞出来
<ul>
<li class="li" v-for="item in list" :style="item.style" ><i class="iconfont icon-shuidi" :class="{'yes' : item.color}"></i></li>
</ul>
positionLi2(){
let a = 150; //圆心坐标
let b = 150; //圆心坐标
let r = 150; //半径
let tatal = 38; // 一个圆有几个点
let h = 360 / tatal; //每个点的角度
let radio = 0; // 12点钟的点是直的,所以是 0度
let arr = [];
// 默认是从12点坐标开始
for(var times=0; times< tatal; times++) {
var hudu = (2*Math.PI / 360) * h * times;
var X = a + Math.sin(hudu) * r; //得到 left 坐标
var Y = b - Math.cos(hudu) * r; //得到 top 坐标
// 定位到中心点,27 是那个 li 点的长高
X = X - 27/2;
Y = Y - 27/2;
arr.push({
style : {'left':X+'px','top' : Y+'px','transform': 'rotate('+(radio-180)+'deg)'},
color : false,
})
radio+=h;
}
this.list = arr;
},
以上方法得到一个圈的点了,如图
3、然后就是去掉底下多余的点,再加上相应的色值 就可以了,代码中的 class=”yes” 就是色值的样式
把代码改一下,从某个点开始,到某个点结束,
positionLi2(){
let a = 150; //圆心坐标
let b = 150; //圆心坐标
let r = 150; //半径
let tatal = 38; // 一个圆有几个点
//从第几个点开始
let start = 27;
let showSpot = 23; // 一共要几个点
let h = 360 / tatal; //每个点的角度
let radio = start * h; // 开始的点的角度
let arr = [];
// 默认是从12点坐标开始
for(var times=start; times< (start + showSpot); times++) {
var hudu = (2*Math.PI / 360) * h * times;
var X = a + Math.sin(hudu) * r; //得到 left 坐标
var Y = b - Math.cos(hudu) * r; //得到 top 坐标
// 定位到中心点,27 是那个 li 点的长高
X = X - 27/2;
Y = Y - 27/2;
arr.push({
style : {'left':X+'px','top' : Y+'px','transform': 'rotate('+(radio-180)+'deg)'},
color : false,
})
radio+=h;
}
this.list = arr;
},
以上代码就得到了大半个圆的点的,改就数组中的 color 参数就可以加上相应的色值了
最终整个组件的代码是这样,
<template>
<div class="credit-img">
<ul>
<li class="li" v-for="item in list" :style="item.style" ><i class="iconfont icon-shuidi" :class="{'yes' : item.color}"></i></li>
</ul>
</div>
</template>
<style>
</style>
<script>
export default {
data() {
return {
htmlLi : '',
remNum : 0,
list : [],
tatal : 38, //一个圆有几个点
showSpot : 23,
numIndex : 0
};
},
methods: {
positionLi(){
//用的 rem 单位,把rem单位转成 px,
let a = this.remNum * 1.5;// 150; //圆心坐标
let b = this.remNum * 1.5; //圆心坐标
let r = this.remNum * 1.5; //半径
let start = 27;
let h = 360 / this.tatal; //每个点的角度
let radio = start * h;
let arr = [];
// 默认是从12点坐标开始 这里是从第二27个点开始
for(var times=start; times< (start + this.showSpot); times++) {
var hudu = (2*Math.PI / 360) * h * times;
var X = a + Math.sin(hudu) * r; //得到 left 坐标
var Y = b - Math.cos(hudu) * r; //得到 top 坐标
// 定位到中心点
X = X - (this.remNum * 0.27)/2;
Y = Y - (this.remNum * 0.27)/2;
arr.push({
style : {'left':X+'px','top' : Y+'px','transform': 'rotate('+(radio-180)+'deg)'},
color : false,
})
radio+=h;
}
this.list = arr;
this.upData();
},
upData(){
if(this.data || this.data === 0){
let num = parseInt(this.data * this.showSpot );
this.numIndex = 0
this.upColor(num)
}
},
upColor(tatal){
if(this.numIndex< tatal){
this.list[this.numIndex].color = true;
this.numIndex ++;
setTimeout(()=>{
this.upColor(tatal);
},80)
}
},
},
created() {
this.userInfo = this.$conf.get('userIndex');
},
mounted(){
this.$nextTick(()=>{
this.remNum = this.$conf.remNum;
this.positionLi();
})
},
props : ['data'],
watch : {
'data' : function(val,old){
this.upData();
}
}
};
</script>
<style lang="stylus">
.credit-img
width : 3rem
height : 3rem
position :absolute
left : 0
top : 0
.iconfont
font-size : 0.28rem
.iconfont.yes
color : #47e5e4
.li
position :absolute
</style>
使用:传入百分比即可
//引入
import creditImg from './credit-img.vue'
//添加上
components : {
'my-creditImg' : creditImg
}
//使用
<my-creditImg data="0.6"></my-creditImg>
效果就像头部的图片