做一个web app,想在第一次或者更新的时候,有一个更新进度条,我个人比较喜欢圆的那种。

canvas + svg高低配,应该还不错的。顺便一提,canvas用来压缩图片也是么么哒的。

先看下效果图,我咋觉得边有点虚。基本的样子有了,但是美观,美观,我要美观,下次再来。

原理就是绘制圆和文本绘制。

特别说明:

1. 会自动计算canvas的宽高,取最大值,并重设宽高为最大值

2. 有简单的计算逻辑,让 百分比的文本居中

3. 超大的边宽会被限制

上代码。


class CanvasProgress {
constructor(cv, options = {
bgColor: '#123456',
cBgColor: 'green',
edgeWidth: 20
}) { if (!cv || !cv.getContext) {
throw new Error('参数cv为空或者getContext方法未定义')
} this._ctx = cv.getContext('2d')
this._diameter = this._getDiameter(cv) //直径
this._radius = Math.ceil(this._diameter / 2) //半径
this._options = Object.assign({
bgColor: '#123456', //未加载的背景色
cBgColor: 'green', //已加载的背景色
edgeWidth: 20, //边款
textMaxWidth: this._radius //进度文本最大长度
}, options)
this._options.edgeWidth = Math.min(this._radius * 0.28, this._options.edgeWidth) //重新计算
this._circleParams = {
x: this._radius,//圆心的x轴坐标值
y: this._radius,//圆心的y轴坐标值
r: Math.floor(this._radius - this._options.edgeWidth / 2 - 1) //圆的半径
} this._resizeCanvas(cv) //调整canvas宽高一致
this._initialize() //绘制背景圆
} /**
* 通过canvas获得直径
* @param {*canvas对象} cv
*/
_getDiameter(cv) {
return Math.max(cv.height || 0, cv.width || 0) || 200
} /**
* 进度转换角度
* @param {*进度} progress
*/
_getAngle(progress) {
return (progress / 100) * Math.PI * 2
} _resizeCanvas(cvProgress) {
cvProgress.width = cvProgress.height = this._diameter
} /**
* 调整canvas宽高一致
*/
_initialize() {
let ctx = this._ctx
// 开始一个新的绘制路径
ctx.beginPath()
//设置弧线的颜色为蓝色
ctx.strokeStyle = this._options.bgColor
ctx.lineWidth = this._options.edgeWidth
//以canvas中的坐标点(100,100)为圆心,绘制一个半径为50px的圆形
ctx.arc(this._circleParams.x, this._circleParams.y, this._circleParams.r, 0, Math.PI * 2, false)
//按照指定的路径绘制弧线
ctx.stroke()
} /**
* 更近进度
* @param {*进度 0-100} progressValue
* @param {*绘制圆的设置} circleSettings
* @param {*绘制文本的设置} progressTextSettings
*/
updateProgress(progressValue, circleSettings, progressTextSettings) {
if (progressValue <= 0) {
return
}
this._updateCircle(progressValue, circleSettings)
this._updateProgressText(progressValue, progressTextSettings)
} /**
* 绘制圆
* @param {*进度} progressValue
* @param {*设置} settings
*/
_updateCircle(progressValue, settings) {
let ctx = this._ctx
ctx.beginPath()
let angle = this._getAngle(progressValue) ctx.strokeStyle = this._options.cBgColor
ctx.lineWidth = this._options.edgeWidth if (settings) {
Object.keys(settings).forEach(k => {
ctx[k] = settings[k]
})
} ctx.arc(this._circleParams.x, this._circleParams.y, this._circleParams.r, 0 + Math.PI * 1.5, angle + Math.PI * 1.5, false)
ctx.stroke()
} /**
* 绘制进度文本
* @param {*进度} progressValue
* @param {*设置} settings
*/
_updateProgressText(progressValue, settings) { if (progressValue < 0 || progressValue > 100) {
return
} let ctx = this._ctx,
r = this._radius,
fontSize = this._getFontSize(settings)
ctx.clearRect(r * 0.5, r * 0.5, r, r)
ctx.font = `${fontSize}px sans-serif`
ctx.fillStyle = this._getTextGradient()
if (settings) {
Object.keys(settings).forEach(k => {
ctx[k] = settings[k]
})
} ctx.fillText(progressValue + '%', this._circleParams.x - this._options.textMaxWidth / 2, this._circleParams.y + fontSize / 2, this._options.textMaxWidth)
} /**
* 渐变设置
*/
_getTextGradient() {
var gradient = this._ctx.createLinearGradient(0, 0, 100, 0);
gradient.addColorStop("0", "red");
gradient.addColorStop("0.5", "blue");
gradient.addColorStop("1.0", "green");
return gradient
} /**
* 获得当前文字大小
* @param {*设置} settings
*/
_getFontSize(settings) {
if (settings && settings.font) {
let matchItem = settings.font.match(/\d{1,2}/)
if (matchItem) {
return Number.parseInt(matchItem[0])
}
}
return this._radius * 0.6
} }

  

调用代码:

<!DOCTYPE>
<html> <head>
<title> canvas 原型进度条</title>
<meta name="viewport" content="width=device-width,initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
<meta charset="utf-8">
</head> <body style="margin:5% 10% 0 10%">
<div>
<canvas id="cvProgress" height="250" width="15">
</div>
<script src="CanvasProgress.js"></script>
</body>
<script>
let ps = new CanvasProgress(cvProgress, {
edgeWidth: 50
}), progress = 0
let tickets = setInterval(function () {
progress += 5
ps.updateProgress(progress,null,{
})
if (progress > 100) {
clearInterval(tickets)
}
}, 100) </script> </html>

源码地址:https://github.com/xiangwenhu/BlogCodes/tree/master/client/canvas

canvas 简易的加载进度条的更多相关文章

  1. Unity3D 场景切换加载进度条实现

    需要三个场景,场景A,场景B,场景C: 场景A:一个按钮,点击加载场景B: 场景B:从A切换到C过度场景,加载进度条: 场景C:目标场景: 创建OnProgress.cs脚本: using Syste ...

  2. css3 linear-gradient实现页面加载进度条效果

    最终效果图: html结构: <div>    <p class="p1">        <span></span>    < ...

  3. ajax页面加载进度条插件

    下面两个都是youtube视频的加载进度条效果的ajax插件 一.官网:http://ricostacruz.com/nprogress/官网 github:https://github.com/rs ...

  4. pace.js – 加载进度条插件

    这儿只是简单介绍一下这个插件pace.js. 在页面中引入Pace.js,页面就会自动监测你的请求(包括Ajax请求),在事件循环滞后,会在页面记录加载的状态以及进度情况.此插件的兼容性很好,可以兼容 ...

  5. 仿UC浏览器图片加载进度条

    前几天用UC浏览器看新闻(无意中给UC打了广告),看到它的图片加载进度条,正好最近有时间,所以就自己写了一个. 效果图如下 进度条的底色和填充颜色都可以调整. 首先中间的笑脸作为一个整体,其实现代码如 ...

  6. 【Web前沿技术】纯 CSS3 打造的10个精美加载进度条动画

    之前向大家介绍8款优秀的 jQuery 加载动画和进度条插件,今天这篇文章向大家推荐10个纯 CSS3 代码实现精美加载进度条动画效果的方案.加载动画和进度条在网站和 Web 应用中的使用非常流行,特 ...

  7. jQuery模拟页面加载进度条

    因为我们无法通过任何方法获取整个页面的大小和当前加载了多少,所以想制作一个加载进度条的唯一办法就是模拟.那要怎么模拟呢? 我们知道,页面是从上往下执行的,也就是说我们可以大致估算出在页面的某个位置加载 ...

  8. js页面加载进度条

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  9. iOS UIWebView 加载进度条的使用-WKWebView的使用,更新2017.6.26

    1.由于项目中加载网络插件,直接使用了webview加载.使用了三方NJKWebViewProgress进度条的使用,近期在测试时发现,网络缓慢时出现白屏,有卡顿现象. 于是采用了WKWebView进 ...

随机推荐

  1. C#_表达式目录树的应用

    使用表达式目录树实现两个不同类型的属性赋值: public class People { public int Age { get; set; } public string Name { get; ...

  2. Hashtable 小记

    Hashtable 是 JDK 中较早的数据结构了,目前已不再推荐使用了.但抱着学习的目的,还是看了下它的实现. 简介 Hashtable,顾名思义即哈希表,是一种经典的数据结构.其基本结构是一个数组 ...

  3. python学习第一天基础篇

    学习背景:决定开始学习python之前,因为公司基本都是微软系统,所以很少碰到linux系统,机缘巧合接到了一个项目是使用shell对mysql进行backup,因为公司唯一的系统工程师是微软在行,对 ...

  4. 动手开发一个名为“微天气”的微信小程序(上)

    引言:在智能手机软件的装机量中,天气预报类的APP排在比較靠前的位置.说明用户对天气的关注度非常高.由于人们不管是工作还是度假旅游等各种活动都须要依据自然天气来安排.跟着本文开发一个"微天气 ...

  5. jQuery->JavaScript一览表

    比较jQuery与JavaScript的不同功能实现 CSS选择器 元素选择 // jQuery $("li").css("color", "red& ...

  6. 关于 getsockname、getpeername和gethostname、gethostbyname

    一.gethostname,gethostbyname的用法 这两个函数可以用来获取主机的信息.gethostname:获取主机的名字gethostbyname:通过名字获取其他的信息(比如ip) 1 ...

  7. 如何正确使用javah

    bogon:src zexu$ javah -jni -classpath /Users/zexu/github/ijkplayer/android/ijkplayer/ijkplayer-java/ ...

  8. 「mysql优化专题」主从复制面试宝典!面试官都没你懂得多!(11)

    内容较多,可先收藏,目录如下: 一.什么是主从复制 二.主从复制的作用(重点) 三.主从复制的原理(重中之重) 四.三步轻松构建主从 五.必问面试题干货分析(最最重要的点) 一.什么是主从复制(技术文 ...

  9. DWR3.0 服务器推送及解惑

    前言:在慕课网上学习一下服务器推送给客户端技术,代码亲测过,没毛病,今天整理记录一下: 一.环境搭建 直接上图,简单粗暴,myeclipse上file->new->WebProject 二 ...

  10. 【java设计模式】【行为模式Behavioral Pattern】策略模式Strategy Pattern

    package com.tn.策略模式; public class Client { private Strategy strategy; public void setStrategy(Strate ...