一、初识canvas
<canvas>
标签定义图形,比如图表和其他图像,标签只是图形容器,必须使用脚本来绘制图形
语法格式:
<canvas id='myCanvas' width="200px" height="200px">
获得canvas
对象(获取画布元素):
var c = document.getElemenetById("myCanvas")
获得CanvasRenderingContext2D
对象,该对象提供基本的绘图命令:
var ctx = c.getContext("2d")
二、canvas绘制线条
绘直线
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Canvas绘线</title>
</head>
<body>
<canvas id="myCanvas" width="800px" height="600px"></canvas>
<script>
//获取画布元素
var canvas = document.getElementById("myCanvas")
//获取2维绘图对象
var ctx = canvas.getContext('2d')
//设置线宽
ctx.lineWidth = 3
//设置线的颜色
ctx.strokeStyle = 'red'
//设置填充色
ctx.fillStyle = 'blue'
//起点
ctx.moveTo(10,10)
//下一个点
ctx.lineTo(100,10)
// 下一个点
ctx.lineTo(100,100)
ctx.lineTo(10,100)
ctx.lineTo(10,10)
//执行绘图操作:fill()填充颜色 stroke()绘线
ctx.stroke()
ctx.fill()
//重新绘制
ctx.beginPath()
ctx.moveTo(200,10)
ctx.lineTo(200,300)
ctx.lineTo(300,300)
ctx.closePath() //闭合,不需要回到起点
ctx.stroke() //每个图形必须要添加这个方法去绘制
</script>
</body>
</html>
效果图:
三、鼠标绘图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>鼠标绘图</title>
</head>
<body>
<canvas id="myCanvas" width="800px" height="600px"></canvas>
<script>
//获取画布元素
var canvas = document.getElementById("myCanvas")
//获取2维绘图对象
var ctx = canvas.getContext('2d')
var flag = false
//按下定起点
canvas.onmousedown = function(e){
flag = true
//设置线宽
ctx.lineWidth = 3
//设置线的颜色
ctx.strokeStyle = 'yellowgreen'
ctx.beginPath()
}
//鼠标移入绘图
canvas.onmousemove = function(e){
if(!flag)return;
ctx.lineTo(e.clientX,e.clientY)
ctx.stroke()
}
// 放开鼠标绘制结束
canvas.onmouseup = function(e){
flag = false
}
</script>
</body>
</html>
效果图:
四、绘制矩形、圆、填充颜色、文字、阴影
//获取画布元素
var canvas = document.getElementById("myCanvas")
//获取2维绘图对象
var ctx = canvas.getContext('2d')
//设置线宽
ctx.lineWidth = 3
//设置线的颜色
ctx.strokeStyle = 'red'
//设置填充色
ctx.fillStyle = 'yellowgreen'
矩形
// 绘制矩形
ctx.rect(20,20,200,200)//ctx.rect(x坐标,y坐标,宽,高)
//执行绘图操作:fill()填充颜色 stroke()绘制
ctx.stroke()
ctx.fill()
效果图:
另外有空心矩形、实心矩形的写法:
空心矩形
ctx.strokeRect(20,20,100,100)
效果图:
实心矩形
ctx.fillRect(20,20,100,100)
效果图:
清除矩形区域
常用于做 “刮刮乐” 效果
//实心矩形
ctx.fillRect(20,20,100,100)
// 清除矩形区域
ctx.clearRect(30,30,50,50)
效果图:
圆
ctx.arc(300,300,100,0,Math.PI*2) //ctx.arc(x坐标,y坐标,半径,起始,角度))
ctx.stroke() //只画线
//ctx.fill() //只填充
效果图:
文字
ctx.font = "50px '微软雅黑'"; //文字样式
ctx.shadowColor = 'black'; //阴影颜色
ctx.shadowOffsetX = 5; //阴影X轴偏移量
ctx.shadowOffsetY = 5; //阴影Y轴偏移量
ctx.shadowBlur = 10; //阴影模糊范围
ctx.fillText("hello world",300,50) // ctx.fillText(text,x,y,maxWidth) 实心内容
ctx.strokeText("hello world",300,120) // ctx.fillText(text,x,y,maxWidth) 空心内容
效果图:
填充渐变色
// ctx.createLinearGradient(x0,y0,x1,y1) //(起始点的x轴,结束点的y轴,结束点的x轴,结束点的y轴)
//设置渐变方向 y轴变化:纵向渐变,x轴变化,横向渐变
var grd = ctx.createLinearGradient(0,0,0,200)
grd.addColorStop(0,'red')
grd.addColorStop(0.5,'white')
grd.addColorStop(1,'blue')
ctx.fillStyle = grd;
ctx.rect(10,10,200,200)
ctx.fill()
效果图:
五、实现人物移动动画
html页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>实现人物移动动画</title>
<script src="./demo.js"></script>
<style>
.btn{
cursor: pointer;
}
.main{
border:1px solid #ccc
}
</style>
</head>
<body>
<div class="main">
<canvas id="myCanvas" width="800px" height="600px" style='background: url(./map_gray.png);'></canvas>
<a class="btn play">开始</a>
<a class="btn stop">暂停</a>
</div>
</body>
</html>
对应的js:demo.js
window.onload = function () {
var arr = [{
x: 200,
y: 200
}, {
x: 400,
y: 400
}];
var speed = 2,
timer,
flag = false;
//图片预加载
var img = new Image();
img.src = './img.jpg'; //加载图片地址
// img.onload = function () {
//图片加载完成后才会绘制图片,我们这里触发条件是点击开始的时候触发,所以这里注释掉,在play()中触发
// ctx.drawImage(img, arr[0].x, arr[0].y, 30, 30)
// }
//获取画布元素
var canvas = document.getElementById("myCanvas");
//获取2维绘图对象
var ctx = canvas.getContext('2d');
//单击事件
document.querySelector(".play").onclick = function () {
play()
}
document.querySelector(".stop").onclick = function () {
stop()
}
//定时器,缓慢移动,
function play() {
// 每隔多少秒移动(绘图)一次
if (flag) return; //防止重复点击
timer = setInterval(draw, 100);
flag = true;
}
//点击暂停的时候,停止移动
function stop() {
clearInterval(timer);
flag = false;
}
//绘图操作
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height) //清除画布的内容
//处理移动时的位置
if (arr[0].x < arr[1].x) {
arr[0].x += speed;
}
if (arr[0].y < arr[1].y) {
arr[0].y += speed;
}
//绘制图片 drawImage(img,x,y.w.h)
ctx.drawImage(img, arr[0].x, arr[0].y, 30, 30)
//画行驶的轨迹
ctx.strokeStyle = "yellowgreen"
ctx.lineTo(arr[0].x, arr[0].y) //画点
ctx.stroke() //连线
}
};
六、canvas小游戏
玩法: 怪兽图标位置随机且固定;英雄图标初始位置固定且可以移动;当英雄移动到和怪兽重合时,得分+1,当英雄移动到超出边界时,游戏结束。
html页面:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>canvas小游戏</title>
<script src="./demo2.js"></script>
</head>
<body>
<div class="main">
<canvas id="myCanvas" width="600px" height="600px" style='border: 2px solid #ccc;'></canvas>
</div>
</body>
</html>
对应的js:demo2.js
window.onload = function () {
//获取画布元素
var canvas = document.getElementById("myCanvas");
//获取2维绘图对象
var ctx = canvas.getContext('2d');
// 初始化图片 :背景、英雄、怪兽
var bgi = new Image();
bgi.src = './bgi.webp'; //背景
var heroImg = new Image();
heroImg.src = './hero.png'; //英雄
var monsterImg = new Image();
monsterImg.src = './img.jpg'; //怪兽
//英雄和怪兽的坐标
var hero = {
x: 0,
y: 0,
speed: 1
}
var monster = {
x: 0,
y: 0
}
// 记录得分
var num = 0;
//设置变量存储键盘方向的keyCode
var keyDown = {}
//事件:监听键盘按下事件
addEventListener('keydown', function (e) {
//e.keyCode判断方向 上38 下40 左37 右39
keyDown[e.keyCode] = true
})
// 事件:监听键盘抬起事件
addEventListener('keyup', function (e) {
//键盘抬起时清除里面存值
delete keyDown[e.keyCode]
})
//开始游戏
function play() {
//按下的时候操作
if (38 in keyDown) { //向上
hero.y -= hero.speed
}
if (40 in keyDown) { //向下
hero.y += hero.speed
}
if (37 in keyDown) { //向左
hero.x -= hero.speed
}
if (39 in keyDown) { //向右
hero.x += hero.speed
}
// 没有按下的时候操作,设置初始位置,判断条件的写法是减小位置误差,使他们能重合
if (hero.x <= (monster.x + 2) && hero.y <= (monster.y + 2) &&
monster.x <= (hero.x + 2) && monster.y <= (hero.y + 2)) {
// 如果2个图片重合,则得分+1,重新设置英雄和怪兽的位置
num++;
hero.x = canvas.width / 2;
hero.y = canvas.height / 2;
monster.x = Math.floor(Math.random() * (canvas.width - 50));
monster.y = Math.floor(Math.random() * (canvas.height - 50));
}
}
//设置flag标志,判断什么时候调用动画神器,刷新界面,false表示未结束,未结束就可以不断刷新调用requestAnimationFrame
var flag = false;
//游戏结束
function over() {
//英雄超出边界游戏结束
if (hero.x <= 0 || hero.x >= canvas.width || hero.y <= 0 || hero.y >= canvas.height) {
flag = true
num = 0
alert('游戏结束!')
}
}
//渲染图片、文字,先渲染的图层在下面
function render() {
// 背景
ctx.drawImage(bgi, 0, 0, canvas.width, canvas.height)
//怪兽
ctx.drawImage(monsterImg, monster.x, monster.y, 30, 30)
//英雄
ctx.drawImage(heroImg, hero.x, hero.y, 30, 30)
//文字
ctx.font = "20px '微软雅黑'"
ctx.fillStyle = "yellowgreen"
ctx.fillText('你的得分:' + num, 30, 30)
}
render()
//初始化
function init() {
render();
play();
over();
if (!flag) { //动画神器 requestAnimationFrame,不断调用
requestAnimationFrame(init)
}
}
init()
//浏览器兼容
requestAnimationFrame = requestAnimationFrame ||
webkitRequestAnimationFrame ||
mozRequestAnimationFrame || msRequestAnimationFrame
};
效果图: