实现效果
实现步骤
下面我们分步实现
拆解问题
- 实现一个扇形
- 把一个圆分成100份儿
- 用1个
div
代表一份儿- div的宽高
- 位置怎么定
- 给
div
一定的旋转角度- 多少角度
- 角度怎么变
- 在扇形中间覆盖一个小圆,从而形成环
静态实现
直接贴初始代码吧
<div class="out-circle">
<div class="inner-circle">4</div>
<div class="item item1"></div>
<div class="item item2"></div>
<div class="item item3"></div>
<div class="item item4"></div>
</div>
.out-circle {
position: relative;
width: 500px;
height: 500px;
border-radius: 50%;
border: 1px solid red;
overflow: hidden;
}
.inner-circle {
z-index: 10;
position: absolute;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
width: 480px;
height: 480px;
text-align: center;
line-height: 480px;
font-size: 30px;
border-radius: 50%;
border: 1px solid red;
background-color: #fff;
}
.item {
position: absolute;
left: 50%;
height: 250.1234208092861px;
width: 15.705379539064147px;
transform-origin: 50% 100%;
background-color: blue;
}
.item1 {
transform: translateX(-50%) rotate(0deg);
}
.item2 {
transform: translateX(-50%) rotate(3.6deg);
}
.item3 {
transform: translateX(-50%) rotate(7.2deg);
}
.item4 {
transform: translateX(-50%) rotate(10.8deg);
}
**图2** 静态效果图
要点:
- 蓝条的位置和旋转角度
transfrom-origin
属性transform
的rotate和translate需同时设置,不然后面的会把前面的覆盖
- 蓝条的宽高
动态实现
把 .progress
内的所有元素清空,用js生成进度条相关的dom,从而达到解偶的目的。甚至可以将css也写到js中,这样使用者只需要引入js即可。
代码如下:
class Progress {
constructor({ dom, ratio }) {
this.dom = dom || document.body;
this.ratio = ratio || 0;
this.create();
}
create() {
this.outCircleDom = document.createElement('div');
this.outCircleDom.classList.add('out-circle');
this.innerCircleDom = document.createElement('div');
this.innerCircleDom.classList.add('inner-circle');
this.outCircleDom.appendChild(this.innerCircleDom);
this.dom.appendChild(this.outCircleDom);
this.render(this.ratio)
}
onChange(ratio) {
this.render(ratio)
}
renderRatio(ratio) {
if (ratio > 1 || ratio < 0) {
throw Error('ratio may be great than 0 and less than 1')
}
this.innerCircleDom.textContent = parseInt(100 * ratio) + '%';
}
renderItems(ratio) {
this.itemCount = parseInt(100 * ratio);
var domFrag = document.createDocumentFragment();
for (let i = 0; i < this.itemCount; i++) {
var item = document.createElement('div');
item.classList.add('item')
item.style.cssText = `transform: translateX(-50%) rotate(${3.6 * i}deg);`
domFrag.appendChild(item)
}
this.outCircleDom.appendChild(domFrag)
}
render(ratio) {
this.renderItems(ratio)
this.renderRatio(ratio)
}
}
到此,我们就可以以如下的方式调用我们的组件了:
// 实例化我们的进度条
let progress = new Progress({
dom: document.querySelector('.progress'),
ratio: 0
});
// 模拟:假设r是某事件的进度:
let r = 0
document.body.onclick = e => {
progress.onChange(r+=0.01)
}
便可实现如下效果:
总结
虽然完成了基础功能,但还有很多东西需要改进。这篇文章只提供思路,生产环境不建议使用。