Canvas教程文档
参考这里 https://www.runoob.com/w3cnote/html5-canvas-intro.html
Canvas的使用
1. Canvas基本绘画
代码语言:javascript复制<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Canvas基本绘制</title>
</head>
<body>
<canvas id="cavsElem" width='1200' height="600">
你的浏览器不支持canvas,请升级浏览器
</canvas>
<script>
/* 绘制圆形*/
//获得画布并上下文对象
var context = document.getElementById('cavsElem').getContext('2d');
context.beginPath(); //开始路径
context.strokeStyle = "yellow"; //设置描边颜色
context.lineWidth = 5; //设置线的粗细
context.arc(100, 100, 100, 0, 2 * Math.PI, true); //绘制圆形,true为逆时针
context.closePath(); //关闭路径
context.fillStyle = 'green'; //设置填充颜色
context.fill(); //填充
context.stroke(); //描边
/* 绘制弧形*/
context.beginPath(); //开始路径
context.strokeStyle = "#fff"; //设置描边颜色
context.lineWidth = 5; //设置线的粗细
context.arc(100, 150, 25, Math.PI / 6, 5 * Math.PI / 6, false); //绘制弧形,false为顺时针
context.stroke(); //描边
//绘制矩形
context.strokeStyle = "blue"; //设置描边颜色
context.strokeRect(190, 190, 210, 120); //矩形边框
context.fillRect(200, 200, 200, 100); //填充矩形
//清除矩形
context.clearRect(300, 50, 200, 200);
//绘制三角形
context.beginPath(); //开始路径
context.moveTo(700, 100); //三角形,左顶点,画笔移动到100,100
context.lineTo(400, 100); //右顶点,画一条线,从100,100 到 300,100
context.lineTo(700, 300); //底部的点,从100,100 到 300,300
context.closePath(); //结束路径
context.stroke(); //描边路径
//绘制图片
//创建图片对象
var img = new Image();
//设置图片路径
img.src = "../images/draw.jpg";
img.onload = function () {
//使用canvas绘制图片
context.drawImage(img, 750, 0);
};
</script>
</body>
</html>
效果如下
2. Canvas画一个时钟
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>drawClock</title>
</head>
<body>
<!-- 定义canvas画布,包括宽度和高度,还有背景颜色 -->
<canvas id="clock" width="1350" height="620"
style="display: block; position: relative; background:black;margin: 20px auto;">
你的浏览器不支持canvas标!
</canvas>
<!-- js脚本 -->
<script>
//获取上下文文档对象
var clock = document.getElementById('clock');
var cxt = clock.getContext('2d');
//画指针
function drawPointer(width, color, value, angle, startx, starty, endx, endy) {
cxt.save(); //先保存当前画布
cxt.lineWidth = width; //设置画笔的宽度
cxt.strokeStyle = color; //设置画笔的颜色
cxt.translate(550, 310); //重置异次元空间的原点坐标
cxt.rotate(value * angle * Math.PI / 180); //设置旋转的角度,参数是弧度
cxt.beginPath();
cxt.moveTo(startx, starty);
cxt.lineTo(endx, endy);
cxt.closePath(); //先闭合路径,再画线
cxt.stroke(); //开始画线
cxt.restore(); //将旋转后的线段返回给画布
}
//画刻度
function drawScale(size, width, color, value, startx, starty, endx, endy) {
for (var i = 0; i < size; i ) {
drawPointer(width, color, value, i, startx, starty, endx, endy);
}
}
//为表盘的中心填充颜色
function drawFill() {
cxt.save();
cxt.beginPath();
cxt.arc(550, 310, 7, 0, 360, false);
cxt.closePath();
cxt.fillStyle = "red";
cxt.fill();
cxt.restore();
}
//画时钟
function drawClock() {
cxt.clearRect(0, 0, 1350, 620); //清空整个画布
var now = new Date(); //获取系统时间,取出时,分,秒
var sec = now.getSeconds();
var min = now.getMinutes();
var hour = now.getHours();
min = sec / 60;
hour = min / 60;
if (hour > 12) hour -= 12;
cxt.beginPath();
cxt.lineWidth = 10;
cxt.strokeStyle = "blue";
cxt.arc(550, 310, 300, 0, 360, false);
cxt.closePath();
cxt.stroke();
drawScale(12, 7, "pink", 30, 0, -280, 0, -260); //画时刻度
drawScale(60, 5, "pink", 6, 0, -280, 0, -270); //画分刻度
drawPointer(7, "purple", hour, 30, 0, 12, 0, -210); //画时针
drawPointer(5, "yellow", min, 6, 0, 15, 0, -240); //画分针
drawPointer(4, "red", sec, 6, 0, 17, 0, -250); //画秒针
//细化秒针,为秒针加箭头
drawPointer(3, "red", sec, 6, -7, -235, 0, -255);
drawPointer(3, "red", sec, 6, 7, -235, 0, -255);
drawFill();
}
drawClock();
setInterval(drawClock, 1000); //setInterval()方法中表示每隔1000ms,就执行drawClock一次
</script>
</body>
</html>
效果如下
3. Canvas绘制黑客入侵效果
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>黑客入侵</title>
<style>
* {
margin: 0
}
canvas {
background: black;
display: block
}
</style>
</head>
<body>
<canvas></canvas>
<script>
var oC = document.querySelector('canvas');
var cxt = oC.getContext('2d');
var w = oC.width = window.innerWidth;
var h = oC.height = window.innerHeight;
var onOff = true;
window.addEventListener('resize', function () {
w = oC.width = window.innerWidth;
h = oC.height = window.innerHeight;
});
var arr = new Array(255).join('1').split('');
console.log(arr)
draw();
function draw() {
if (onOff) {
cxt.fillStyle = 'rgba(0,0,0,0.05)';
cxt.fillRect(0, 0, w, h);
} else {
cxt.clearRect(0, 0, w, h);
}
cxt.fillStyle = randomColor();
arr.map(function (value, index) {
cxt.font = '16px 宋体';
text = String.fromCharCode(65 Math.random() * 57); // 把ASCII转换成对应的字符串;
x = index * 10;
cxt.fillText(text, x, value);
arr[index] = ((value > h Math.random() * 500) ? 0 : value 15);
})
requestAnimationFrame(draw);
}
function randomColor() {
var r = Math.floor(Math.random() * 256);
var g = Math.floor(Math.random() * 256);
var b = Math.floor(Math.random() * 256);
return 'rgb(' r ',' g ',' b ')';
}
</script>
</body>
</html>
效果如下
4. Canvas绘制星星特效
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>stars</title>
<style>
* {
margin: 0;
padding: 0;
overflow: hidden;
}
html,
body {
width: 100%;
height: 100%;
/* background: linear-gradient(to top, palevioletred 0%, #fff 100%); */
background: no-repeat linear-gradient(to bottom, #dcdcdc 0%, #000 100%);
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
</body>
<script>
(function (win, doc) {
const maxW = win.innerWidth;
const maxH = win.innerHeight;
const maxSize = 5;
const minSize = 1;
let isMoving = false;
let timer = null;
let canvas = doc.getElementById('canvas');
canvas.width = maxW;
canvas.height = maxH;
let ctx = canvas.getContext('2d');
let stars = []; // 存放作为背景使用的星星
let move_stars = []; // 存放鼠标移动时绘制的星星
function CanvasStar(num) {
this.num = num;
};
CanvasStar.prototype = {
render() {
for (let i = 0; i < this.num; i ) {
let alpha = Math.random() 0.1;
stars[i] = new Star(i, getOneRandom(maxW), getOneRandom(maxH), getOneRandom(maxSize,
minSize), true, alpha);
}
animate();
}
};
function Star(id, x, y, r, isCache, dot_alpha) {
this.id = id;
this.x = x;
this.y = y;
this.r = r;
this.dot_alpha = dot_alpha;
this.show = .5; // 作用:控制 鼠标绘制点的隐藏
this.direct = getOneRandom(180) 180;
this.isCache = isCache;
this.cacheCanvas = doc.createElement('canvas');
this.ctx_cache = this.cacheCanvas.getContext('2d');
if (isCache) {
this.cache();
}
};
Star.prototype = {
draw() {
// 绘制一个Star
if (!this.isCache) {
let alpha = Math.random() 0.1;
ctx.save();
ctx.beginPath();
ctx.arc(this.x, this.y, this.r, 0, 2 * Math.PI, false);
ctx.closePath();
ctx.shadowColor = '#fff';
ctx.shadowBlur = 2 * this.r;
ctx.fillStyle = `rgba(255, 255, 255, ${ this.dot_alpha })`;
ctx.fill();
ctx.restore();
} else {
ctx.drawImage(this.cacheCanvas, this.x - 3 * this.r, this.y - 3 * this.r)
}
},
move() {
this.y -= 0.25;
if (this.y < -10) {
this.y = maxH 10;
}
this.draw();
},
// 使鼠标绘制的点抖动起来
shake(arr) {
this.show -= 0.01;
if (this.show < 0) {
return;
}
let speed = .5;
this.x = Math.cos(this.direct * Math.PI / 180) * speed;
this.y = Math.sin(this.direct * Math.PI / 180) * speed;
this.draw();
this.link();
},
link() {
if (!this.id) return;
let len = move_stars.length;
// 关键思想:取当前id,之前的4个点,每绘制一次就向前取4个点,以此类推
// 而不是move_stars最后的四个点,否则的话只有最后几个点会被连接起来
let arr = move_stars.slice(this.id - 3, this.id);
let endIdx = arr.length - 1;
ctx.save();
for (let i = endIdx; i >= 0; i--) {
if (i == endIdx && !!arr[endIdx]) {
ctx.moveTo(arr[endIdx].x, arr[endIdx].y);
ctx.beginPath();
ctx.lineTo(this.x, this.y);
}
if (i != endIdx && !!arr[i] && arr[i].show > 0) ctx.lineTo(arr[i].x, arr[i].y);
}
ctx.closePath();
ctx.strokeStyle = 'rgba(81, 196, 211, 0.6)';
ctx.stroke();
ctx.restore();
},
cache() {
this.cacheCanvas.width = 6 * this.r;
this.cacheCanvas.height = 6 * this.r;
this.ctx_cache.save();
this.ctx_cache.beginPath();
this.ctx_cache.arc(this.r * 3, this.r * 3, this.r, 0, 2 * Math.PI, false);
this.ctx_cache.closePath();
this.ctx_cache.shadowColor = '#fff';
this.ctx_cache.shadowBlur = 2 * this.r;
this.ctx_cache.fillStyle = `rgba(255, 255, 255, ${this.dot_alpha})`;
this.ctx_cache.fill();
this.ctx_cache.restore();
}
};
// 动画
function animate() {
ctx.clearRect(0, 0, maxW, maxH);
let len = stars.length;
for (let i = 0; i < len; i ) {
stars[i].move();
}
let len2 = move_stars.length;
if (isMoving) {
for (let i = 0; i < len2; i ) {
if (move_stars[i]) move_stars[i].shake(move_stars);
}
} else {
move_stars = []
}
requestAnimationFrame(animate);
};
// 获取区间内的随机数
function getOneRandom(max, min = 0) {
return Math.floor(Math.random() * (max - min) min);
};
// 获取正负号
function getSign() {
return Math.random() > .5 ? -1 : 1;
};
// 鼠标移动事件
doc.addEventListener('mousemove', function (e) {
let x = e.clientX,
y = e.clientY;
// 控制绘制密度 以及点之间的距离 两个重要的点
// 密度是控制绘制的数量 dis_x = Math.abs(x - pre_star.x);
// 距离是在已绘制的点基础上、控制点的间距
// 控制绘制密度 和 控制点之间的距离 不是一个功能哦(需要实际操作去体会, 文字很难表述~.~)
// 没有控制距离的话 绘制的图形,太规则了,不够分散 x = x getSign() * getOneRandom(50)
let len = move_stars.length;
let dis_x, dis_y;
if (!len) {
move_stars.push(new Star(len, x, y, getOneRandom(maxSize, 3), true, 1));
}
if (move_stars[len - 1]) {
// 当前的星还没有push到move_stars里,所以上个星是move_stars[len - 1]
let pre_star = move_stars[len - 1];
if (pre_star) {
dis_x = Math.abs(x - pre_star.x);
dis_y = Math.abs(y - pre_star.y);
}
x = x getSign() * getOneRandom(50);
y = y getSign() * getOneRandom(50);
if (dis_x > 5 && dis_y > 5) move_stars.push(new Star(len, x, y, getOneRandom(maxSize,
minSize), true, 1));
}
isMoving = true;
clearInterval(timer); // 清除上一次的定时器(此时还没触发)
timer = setInterval(function () {
isMoving = false;
clearInterval(timer); // 鼠标停止再清除下定时器
}, 500)
}, false);
window.CanvasStar = CanvasStar;
})(window, document);
</script>
<script>
let canvasStar = new CanvasStar(200);
canvasStar.render();
</script>
</html>
效果如下
5. Canvas网页涂鸦板增强版
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas案例-网页涂鸦板</title>
</head>
<body>
<!--<center></center>表示将标签内所有的内容居中-->
<center>
<canvas id="cavsElem">
你的浏览器不支持canvas,请升级浏览器
</canvas><br>
选择画笔颜色:<input type="color" value="#ff0000" id="mycolor" onchange=colorChange() />
<input type="button" value="清除" id="clear" onclick=clearAll()>
选择画笔粗细:<input type="number" id="gsize" value="1" min="1" onchange=sizeChange()>
</center>
<script>
//获得画布
var canvas = document.getElementById('cavsElem');
//准备画笔(获取上下文对象)
var context = canvas.getContext('2d');
//设置标签的宽高和边框
canvas.width = 900;
canvas.height = 600;
context.strokeStyle = document.getElementById("mycolor").value; //设置描边颜色
canvas.style.border = "1px solid #000";
//当鼠标按下触发onmousedown事件时,定义一个函数获取鼠标起始坐标
canvas.onmousedown = function (e) {
var x = e.clientX - canvas.getBoundingClientRect().left;
var y = e.clientY - canvas.getBoundingClientRect().top;
context.beginPath(); //开始规划路径
context.moveTo(x, y); //移动起始点
//当鼠标移动触发onmousemove事件时,定义一个函数获取绘制线条的坐标
canvas.onmousemove = function (event) {
var x = event.clientX - canvas.getBoundingClientRect().left;
var y = event.clientY - canvas.getBoundingClientRect().top;
// canvas.clearRect(0, 0, 900, 600);
context.lineTo(x, y); //绘制线条
context.stroke(); //绘制描边
};
//当鼠标按键被松开时,onmousemovet函数返回null
canvas.onmouseup = function (event) {
canvas.onmousemove = null;
};
};
/* 清除画布 */
function clearAll() {
//清除矩形
context.clearRect(0, 0, 900, 600);
}
/* 颜色选择 */
function colorChange() {
var mycolor = document.getElementById("mycolor");
var x = mycolor.value;
// console.log('x :', x);
context.strokeStyle = x; //设置描边颜色
}
/* 画笔粗细 */
function sizeChange() {
var mycolor = document.getElementById("gsize");
var x = mycolor.value;
context.lineWidth = x; //设置线的粗细
}
</script>
</body>
</html>
效果如下
6. 3D炫酷特效
代码语言:javascript复制<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3D特效</title>
<style>
body {
margin: 0;
padding: 0;
background: #FFF;
}
canvas {
position: absolute;
width: 100%;
height: 100%;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas;
var context;
var screenWidth;
var screenHeight;
var doublePI = Math.PI * 2;
var step = 0;
var points = [];
var focalLength = 500;
var bgGradient;
window.onload = function () {
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
window.onresize = function () {
screenWidth = window.innerWidth;
screenHeight = window.innerHeight;
canvas.width = screenWidth;
canvas.height = screenHeight;
bgGradient = context.createRadialGradient((screenWidth >> 1), screenHeight >> 1, screenWidth,
screenWidth >> 1, screenHeight >> 1, 0);
bgGradient.addColorStop(1, '#000');
bgGradient.addColorStop(0.2, '#900');
};
generatePoints();
window.onresize();
loop();
};
function generatePoints() {
var i = 2000;
for (i; i > -1; --i) {
var point3D = {
x: (1 - Math.random() * 2) * 600,
y: (1 - Math.random() * 2) * 600,
z: (1 - Math.random() * 2) * 600,
vx: 0,
vy: 0,
vz: 0
};
points.push(point3D);
}
}
window.getAnimationFrame =
window.requestAnimationFrame ||
window.webkitRequestAnimationFrame ||
window.mozRequestAnimationFrame ||
window.oRequestAnimationFrame ||
window.msRequestAnimationFrame ||
function (callback) {
window.setTimeout(callback, 16.6);
};
function loop() {
context.globalAlpha = 0.4;
context.fillStyle = bgGradient;
context.fillRect(0, 0, screenWidth, screenHeight);
context.globalAlpha = 1;
updatePoints();
renderPoints();
renderWire();
step = 0.02;
getAnimationFrame(loop);
}
function renderPoints() {
var i = points.length - 1;
for (i; i > -1; --i) {
var point = points[i];
var scale = focalLength / (point.z focalLength);
var px = (point.x * scale (screenWidth >> 1));
var py = point.y * scale (screenHeight >> 1);
drawPoint({
x: px,
y: py
}, scale);
}
}
function renderWire() {
context.globalAlpha = 0.02;
context.lineWidth = 1;
context.strokeStyle = '#FFF';
context.beginPath();
var i = points.length - 1;
for (i; i > -1; --i) {
var point = points[i];
var scale = focalLength / (point.z focalLength);
if (i === points.length - 1) context.moveTo(point.x * scale (screenWidth >> 1), point.y * scale (
screenHeight >> 1));
else context.lineTo(point.x * scale (screenWidth >> 1), point.y * scale (screenHeight >> 1));
}
if (Math.random() > 0.4) context.stroke();
context.closePath();
context.globalAlpha = 1;
}
function updatePoints() {
var i = points.length - 1;
for (i; i > -1; --i) {
var point = points[i];
point.x = Math.cos(step * 0.4) * 2;
point.y = Math.sin(step * 0.8) * 2;
point.z -= 2;
checkBounds(point);
}
}
function checkBounds(point) {
if (point.x < -2000) point.x = Math.random() * 2000;
else if (point.x > 2000) point.x = Math.random() * -2000;
if (point.y < -2000) point.y = Math.random() * 2000;
else if (point.y > 2000) point.y = Math.random() * -2000;
if (point.z < -500) point.z = Math.random() * 2400 200;
}
function drawPoint(point, scale) {
context.globalAlpha = scale;
context.fillStyle = '#FAA';
context.beginPath();
context.rect(point.x, point.y, (1.6 * scale > 0) ? 1.6 * scale : 1, (1.6 * scale > 0) ? 1.6 * scale : 1);
context.fill();
context.closePath();
context.globalAlpha = 1;
}
</script>
</html>
效果如下
总结
总的来说Canvas真的非常强大,但是要做出炫酷的作品,难度也很大,涉及了很多算法的实现,只是刚接触,需要更多的练习。 本文章花了很多时间搜集特效代码,对搜集的代码也自己认真的改善,和谐、整理后可以直接使用的。