这是一个仿支付宝芝麻信用分的一个canvas,其实就是一个动画仪表盘。

首先, 上原图:

这个是在下支付宝上的截图,分低各位见笑了。然后看下我用canvas实现的效果图:

<canvas id="canvas" width="400" height="700" data-score='724'></canvas>
<!-- 设置data-score,分数区间[400, 900] -->

唉,总感觉不像。这个是GIF图,可能在网页上打开的效果会好一点(当然可能就是这样)。大家可以点击底部预览codepen上的演示。有两个不完美的地方,一个是实际上芝麻信用表盘上的的刻度是不均匀的,我这为了简单的实现就采取相同的刻度;二是表盘上运动的点是有模糊的效果,还没解决。唉,下次再说吧。

接下来还是来说说怎么实现的吧。第一步,国际惯例,创建画布:

var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
cWidth = canvas.width,
cHeight = canvas.height;

然后绘制表盘,虽说不是处女座,但也要尽可能做到跟原图上的一样,那就是这个环形开口的角度是多少呢?请上ps来测一下:

嗯,136°,这个角度确实刁钻,为了方便接下来的计算,那就约等于140°。那么一个分数段的弧度就是:

var deg1 = Math.PI * 11 / 45

先把中间半透明的刻度层画好:

ctx.save(); //中间刻度层
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(0, 0, 135, 0, 11 * deg0, false);
ctx.stroke();
ctx.restore();

接着,画6条刻度线,用for循环来实现:

ctx.save(); // 刻度线
for (var i = 0; i < 6; i++) {
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
ctx.moveTo(140, 0);
ctx.lineTo(130, 0);
ctx.stroke();
ctx.rotate(deg1);
}
ctx.restore();

同理,再把大刻度细分为5个小刻度:

ctx.save(); // 细分刻度线
for (i = 0; i < 25; i++) {
if (i % 5 !== 0){
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .1)';
ctx.moveTo(140, 0);
ctx.lineTo(133, 0);
ctx.stroke();
}
ctx.rotate(deg1 / 5);
}
ctx.restore();

刻度到这里就ok了,还需要给刻度标上文字和每个分数段的信用级别,具体的参见代码,因为跟刻度实现的原理差不多,就不啰嗦了。现在最关键就是实现表盘上那个运动的点(不知道怎么称呼,下文就叫它动点),我们可以这样想,它是个半径很小的圆,只不过是画在最外层环形轨道上圆,而圆在canvas上的实现方法是:

ctx.arc(x, y, radius, sAngle, eAngle, false);

我们只要控制x, y就能让它动起来,实现我们想要的效果。so,创建一个动点对象:

function Dot() {
this.x = 0;
this.y = 0;
this.draw = function (ctx) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = 'rgba(255, 255, 255, .7)';
ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
ctx.fill();
ctx.restore();
};
}
var dot = new Dot(),
dotSpeed = 0.03, //控制动点的速度
angle = 0, //这个很关键,用来得到动点的坐标x, y
credit = 400; //信用最低分数

如何得到dot的坐标x, y呢?那就要用到传说中三角函数了。

通过上图我们可以得到

x = r * cos(angle), y = r * sin(angle)

在JavaScript中,dot的中心坐标就变成了:

dot.x = radius * Math.cos(angle); //radius为最外层轨道的半径值
dot.y = radius * Math.sin(angle);

接下来我们只要得到这个angle。这个通过弧度与分数的比例关系就可以得到:

var aim = (score - 400) * deg1 / 100;
if (angle < aim) {
angle += dotSpeed;
}
dot.draw(ctx);

然后让中间的信用分数也能随动点的转动而变化,创建一个text(),为了使数字变化能和动点保持一致,要根据动点的速率来计算数字变化:

function text(process) {
ctx.save();
ctx.rotate(10 * deg0);
ctx.fillStyle = '#000';
ctx.font = '80px Microsoft yahei';
ctx.textAlign = 'center';
ctx.textBaseLine = 'top';
ctx.fillText(process, 0 ,10);
ctx.restore();
}
var textSpeed = Math.round(dotSpeed * 100 / deg1),
if (credit < score - textSpeed) {
credit += textSpeed;
} else if (credit >= score - textSpeed && credit < score) {
credit += 1; // 这里确保信用分数最后停下来是我们输入的分数
}
text(credit);

最后这一切都逃不过让window.requestAnimationFrame()来控制绘制动画和用ctx.clearRect(0, 0, cWidth, cHeight)来清除画布。

写的不好,大家将就着看,我相信大家理解代码的能力一定强于理解我这些我自己都不知道说什么的文字。

好了,以上。

code:

<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title>芝麻信用仪表盘</title>
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
margin: 0;
} canvas {
border: 1px solid #eee;
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: -webkit-linear-gradient(top, #0e83f5 0%, #21bdf6 100%);
background: -ms-linear-gradient(top, #0e83f5 0%, #21bdf6 100%);
background: -moz-linear-gradient(top, #0e83f5 0%, #21bdf6 100%);
background: linear-gradient(top, #0e83f5 0%, #21bdf6 100%);
}
</style>
<script type="text/javascript">
window.onload = function() {
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
cWidth = canvas.width,
cHeight = canvas.height,
score = canvas.attributes['data-score'].value,
stage = ['较差', '中等', '良好', '优秀', '极好'],
radius = 150,
deg0 = Math.PI / 9,
deg1 = Math.PI * 11 / 45; if(score < 400 || score > 900) {
alert('信用分数区间:400~900');
} else {
var dot = new Dot(),
dotSpeed = 0.03,
textSpeed = Math.round(dotSpeed * 100 / deg1),
angle = 0,
credit = 400; (function drawFrame() { ctx.save();
ctx.clearRect(0, 0, cWidth, cHeight);
ctx.translate(cWidth / 2, cHeight / 2);
ctx.rotate(8 * deg0); dot.x = radius * Math.cos(angle);
dot.y = radius * Math.sin(angle); var aim = (score - 400) * deg1 / 100;
if(angle < aim) {
angle += dotSpeed;
}
dot.draw(ctx); if(credit < score - textSpeed) {
credit += textSpeed;
} else if(credit >= score - textSpeed && credit < score) {
credit += 1;
}
text(credit); ctx.save();
ctx.beginPath();
ctx.lineWidth = 3;
ctx.strokeStyle = 'rgba(255, 255, 255, .5)';
ctx.arc(0, 0, radius, 0, angle, false);
ctx.stroke();
ctx.restore(); window.requestAnimationFrame(drawFrame); ctx.save(); //中间刻度层
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .2)';
ctx.lineWidth = 10;
ctx.arc(0, 0, 135, 0, 11 * deg0, false);
ctx.stroke();
ctx.restore(); ctx.save(); // 刻度线
for(var i = 0; i < 6; i++) {
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .3)';
ctx.moveTo(140, 0);
ctx.lineTo(130, 0);
ctx.stroke();
ctx.rotate(deg1);
}
ctx.restore(); ctx.save(); // 细分刻度线
for(i = 0; i < 25; i++) {
if(i % 5 !== 0) {
ctx.beginPath();
ctx.lineWidth = 2;
ctx.strokeStyle = 'rgba(255, 255, 255, .1)';
ctx.moveTo(140, 0);
ctx.lineTo(133, 0);
ctx.stroke();
}
ctx.rotate(deg1 / 5);
}
ctx.restore(); ctx.save(); //信用分数
ctx.rotate(Math.PI / 2);
for(i = 0; i < 6; i++) {
ctx.fillStyle = 'rgba(255, 255, 255, .4)';
ctx.font = '10px Microsoft yahei';
ctx.textAlign = 'center';
ctx.fillText(400 + 100 * i, 0, -115);
ctx.rotate(deg1);
}
ctx.restore(); ctx.save(); //分数段
ctx.rotate(Math.PI / 2 + deg0);
for(i = 0; i < 5; i++) {
ctx.fillStyle = 'rgba(255, 255, 255, .4)';
ctx.font = '10px Microsoft yahei';
ctx.textAlign = 'center';
ctx.fillText(stage[i], 5, -115);
ctx.rotate(deg1);
}
ctx.restore(); ctx.save(); //信用阶段及评估时间文字
ctx.rotate(10 * deg0);
ctx.fillStyle = '#fff';
ctx.font = '28px Microsoft yahei';
ctx.textAlign = 'center';
if(score < 500) {
ctx.fillText('信用较差', 0, 40);
} else if(score < 600 && score >= 500) {
ctx.fillText('信用中等', 0, 40);
} else if(score < 700 && score >= 600) {
ctx.fillText('信用良好', 0, 40);
} else if(score < 800 && score >= 700) {
ctx.fillText('信用优秀', 0, 40);
} else if(score <= 900 && score >= 800) {
ctx.fillText('信用极好', 0, 40);
} ctx.fillStyle = '#80cbfa';
ctx.font = '14px Microsoft yahei';
ctx.fillText('评估时间:2016.11.06', 0, 60); ctx.fillStyle = '#7ec5f9';
ctx.font = '14px Microsoft yahei';
ctx.fillText('BETA', 0, -60);
ctx.restore(); // ctx.save(); //最外层轨道
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 255, 255, .4)';
ctx.lineWidth = 3;
ctx.arc(0, 0, radius, 0, 11 * deg0, false);
ctx.stroke();
ctx.restore(); })();
} function Dot() {
this.x = 0;
this.y = 0;
this.draw = function(ctx) {
ctx.save();
ctx.beginPath();
ctx.fillStyle = 'rgba(255, 255, 255, .7)';
ctx.arc(this.x, this.y, 3, 0, Math.PI * 2, false);
ctx.fill();
ctx.restore();
};
} function text(process) {
ctx.save();
ctx.rotate(10 * deg0);
ctx.fillStyle = '#000';
ctx.font = '80px Microsoft yahei';
ctx.textAlign = 'center';
ctx.textBaseLine = 'top';
ctx.fillText(process, 0, 10);
ctx.restore();
}
};
</script>
</head> <body>
<canvas id="canvas" width="400" height="700" data-score='724'></canvas>
</body> </html>

 

<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title>芝麻信用仪表盘</title>
<style type="text/css">
html,
body {
width: 100%;
height: 100%;
margin: 0;
} canvas {
border: 1px solid red;
position: relative;
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
background: -webkit-linear-gradient(top, #0e83f5 0%, #21bdf6 100%); }
</style>
<script type="text/javascript">
window.onload = function() {
var canvas = document.getElementById('canvas'),
ctx = canvas.getContext('2d'),
cWidth = canvas.width,
cHeight = canvas.height,
score = canvas.attributes['data-score'].value,
radius = 100, //圆的半径
deg0 = Math.PI / 9, //0.3490658503988659
deg1 = Math.PI * 11 / 45; //0.767944870877505 if(score < 2000 || score > 10000) {
console.log('信用分数区间:2000~10000'); } else { var dotSpeed = 0.1,
angle = 0,
credit = 2000; //默认值开始数 (function drawFrame() { ctx.save();
ctx.clearRect(0, 0, cWidth, cHeight);
ctx.translate(cWidth / 2, cHeight / 2);
ctx.rotate(8 * deg0); var aim = (score - 2000) * deg1 / 1600;
if(angle < aim) {
angle += dotSpeed;
} if(credit < score) {
credit += 200;
} else if(credit >= 10000) {
credit = 10000;
}
text(credit); ctx.save();
ctx.beginPath();
ctx.lineWidth = 5;
ctx.strokeStyle = 'rgba(255, 255, 255, 1)';
ctx.arc(0, 0, radius, 0, angle, false);
ctx.stroke();
ctx.restore();
ctx.save();
ctx.rotate(10 * deg0);
ctx.restore();
ctx.beginPath();
ctx.strokeStyle = 'rgba(255, 0, 0, .1)';
ctx.lineWidth = 5;
ctx.arc(0, 0, radius, 0, 11 * deg0, false); //设置外圆环
ctx.stroke();
ctx.restore(); window.requestAnimationFrame(drawFrame);
})();
} function text(process) {
ctx.save();
ctx.rotate(10 * deg0);
ctx.fillStyle = 'red';
ctx.font = '40px Microsoft yahei';
ctx.textAlign = 'center';
ctx.textBaseLine = 'top';
ctx.fillText(process, 0, 10);
ctx.restore();
}
};
</script>
</head> <body>
<canvas id="canvas" width="400" height="500" data-score='10000'></canvas>
</body> </html>

  

 自动打手CSS零时打造一个:

<!DOCTYPE html>
<html> <head>
<meta charset="UTF-8">
<title></title>
<style type="text/css">
#yibiao {
width: 400px;
height: 200px;
background: white;
margin: 0 auto;
position: relative;
overflow: hidden;
} .yuan1 {
width: 400px;
height: 400px;
position: absolute;
top: 0px;
left: 0px;
border-radius: 50%;
background: black;
opacity: 0.2;
} .yuan2 {
width: 360px;
height: 360px;
position: absolute;
top: 20px;
left: 20px;
border-radius: 50%;
background: white;
} .clip {
width: 400px;
height: 400px;
position: absolute;
top: 0px;
left: 0px;
border-radius: 50%;
background: blue;
clip: rect(200px, 400px, 400px, 0px);
transform: rotate(0deg);
} .num {
position: absolute;
width: 100%;
height: 100px;
top: 100px;
text-align: center;
font-size: 100px;
}
</style>
<script type="text/javascript" src="js/jquery-3.1.1.js"></script>
<script type="text/javascript">
$(function() {
//默认数字0--10000,默认数字自增步长100
var buchang = 200;
var deg = 180 * buchang / 10000; //每个步长代表的度数
var degs = parseInt($(".num").text()) / buchang * deg; //先计算有几个步长,算出半圆要转的度数
var du = 0; //起始度数
var bu = 0; //数字自增步长
function zhuan() { $(".clip").css("transform", "rotate(" + du + "deg)");
$(".num").text(bu);
du += deg; bu += buchang;
if(du >= degs) {
clearInterval(setin);
} }
var setin = setInterval(zhuan, 30) })
</script>
</head> <body>
<div id="yibiao">
<div class="yuan1"></div>
<div class="clip"></div>
<div class="yuan2"></div>
<div class="num">5000</div>
</div>
</body> </html>

  

canvas仿芝麻信用分仪表盘的更多相关文章

  1. vue 使用canvas仿芝麻分信用表

    如图所示: 画布组件:dashboard.vue <template> <div> <canvas ref="canvas" v-if="c ...

  2. iOS仿支付宝芝麻信用仪表盘效果

    概述 自定义View之高仿支付宝芝麻信用分数仪表盘动画效果 详细 代码下载:http://www.demodashi.com/demo/10654.html 仿支付宝芝麻信用仪表盘效果 一.主要思路 ...

  3. 自定义View(三),仿支付宝芝麻信用自定义控件

    仿支付宝的芝麻信用仪表盘 实现的效果 实现的功能: 指针和数字动态改变 背景动态变化 没了... 代码如下 MyCustomView.java package com.example.testcust ...

  4. PHP接入芝麻信用续。

    前面,做好了,PHP查询芝麻信用. 客户又要求说,芝麻官方,发来邮件,还需要提交网站的数据给芝麻, 就是说接入芝麻SDK,还有一步,就是数据反馈. 大概芝麻分就是根据这些反馈的数据来计算的吧. 不多说 ...

  5. Canvas 仿百度贴吧客户端 loading 小球

    前言 几天前在简书上看到在一篇文章<Android仿百度贴吧客户端Loading小球>,看了一下作者,他写了两个好玩的 demo,效果图如下: 今天趁着周末有空,用 H5 的 Canvas ...

  6. 笔记︱金融风险控制基础常识——巴塞尔协议+信用评分卡Fico信用分

    每每以为攀得众山小,可.每每又切实来到起点,大牛们,缓缓脚步来俺笔记葩分享一下吧,please~ --------------------------- 本笔记源于CDA-DSC课程,由常国珍老师主讲 ...

  7. java 对接芝麻信用 -用芝麻私钥解密错误

    最近在做芝麻信用认证对接, 按照官方的文档,配置了,appid ,私钥公钥 ,然后把示例文档拷过来, 结果 总是报错, 芝麻私钥解密 ZMOP.decode_private_key_error, 调了 ...

  8. PHP 接入芝麻信用 注意 事项

    芝麻官方下载的SDK,跑不起来,百度搜索一番也没有发现太多的文章 ,只有一个CSDN博客写的一篇文章,比较有参考价值 详细查阅文档+几天测试整理以下几点注意事项: 接入芝麻API接口,应该分2步: 第 ...

  9. canvas仿屏幕保护运动线条

    canvas是H5中及其重要的一个新标签,它得出现不仅让前端做图形图表功能变得异常强大,还用极强的性能丰富前端渲染页面的能力. Life is not a problem to be solved, ...

随机推荐

  1. 如何用Chrome自带的截屏功能截取超过一个屏幕的网页

    提升程序员工作效率的工具/技巧推荐系列 推荐一个功能强大的文件搜索工具SearchMyFiles 介绍一个好用的免费流程图和UML绘制软件-Diagram Designer 介绍Windows任务管理 ...

  2. 在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图

    在Jerry写这篇文章时,通过Google才知道,SAP其实是有自己的3D模型视图显示解决方案的. 故事要从Right Hemisphere说起,这是一家专业的企业级2D/3D模型浏览及转换的软件供应 ...

  3. 【C++】cerr,cout,clog

    http://stackoverflow.com/questions/16772842/what-is-the-difference-between-cout-cerr-clog-of-iostrea ...

  4. uva10366 Faucet Flow

    每次找到两边离中心最高的板,如果等,再找外围的最高版...画图便于理解两边先找到距离(-1,1)最近的最大值L和R,因为可能存在多个最高的挡板.接着比较两个L和R的大小,相等的话分别分析两边,取最小值 ...

  5. gprc-java与golang分别实现服务端,客户端,跨语言通信(二.golang实现)

    1.编译器protoc, 下载地址:https://github.com/protocolbuffers/protobuf/releases  (下载对应的版本, 解压后放到go的bin中) 2.安装 ...

  6. Java中的类加载器--Class loader

    学习一下Java中的类加载器,这个是比较底层的东西,好好学习.理解一下.  一.类加载器的介绍 1.类加载器:就是加载类的工具,在java程序中用到一个类,java虚拟机首先要把这个类的字节码加载到内 ...

  7. CFNetwork framework

    iphone包含了很多框架和库,从底层的套接字到不同层次的封装,可以方便地给程序添加网络功能. (1)BSD套接字.最底层的套接字,这是Unix网络开发常用的API.如果从其他系统移植程序,而程序用的 ...

  8. 用Jenkins构建项目实战

    登录Jenkins,新建任务 输入一个任务名称,选择一个项目类型 使用自定义工作空间:使该项目独立于系统的工作空间 自动从Git下载源码,点击添加可以增加凭证 日程表的参数: 第一个参数代表的是分钟 ...

  9. Week06-继承、多态、抽象类与接口

    Week06-继承.多态.抽象类与接口 1. 本周学习总结 1.1 写出你认为本周学习中比较重要的知识点关键词 关键字:接口,Comparable,interface关键字,Comparator,继承 ...

  10. xshell连接Linux(centos6.8)失败的解决方法

    注意:本人使用的是Centos6.8版本. Centos7以上版本linux命令会又不一样的地方. 启动xshell终端进行连接服务器:使用命令:ssh + ip地址或是手动使用可视化操作窗口操作, ...