canvas简述(一)
canvas是HTML5推出的画布技术 有2D和3D 目前3D兼容性很差但相信随着VR的兴起 3D也会逐渐发力 目前只讲述关于2D 相关的API 以及 业务逻辑 常用场景 游戏等等
API部分
<style> canvas{ border:solid 2px red } </style> <canvas id="cvs" width="800" height="800"></canvas> </head> <body> <script> //获取canvas以及其上下文对象 var cvs = document.querySelector('#cvs') var ctx = cvs.getContext('2d') //开始绘制 ctx.beginPath() ctx.moveTo(200,200) ctx.lineTo(200,400) ctx.lineTo(100,400) ctx.lineWidth = 15 ctx.closePath() ctx.strokeStyle = 'red' ctx.fillStyle = 'blue' ctx.stroke() ctx.fill() //上面自己绘制了一个三角形 </script>
上面自己绘制了一个三角形 在canvas中的路径 良好的习惯每次 绘制结束 都要闭合 每次绘制开始都要重新开启路径 第一步定点 然后 绘制 路径 填充非常简单
下面放canvas绘制矩形 以及 圆弧 以及 绘制图片的API demo
ctx.fillStyle = 'red' ctx.fillRect(200,200,200,200) ctx.strokeStyle = 'blue' ctx.strokeRect(400,400,400,400)
上面绘制了两个canvas预定义的 实心矩形和 空心矩形
在绘制圆形之前首先要明白canvas 圆形绘制是根据弧度制的 也就是角度跟弧度弧度是成比例的 是什么一个关系 圆的周长 = 2πr 如果将360° 跟 周长划一个关系的话 那么必须提取一个唯一的变量那就是r 在不同大小的圆下r也是不同的
将r提取出来 周长 / 2π = r 360° / 2π = 57.29° 那么我们就可以说 无论在什么情况下 1r 的弧度就等于 = 57.29° 的角度 那么有了这个对等的关系就非常简单了 我们可以假设360°就是 2π 的弧度 实际上canvas也是这么实现的 这两个是常量 在角度 和 r 有一个对等的比例关系下 可以将其忽略 在这个前提下 那么如果我们要计算30°的弧度是多少就非常简单了 就是360 / 30 * 2π 这样我们就计算出了30 的弧度 下面讲述一下API用法
//下面是圆弧的绘制 ctx.arc(200,200,100,0,2 * Math.PI,false) ctx.fillStyle = 'red' ctx.lineWidth = 10 ctx.strokeStyle = 'blue' ctx.fill() ctx.stroke()
在canvas中所有呈现出来的元素立即被像素化 因此无法像DOM一样操作canvas中的元素 只能通过画布帧动画的概念来实现各种动画游戏效果
下面一个圆球动画的简例:
//获取canvas以及其上下文对象 var cvs = document.querySelector('#cvs') var ctx = cvs.getContext('2d') let x = 100, x1 = 100, x2 = 100 setInterval(function(){ x += 20 x1 += 40 x2 += 60 ctx.clearRect(0,0,800,800) ctx.beginPath() ctx.fillStyle = 'blue' ctx.arc(x,100,50,0,2*Math.PI,false) ctx.fill() ctx.beginPath() ctx.fillStyle = 'blue' ctx.arc(x1,200,50,0,2*Math.PI,false) ctx.fill() ctx.beginPath() ctx.fillStyle = 'blue' ctx.arc(x2,300,50,0,2*Math.PI,false) ctx.fill() },100)
在多个元素运动和canvas游戏中一般采用的是 面向对象的方式 接下来用渐进增强的方式慢慢解析
<script> //获取canvas以及其上下文对象 var cvs = document.querySelector('#cvs') var ctx = cvs.getContext('2d') //运动元素构造函数 function Ball (x,y,r,speed){ this.x = x this.y = y this.r = r this.speed = speed actorsAll.push(this) } const actorsAll = [] //更新函数 Ball.prototype.update = function(){ this.x += this.speed } //渲染函数 Ball.prototype.render = function(){ ctx.beginPath() ctx.arc(this.x,this.y,this.r,0,2 * Math.PI,false) ctx.fillStyle = 'yellow' ctx.fill() } new Ball(100,100,30,1) new Ball(100,200,30,2) new Ball(100,300,30,3) new Ball(100,400,30,4) setInterval(function(){ ctx.clearRect(0,0,800,800) actorsAll.forEach(value => { value.update() value.render() }) }) </script>
使用面向会使代码更加的规整 已读 canvas中运用面向对象是一种非常好的思路
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> canvas{ border:solid 2px red } </style> <canvas id="cvs" ></canvas> </head> <body> <script> //获取canvas以及其上下文对象 var cvs = document.querySelector('#cvs') var ctx = cvs.getContext('2d') cvs.width = document.documentElement.clientWidth cvs.height = document.documentElement.clientHeight //运动元素构造函数 function Ball(x,y){ this.x = x this.y = y this.color = `rgba(${parseInt(Math.random()*256)},${parseInt(Math.random()*256)},${parseInt(Math.random()*256)},0.8)` this.r = 30 this.dx = parseInt(Math.random() * 17) - 8 this.dy = parseInt(Math.random() * 17) - 8 actorAll.push(this) } const actorAll = [] //渲染函数 Ball.prototype.render = function(){ ctx.beginPath() ctx.fillStyle = this.color ctx.arc(this.x,this.y,this.r,0,2 * Math.PI,false) ctx.fill() } //更新函数 Ball.prototype.update = function(){ console.log(this.x) console.log(this.y) this.x += this.dx this.y += this.dy this.r -- if(this.r <= 0){ this.godie() } } //删除函数 Ball.prototype.godie = function(){ actorAll.forEach((value,i) => { if(this === value){ actorAll.splice(i,1) } }) } cvs.addEventListener('mousemove',function(event){ new Ball(event.clientX,event.clientY) }) setInterval(function(){ ctx.clearRect(0,0,cvs.width,cvs.height) actorAll.forEach(value => { value.update() value.render() }) },30) </script> </body> </html>