这是一个仿支付宝芝麻信用分的一个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>
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除!
RTX 5090要首发 性能要翻倍!三星展示GDDR7显存
三星在GTC上展示了专为下一代游戏GPU设计的GDDR7内存。
首次推出的GDDR7内存模块密度为16GB,每个模块容量为2GB。其速度预设为32 Gbps(PAM3),但也可以降至28 Gbps,以提高产量和初始阶段的整体性能和成本效益。
据三星表示,GDDR7内存的能效将提高20%,同时工作电压仅为1.1V,低于标准的1.2V。通过采用更新的封装材料和优化的电路设计,使得在高速运行时的发热量降低,GDDR7的热阻比GDDR6降低了70%。
更新日志
- 群星《歌手2024 第13期》[FLAC/分轨][325.93MB]
- 阿木乃《爱情买卖》DTS-ES【NRG镜像】
- 江蕾《爱是这样甜》DTS-WAV
- VA-Hair(OriginalBroadwayCastRecording)(1968)(PBTHAL24-96FLAC)
- 博主分享《美末2RE》PS5 Pro运行画面 玩家仍不买账
- 《双城之战2》超多新歌MV发布:林肯公园再次献声
- 群星《说唱梦工厂 第11期》[320K/MP3][63.25MB]
- 群星《说唱梦工厂 第11期》[FLAC/分轨][343.07MB]
- 群星《闪光的夏天 第5期》[320K/MP3][79.35MB]
- 秀兰玛雅.1999-友情人【大旗】【WAV+CUE】
- 小米.2020-我想在城市里当一个乡下人【滚石】【FLAC分轨】
- 齐豫.2003-THE.UNHEARD.OF.CHYI.3CD【苏活音乐】【WAV+CUE】
- 黄乙玲1986-讲什么山盟海誓[日本东芝版][WAV+CUE]
- 曾庆瑜1991-柔情陷阱[台湾派森东芝版][WAV+CUE]
- 陈建江《享受男声》DTS-ES6.1【WAV】