前言
最近在FA项目开发中,遇到类似这样的圆形进度条,参考开发文档利用canvas封装成了一个组件,这是一个基于JS扩展的类Web开发范式组件中的基础组件 。
组件介绍
circle进度条组件在开发中经常用到,形式多种多样,参考canvas文档做了简单的一种,支持各种属性调整。有需要可以参考看看。
代码演示
- 默认普通展示
<circularBar percent = '80' ></circularBar>
- 显示百分比文字
<circularBar percent = '60' istext = 'true'></circularBar>
- 自定义宽度
<circularBar percent = '60' bg-width = '20' f-width = '20'></circularBar>
- 自定义颜色
<circularBar percent = '60' color-c = '#ff6600'></circularBar>
- 自定义渐变颜色
<circularBar percent = '60' color-num = '2' start-c = '#f463b2' end-c = '#376af9'></circularBar>
- 自定义背景颜色
<circularBar percent = '60' bg-color = '#6a6a6a'></circularBar>
- 自定义绘制方向
<circularBar percent = '60' direction = 'true'></circularBar>
注意:
父子组件属性使用:camelCase (驼峰命名法) 的 prop 名,在外部父组件传递参数时需要使用 kebab-case (短横线分隔命名) 形式,即当属性compProp在父组件引用时需要转换为comp-prop。
API
props
参数 | 说明 | 类型 | 默认值 |
percent | 进度条百分比 | Number | 50 |
colorNum | 颜色值,1:纯色 2: 渐变色 | String | - |
bgWidth | 背景圈的宽度 | Number | 10 |
fWidth | 动态圈的宽度 | Number | 10 |
istext | 显示百分比文字 | Boolean | false |
direction | 绘制方向,顺时针false/逆时针true | Boolean | false |
bgColor | 背景圈颜色 | String | ‘#cccccc’ |
部分代码展示
1、html部分
<div class="container">
<div style="margin-left: 10%;">
<canvas ref="canvasbox" style="width: 100px; height: 100px;">
canvas>
div>
div>
2、js部分
相关api参考
名称 | 类型 | 默认值 | 描述 |
string | ‘butt’ | 指定线端点的样式,可选值为:- ‘butt’:线端点以方形结束。- ‘round’:线端点以圆形结束。- ‘square’:线端点以方形结束,该样式下会增加一个长度和线段厚度相同,宽度是线段厚度一半的矩形。 | |
- | 设置描边的颜色。- 类型为 | ||
font | string | ‘normal normal 14px sans-serif’ | 设置文本绘制中的字体样式。语法:ctx.font=‘font-size font-family’- font-size(可选),指定字号和行高,单位只支持px。- font-family(可选),指定字体系列。语法:ctx.font=‘font-style font-weight font-size font-family’- font-style(可选),用于指定字体样式,支持如下几种样式:‘normal’,talic。- font-weight(可选),用于指定字体的粗细,支持如下几种类型:‘normal’, ‘bold’, ‘bolder’, ‘lighter’, 100, 200, 300, 400, 500, 600, 700, 800, 900。- font-size(可选),指定字号和行高,单位只支持px。- font-family(可选),指定字体系列,支持如下几种类型:‘sans-serif’, ‘serif’, ‘monospace’。 |
- 封装组件在onshow()周期内绘制显示不出动画图像,修改为onpageshow()绘制成功,延迟200毫秒画布绘制要在页面展示后才能绘制。
//初始绘制
onPageShow(){
setTimeout(()=>{
const darw_el = this.$refs.canvasbox;
console.info(darw_el)
//颜色取值不支持#ccc #f60 十六进制颜色 不支持缩写
this.circleFun(darw_el,this.colorNum,this.percent,this.bgWidth,this.fWidth,this.bgColor,this.textColor,this.istext,this.direction,this.startC,this.endC,this.colorC)
},200)
},
- 获取canvas绘制图像的宽高值,无法直接获取,需使用getBoundingClientRect()方法 ;这里绘制的中心点,以画布的中点为中心。
//定义变量
var rect = draw_item.getBoundingClientRect();
var context = draw_item.getContext('2d');
var center_x = (rect.width)/2;
var center_y = (rect.height)/2;
var rad = (Math.PI *2) /100;
var speed = 0;
- 绘制圆圈的半径主要以画布的宽度和线圈宽度有关,这里没有把宽度作为props属性值传参进来,使用修改可直接修改画布大小,半径为画布宽度一半减去线圈宽度,结尾形状取值参考。
// 绘制后面的圈圈
function backCircle(){
context.save()
context.beginPath()
context.lineWidth = lineWidth_b // 设置线宽
var radius = center_x - context.lineWidth //设置半径
context.lineCap = 'round' //结尾形状
context.strokeStyle = color_b //线条颜色
context.arc(center_x, center_y, radius, 0, Math.PI * 2, false)
context.stroke()
context.closePath()
context.restore()
}
- 进度条填充颜色可自定义选择,colornums取值1为纯色对应传Color_C的颜色值,colornums取值为2为渐变色需传入开始颜色start_C和结束颜色end_C两个颜色值。
//绘制前面的圈圈
function foceCircle(n){
context.save()
//context.strokeStyle = color_f //决定圆环颜色
context.lineWidth = lineWidth_f;//前面动态圈宽度
context.lineCap = 'round';//结尾形状
var radius = center_x - context.lineWidth;//半径
context.beginPath()
if (colornums == 1) {
context.strokeStyle = Color_C
}
if (colornums == 2) {
//创建渐变对象,渐变开始点和渐变结束点
let g = context.createLinearGradient(0, 90, 90, 0);
g.addColorStop(0, start_C); //添加颜色点
g.addColorStop(1, end_C); //添加颜色点
context.strokeStyle = g; //使用渐变对象作为圆环的颜色
}
//用于绘制圆弧context.arc(x坐标,y坐标,半径,起始角度,终止角度,顺时针/逆时针)
//context.arc(center_x,center_y,radius, -Math.PI / 4,-Math.PI / 4 + n * rad,direct )
context.arc(center_x,center_y,radius, Math.PI / 20, n*rad, direct )
context.stroke()
context.closePath()
context.restore()
}
- 文字绘制相关api参考,组件百分比文字显示作为可选项,需要显示时传入istext字段即可。
//绘制文字
function text(n) {
context.save();
context.fillStyle = color_f; //文字颜色
var font_size = 20 ;//字体大小
context.font = font_size + 'px Helvetica' //字体大小和文字形状
var text_width = context.measureText(n.toFixed(0) + '%').width;//文字宽度
context.fillText(n.toFixed(0) + '%', center_x - text_width / 2, center_y + font_size / 2)
context.restore()
}
- 在最后执行动画这块做了一个文字百分比的动态增加,这块有一点点的小问题文字动态增加过程中会出现绘制闪动的问题,目前尚未解决,但是不影响正常使用。后续会逐步更新解决。
//执行动画
(function drawFrame() {
if (speed <= percent) {
requestAnimationFrame(drawFrame)
} else {
return false
}
context.clearRect(0, 0, rect.width, rect.height)
//context.globalCompositeOperation = "copy"
backCircle();
//控制百分比文字显示、隐藏
if(textshow){
text(speed);
}
foceCircle(speed);
if (speed >= percent) {
speed ++
} else {
speed += 1
}
})()
总结
此自定义组件运用了canvas绘制,使用和练习中参考官方api,也结合了组件通信,父子组件直接的传值。
缺点是不支持拖动事件,在事件这部分没有做添加。