canvas一直是前端开发中不可或缺的一种用来绘制图形的标签元素,比如压缩上传的图片、比如刮刮卡、比如制作海报、图表插件等,很多人在面试的过程中也会被问到有没有接触过canvas图形绘制。
定义
canvas元素用于图形的绘制,通过脚本 (通常是JavaScript)来完成。
canvas标签只是图形容器,您必须使用脚本来绘制图形。
浏览器支持
Internet Explorer 9、Firefox、Opera、Chrome 和 Safari 支持
那么本篇文章就通过一个时钟组件来熟悉使用一下关于canvas的api。
<!DOCTYPE html><html><head><meta charset="UTF-8" /><title>canvas时钟</title><style>*{margin:0;padding:0;}body{text-align:center;padding-top:100px;}</style></head><body><canvas id="clock" width="200px" height="200px"></canvas><script>(function(win){ ???function DrawClock(options){ ???????this.canvas = options.el; ???????this.ctx ???= this.canvas.getContext('2d');//方法返回一个用于在画布上绘图的环境 ???????this.width ?= this.ctx.canvas.width; ???????this.height = this.ctx.canvas.height; ???????this.r ?????= this.width / 2; ???????this.rem ???= this.width / 200; ???????this.digits = [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2]; ???????var self ???= this; ???????self.init(); ???????setInterval(function(){ ???????????self.init(); ???????}, 1000); ???} ???DrawClock.prototype = { ???????init: function(){ ???????????var ctx = this.ctx; ???????????ctx.clearRect(0, 0, this.width, this.height); ???//在给定的矩形内清除指定的像素 ???????????var now = new Date(); ???????????var hours = now.getHours(); ???????????var minutes = now.getMinutes(); ???????????var seconds = now.getSeconds(); ???????????var hour = hours >= 12 ? hours - 12 : hours; ???????????var minute = minutes + seconds / 60; ???????????this.drawBackground(); ???????????this.drawHour(hour, minute); ???????????this.drawMinute(minute); ???????????this.drawSecond(seconds); ???????????this.drawDot(); ???????????ctx.restore(); ???????}, ???????drawBackground: function(){ ???????????var ctx = this.ctx; ???????????var self = this; ???????????ctx.save(); ???????????ctx.translate(this.r, this.r); ????????//重新映射画布上的 (0,0) 位置 ???????????ctx.beginPath(); ???????????ctx.lineWidth = 8 * this.rem; ???????????ctx.arc(0, 0, this.r - ctx.lineWidth / 2, 0, 2 * Math.PI, false); ???//创建弧/曲线(用于创建圆形或部分圆) ???????????ctx.stroke(); ???????????ctx.font = 16 ?* this.rem + "px Arial";//设置或返回文本内容的当前字体属性 ???????????ctx.textAlign = "center"; ?????????????//设置或返回文本内容的当前对齐方式 ???????????ctx.textBaseline = "middle"; ??????????//设置或返回在绘制文本时使用的当前文本基线 ???????????this.digits.forEach(function(number, i){ ???????????????var rad = 2 * Math.PI / 12 * i; ???????????????var x = Math.cos(rad) * (self.r - 33 * self.rem); ???????????????var y = Math.sin(rad) * (self.r - 33 * self.rem); ???????????????ctx.fillText(number, x, y); ???????//在画布上绘制"被填充的"文本 ???????????}); ???????????//分钟的刻度,每分钟转6deg ???????????for (var i = 0; i < 60; i++){ ???????????????ctx.save(); ???????????????????????//保存当前环境的状态 ???????????????ctx.rotate(6 * i * Math.PI / 180); //旋转当前绘图 ???????????????ctx.beginPath(); ??????????????????//起始一条路径,或重置当前路径 ???????????????ctx.moveTo(0, -82 * this.rem); ????//把路径移动到画布中的指定点,不创建线条 ???????????????ctx.lineTo(0, -87 * this.rem); ????//添加一个新点,然后在画布中创建从该点到最后指定点的线条 ???????????????ctx.closePath(); ??????????????????//创建从当前点回到起始点的路径 ???????????????ctx.strokeStyle = '#000'; ?????????//设置或返回用于笔触的颜色、渐变或模式 ???????????????ctx.lineWidth = 1 * this.rem; ?????//设置或返回当前的线条宽度 ???????????????ctx.stroke(); ?????????????????????//绘制已定义的路径 ???????????????ctx.restore(); ????????????????????//返回之前保存过的路径状态和属性 ???????????} ???????????//小时的刻度,每小时转30deg ???????????for (var i = 0; i < 12; i++){ ???????????????ctx.save(); ???????????????ctx.rotate(30 * i * Math.PI / 180); ???????????????ctx.beginPath(); ???????????????ctx.moveTo(0, -79 * this.rem); ???????????????ctx.lineTo(0, -87 * this.rem); ???????????????ctx.closePath(); ???????????????ctx.strokeStyle = '#000'; ???????????????ctx.lineWidth = 2 * this.rem; ???????????????ctx.stroke(); ???????????????ctx.restore(); ???????????} ???????}, ???????drawHour: function(hour, minute){ ???????????var ctx = this.ctx; ???????????ctx.save(); ???????????ctx.beginPath(); ???????????var hRad = 2 * Math.PI / 12 * hour; ???????????var mRad = 2 * Math.PI / 12 / 60 * minute; ???????????ctx.rotate(hRad + mRad); ???????????ctx.lineWidth = 6 * this.rem; ???????????ctx.lineCap = "round"; ????????????????//设置或返回线条的结束端点样式 ???????????ctx.moveTo(0, 10 * this.rem); ???????????ctx.lineTo(0, -this.r / 2); ???????????ctx.stroke(); ???????????ctx.restore(); ???????}, ???????drawMinute: function(minute){ ???????????var ctx = this.ctx; ???????????ctx.save(); ???????????ctx.beginPath(); ???????????var rad = 2 * Math.PI / 60 * minute; ???????????ctx.rotate(rad); ???????????ctx.lineWidth = 3 * this.rem; ???????????ctx.lineCap = "round"; ???????????ctx.moveTo(0, 10 * this.rem); ???????????ctx.lineTo(0, -this.r + 26 * this.rem); ???????????ctx.stroke(); ???????????ctx.restore(); ???????}, ???????drawSecond: function(second){ ???????????var ctx = this.ctx; ???????????ctx.save(); ???????????ctx.beginPath(); ???????????ctx.fillStyle = "#c14543"; ???????????var rad = 2 * Math.PI / 60 * second; ???????????ctx.rotate(rad); ???????????ctx.moveTo(-3 * this.rem, 20 * this.rem); ???????????ctx.lineTo(3 * this.rem, 20 * this.rem); ???????????ctx.lineTo(1, -this.r + 26 * this.rem); ???????????ctx.lineTo(-1, -this.r + 26 * this.rem); ???????????ctx.fill(); ???//填充当前绘图(路径) ???????????ctx.restore(); ???????}, ???????drawDot: function(minute){ ???????????var ctx = this.ctx; ???????????ctx.beginPath(); ???????????ctx.fillStyle = "#fff"; ???????????ctx.arc(0, 0, 3 * this.rem, 0, 2 * Math.PI, false); ???????????ctx.fill(); ???????} ???}; ??????win.DrawClock = DrawClock;})(window);new DrawClock({el: document.getElementById("clock")});</script></body></html>
只要心中有丘壑,就能耕出二亩田!canvas时钟用到了canvas中大部分的api,通过学习canvas时钟的代码实现,很能了解canvas的属性和方法,同时,实现时钟效果时,用到了数学中的几何模型正弦sin和余弦cos以及弧度的计算方法,又重温了一把当年学数学时的许多乐趣,可谓是一举两得。
时钟效果图如下:
原生js之canvas时钟组件
原文地址:https://www.cnblogs.com/tnnyang/p/8951804.html