HTML5 Canvas
canvas是html5新加的标签,主要有2D和3D,2D的应用是动画和图像,3D的应用是游戏渲染。
1. 2D基础
1.1绘制线
<!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>canvas</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.moveTo(100,100);
ctx.lineTo(500,100)
ctx.strokeStyle = "#000";
ctx.stroke();
ctx.endPath();
}
</script>
</body>
</html>
1.3 绘制矩形
<!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>canvas</title>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = "green";
ctx.fillRect(100,100,500,1000)
}
</script>
</body>
</html>
1.4 绘制圆
<!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>canvas</title>
</head>
<body>
<canvas id="canvas" width="800" height="800"></canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.beginPath();
ctx.fillStyle = "green";
ctx.arc(100,100,80,0,Math.PI*2,true);
ctx.fill()
ctx.endPath();
}
</script>
</body>
</html>
1.5 绘制文字
<!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>canvas</title>
</head>
<body>
<canvas id="canvas" width="800" height="800"></canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = "#F47C7C";
ctx.font="30px Arial";
ctx.fillText("Hello World",10,50);
}
</script>
</body>
</html>
1.6 表格练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Canvas绘制表格</title>
</head>
<body style="padding: 100px;">
<canvas id="canvas" width="900" height="600" style="border:1px solid #000"></canvas>
<script>
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// 绘制表格
var marginXY = 10;
var rows = canvas.height / marginXY,
cols = canvas.width / marginXY;
// 绘制横线
for (var i=1; i<rows; i++){
// 起点
ctx.moveTo(0, i*marginXY);
// 终点
ctx.lineTo(canvas.width, i*marginXY);
}
// 绘制竖线
for (var i=1; i<cols; i++){
// 起点
ctx.moveTo(i*marginXY, 0);
// 终点
ctx.lineTo(i*marginXY, canvas.height);
}
// 绘制
ctx.strokeStyle = '#000';
ctx.lineWidth = .5;
ctx.stroke();
// 绘制坐标
var x0 = 100, y0 = 500;
var maxWidth = 500, maxHeight = 400;
ctx.beginPath();
ctx.moveTo(x0, y0);
ctx.lineTo(x0 + maxWidth, y0);
ctx.lineTo(x0 + maxWidth - marginXY, y0 - marginXY);
ctx.moveTo(x0 + maxWidth - marginXY, y0 + marginXY); // 起点
ctx.lineTo(x0 + maxWidth, y0);
ctx.moveTo(x0, y0);
ctx.lineTo(x0, y0 - maxHeight);
ctx.lineTo(x0 - marginXY, y0 - maxHeight + marginXY);
ctx.moveTo(x0 + marginXY, y0 - maxHeight + marginXY); // 起点
ctx.lineTo(x0, y0 - maxHeight);
ctx.strokeStyle = 'blue';
ctx.lineWidth = 2;
ctx.stroke();
// 绘制折线
var data = [20, 40, 30, 60, 30, 80, 20];
//设置缩放比例
var w = maxWidth / data.length,
h = maxHeight / 100; // 1: 100
//生成坐标点
var pointArr = [];
for(var i=0; i<data.length; i++){
pointArr.push({
x: x0 + (i+1) * w,
y: y0 - data[i] * h
});
}
console.log(pointArr);
// 绘制
ctx.beginPath();
ctx.moveTo(x0, y0);
for(var i=0; i<pointArr.length; i++){
ctx.lineTo(pointArr[i].x, pointArr[i].y);
}
ctx.strokeStyle = 'red';
ctx.lineWidth = 4;
ctx.stroke();
</script>
</body>
</html>
2. canvas动画
2.1动画原理
//requestAnimationFrame会根据刷新频率自动调用callback
(function drawFrame(){
window.requestAnimationFrame(drawFrame, canvas);
}());
2.2进度条练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>canvas动画</title>
<style>
body{
background:#000;
}
canvas{
border:1px solid #fff;
}
</style>
</head>
<body>
<canvas id="canvas" width='500' height="500">
<P>you browser not support canvas!</P>
</canvas>
<script>
window.onload = function(){
var canvas = document.getElementById('canvas')
context = canvas.getContext('2d'),
centerX = canvas.width/2,
centerY = canvas.height/2,
rad = Math.PI*2/100,
speed = 0.1;
//绘制蓝色外圈
function blueCircle(n){
context.save();
context.beginPath();
context.strokeStyle = "blue";
context.lineWidth = 12;
context.arc(centerX, centerY, 100 , -Math.PI/2, -Math.PI/2 + n*rad, false);
context.stroke();
context.restore();
}
//绘制绿色外圈
function whiteCircle(){
context.save();
context.beginPath();
context.strokeStyle = "green";
context.lineWidth = 12;
context.arc(centerX, centerY, 100 , 0, Math.PI*2, false);
context.stroke();
context.closePath();
context.restore();
}
//百分比文字绘制
function text(n){
context.save();
context.fillStyle = "#F47C7C";
context.font = "40px Arial";
context.textAlign = "center";
context.textBaseline = "middle";
context.fillText(n.toFixed(0)+"%", centerX, centerY);
context.restore();
}
//动画循环
(function drawFrame(){
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
whiteCircle();
text(speed);
blueCircle(speed);
if(speed > 100) speed = 0;
speed += 0.1;
}());
}
</script>
</body>
</html>
2.3弹动小球练习
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ball animate</title>
<style>
body {
margin:0;
padding:0;
height: 100%;
/*background: #000;*/
overflow: hidden;
}
canvas {
padding: 0;
background: #000;
border: 1px solid;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var SCREEN_WIDTH = window.innerWidth,
SCREEN_HEIGHT = window.innerHeight,
ACCURACY = 1, ACCURACY_COMPARE = 1e-5;
canvas.width = 500;
canvas.height = 500;
var context = canvas.getContext('2d'),
animation, running = false;
var Ball = function(){
// x 坐标
this.x = 100;
// y 坐标
this.y = 100;
// x 方向初始速度
this.vx = 10;
// y 方向初始速度
this.vy = 25;
// x 方向位移
this.dx = function() {
return this.s(this.vx, this.ax, this.dt);
};
// y 方向位移
this.dy = function() {
return this.s(this.vy, this.ay, this.dt);
};
// 计算位移
this.s = function(v, a, t){
return v * t + (1 / 2.0) * a * t * t;
};
// x 方向碰撞速度损失
this.loss_x = 0.8;
// y 方向碰撞速度损失
this.loss_y = 0.8;
// 水平方向加速度
this.ax = 0;
// 竖直方向加速度
this.ay = 1;
// 两帧之间的时间间隔
this.dt = 1;
// 小球半径
this.radius = 20;
// 小球质量
this.m = 1;
// 小球颜色
this.color = 'cyan';
};
// 小球绘制函数
Ball.prototype.draw = function() {
context.beginPath();
context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true);
context.closePath();
context.fillStyle = this.color;
context.fill();
};
// 清除小球
Ball.prototype.clear = function() {
context.clearRect(this.x - this.radius,
this.y - this.radius,
this.radius * 2,
this.radius * 2);
};
// 获取小球下一个状态
Ball.prototype.next = function() {
// 记录当前状态值
var current_x = this.x, current_vx = this.vx, t1, self = this,
current_y = this.y, current_vy = this.vy;
// 下一状态理想坐标
this.x += this.dx();
this.y += this.dy();
// 下一状态理想速度
this.vx = this.vx + this.ax * this.dt;
this.vy = this.vy + this.ay * this.dt;
function boundary(top, right, bottom, left) {
// 边界判断,预判下一状态是否碰撞下方墙壁
if (self.y > bottom) {
// 越界需要重新计算速度和坐标
// 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
self.vy = Math.sqrt(Math.abs(2 * self.ay * (bottom - current_y) + current_vy * current_vy));
self.vy = current_vy > 0 ? self.vy : -self.vy;
if (isNaN(self.vy)) {
self.vy = 0;
self.ay = 0;
self.y = bottom;
return false;
}
// 计算从当前位置到碰撞位置的时间
if (self.ay == 0) {
if (self.vy == 0) {
t1 = 0;
} else {
t1 = (bottom - current_y) / self.vy;
}
} else {
t1 = Math.abs((self.vy - current_vy) / self.ay);
}
// 碰撞后速度衰减并反向
self.vy = -self.vy * self.loss_y;
// 碰撞后反弹的位移位置
self.y = bottom + self.s(self.vy, self.ay, self.dt - t1);
// 位移小于阈值,则速度归零
if (bottom - self.y < ACCURACY) {
self.vy = 0;
self.y = bottom;
self.ay = 0;
}
}
else if (self.x > right) {
// 越界需要重新计算速度和坐标
// 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
self.vx = Math.sqrt(Math.abs(2 * self.ax * (right - current_x) + current_vx * current_vx));
self.vx = current_vx > 0 ? self.vx : -self.vx;
if (isNaN(self.vx)) {
self.vx = 0;
self.ax = 0;
self.x = right;
return false;
}
// 计算从当前位置到碰撞位置的时间
if (self.ax == 0) {
if (self.vx == 0) {
t1 = 0;
} else {
t1 = (right - current_x) / self.vx;
}
} else {
t1 = Math.abs((self.vx - current_vx) / self.ax);
}
// 碰撞后速度衰减并反向
self.vx = -self.vx * self.loss_x;
// 碰撞后反弹的位移位置
self.x = right + self.s(self.vx, self.ax, self.dt - t1);
// 位移小于阈值,则速度归零
if (right - self.x < ACCURACY) {
self.vx = 0;
self.ax = 0;
self.x = right;
}
}
else if (self.x < left) {
// 越界需要重新计算速度和坐标
// 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
self.vx = Math.sqrt(Math.abs(2 * self.ax * (current_x - left) + current_vx * current_vx));
self.vx = current_vx > 0 ? self.vx : -self.vx;
if (isNaN(self.vx)) {
self.vx = 0;
self.ax = 0;
self.x = left;
return false;
}
// 计算从当前位置到碰撞位置的时间
if (self.ax == 0) {
if (self.vx == 0) {
t1 = 0;
} else {
t1 = (current_x - left) / self.vx;
}
} else {
t1 = Math.abs((self.vx - current_vx) / self.ax);
}
// 碰撞后速度衰减并反向
self.vx = -self.vx * self.loss_x;
// 碰撞后反弹的位移位置
self.x = self.s(self.vx, self.ax, self.dt - t1);
// 位移小于阈值,则速度归零
if (self.x - left < ACCURACY) {
self.vx = 0;
self.ax = 0;
self.x = left;
}
}
else if (self.y < top) {
// 越界需要重新计算速度和坐标
// 计算刚好碰到边界之前的速度: vt = sqrt(2aS + v0^2)
self.vy = Math.sqrt(Math.abs(2 * self.ay * (current_y - top) + current_vy * current_vy));
self.vy = current_vy > 0 ? self.vy : -self.vy;
if (isNaN(self.vy)) {
self.vy = 0;
self.ay = 0;
self.y = top;
return false;
}
// 计算从当前位置到碰撞位置的时间
if (self.ay == 0) {
if (self.vy == 0) {
t1 = 0;
} else {
t1 = (top - current_y) / self.vy;
}
} else {
t1 = Math.abs((self.vy - current_vy) / self.ay);
}
// 碰撞后速度衰减并反向
self.vy = -self.vy * self.loss_y;
// 碰撞后反弹的位移位置
self.y = self.s(self.vy, self.ay, self.dt - t1);
// 位移小于阈值,则速度归零
if (self.y - top < ACCURACY) {
self.vy = 0;
self.ay = 0;
self.y = top;
}
}
else {}
}
boundary(0, canvas.width - this.radius, canvas.height - this.radius, 0);
};
function clear() {
context.fillStyle = 'rgba(0,0,0,0.3)';
context.fillRect(0,0,canvas.width,canvas.height);
}
var ball = new Ball(), animate;
function draw() {
clear();
ball.draw();
ball.next();
}
canvas.addEventListener('click',function(e){
if (!running) {
ball.x = e.clientX;
ball.y = e.clientY;
animate = setInterval(function() {
draw();
}, 20);
running = true;
} else {
running = false;
clearInterval(animate);
}
});
ball.draw();
</script>
</body>
</html>
3.canvas图像
3.1基础api
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>ball animate</title>
<style>
body {
margin:0;
padding:0;
height: 100%;
/*background: #000;*/
overflow: hidden;
}
canvas {
padding: 0;
background: #000;
border: 1px solid;
}
</style>
</head>
<body>
<canvas id="canvas" width="800" height="800"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
img.src = './1.png';
img.onload = function() {
ctx.drawImage(img,280,280)
}
// 绘制裁剪路径
//ctx.arc(100, 100, 75, 0, Math.PI*2, false);
//ctx.clip();
//ctx.fillRect(0, 0, 100,100);
</script>
</body>
</html>
3.2canvas放大镜效果练习
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body style="background: black;">
<canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
您的浏览器尚不支持canvas
</canvas>
<canvas id="offCanvas" style="display: none">
</canvas>
<script>
var canvas = document.getElementById("canvas")
var context = canvas.getContext("2d")
var offCanvas = document.getElementById("offCanvas")
var offContext = offCanvas.getContext("2d")
var image = new Image()
var isMouseDown = false
var scale
window.onload = function(){
canvas.width = 1152
canvas.height = 768
image.src = "img-lg.jpg"
image.onload = function(){
offCanvas.width = image.width
offCanvas.height = image.height
scale = offCanvas.width / canvas.width
context.drawImage( image , 0 , 0 , canvas.width , canvas.height )
offContext.drawImage( image , 0 , 0 )
}
}
function windowToCanvas( x , y ){
var bbox = canvas.getBoundingClientRect()
return {x:x-bbox.left , y:y-bbox.top}
}
canvas.onmousedown = function(e){
e.preventDefault()
isMouseDown = true
point = windowToCanvas( e.clientX , e.clientY )
console.log( point.x , point.y )
drawCanvasWithMagnifier( true , point )
}
canvas.onmouseup = function(e){
e.preventDefault()
isMouseDown = false
drawCanvasWithMagnifier( false )
}
canvas.onmouseout = function(e){
e.preventDefault()
isMouseDown = false
drawCanvasWithMagnifier( false )
}
canvas.onmousemove = function(e){
e.preventDefault()
if( isMouseDown == true ){
point = windowToCanvas( e.clientX , e.clientY )
console.log( point.x , point.y )
drawCanvasWithMagnifier( true , point )
}
}
function drawCanvasWithMagnifier( isShowMagnifier , point ){
context.clearRect( 0 , 0 , canvas.width , canvas.height )
context.drawImage( image , 0 , 0 , canvas.width , canvas.height )
if( isShowMagnifier == true ){
drawMagnifier( point )
}
}
function drawMagnifier( point ){
var mr = 200
var imageLG_cx = point.x * scale
var imageLG_cy = point.y * scale
var sx = imageLG_cx - mr
var sy = imageLG_cy - mr
var dx = point.x - mr
var dy = point.y - mr
context.save()
context.lineWidth = 10.0
context.strokeStyle = "#069"
context.beginPath()
context.arc( point.x , point.y , mr , 0 , Math.PI*2 , false )
context.stroke()
context.clip()
context.drawImage( offCanvas , sx , sy , 2*mr , 2*mr , dx , dy , 2*mr , 2*mr )
context.restore()
}
</script>
</body>
</html>
3.3canvas缩放效果练习
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body style="background: black;">
<canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
您的浏览器尚不支持canvas
</canvas>
<canvas id="watermark-canvas" style="display:none;margin:0 auto;border:1px solid #aaa;">
您的浏览器尚不支持canvas
</canvas>
<input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="0" style="display:block;margin:20px auto;width:800px"/>
<script>
var canvas = document.getElementById("canvas")
var context = canvas.getContext("2d")
var slider = document.getElementById("scale-range")
var image = new Image()
var watermarkCanvas = document.getElementById("watermark-canvas")
var watermarkContext = watermarkCanvas.getContext("2d")
window.onload = function(){
canvas.width = 1152
canvas.height = 768
var scale = slider.value
image.src = "img-lg.jpg"
image.onload = function(){
//缩放
drawImageByScale( scale )
slider.onmousemove = function(){
scale = slider.value
drawImageByScale( scale )
}
}
}
function drawImageByScale( scale ){
var imageWidth = 1152 * scale
var imageHeight = 768 * scale
x = canvas.width /2 - imageWidth / 2
y = canvas.height / 2 - imageHeight / 2
context.clearRect( 0 , 0 , canvas.width , canvas.height )
context.drawImage( image , x , y , imageWidth , imageHeight )
}
</script>
</body>
</html>
3.4canvas水印效果练习
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body style="background: black;">
<canvas id="canvas" style="display:block;margin:0 auto;border:1px solid #aaa;">
您的浏览器尚不支持canvas
</canvas>
<input type="range" id="scale-range" min="0.5" max="3.0" step="0.01" value="1.0" style="display:block;margin:20px auto;width:800px"/>
<canvas id="watermark-canvas" style="display:none;margin:0 auto;border:1px solid #aaa;">
您的浏览器尚不支持canvas
</canvas>
<script>
var canvas = document.getElementById("canvas")
var context = canvas.getContext("2d")
var slider = document.getElementById("scale-range")
var watermarkCanvas = document.getElementById("watermark-canvas")
var watermarkContext = watermarkCanvas.getContext("2d")
window.onload = function(){
canvas.width = 1152
canvas.height = 768
var image = new Image()
var scale = 1.0
image.src = "img-lg.jpg"
image.onload = function(){
drawImage( image , scale )
slider.onmousemove = function(){
scale = slider.value
drawImage( image , scale )
}
}
//setup watermark canvas
watermarkCanvas.width = 600
watermarkCanvas.height = 100
watermarkContext.font = "bold 50px Arial"
watermarkContext.lineWidth = "1"
watermarkContext.fillStyle = "rgba( 255 , 255 , 255 , 0.5 )"
watermarkContext.textBaseline = "middle";
watermarkContext.fillText( "SFY❤GYK" , 20 , 50 )
}
function drawImage( image , scale ){
imageWidth = 1152 * scale
imageHeight = 768 * scale
x = canvas.width /2 - imageWidth / 2
y = canvas.height / 2 - imageHeight / 2
context.clearRect( 0 , 0 , canvas.width , canvas.height )
context.drawImage( image , x , y , imageWidth , imageHeight )
context.drawImage( watermarkCanvas , canvas.width - watermarkCanvas.width ,
canvas.height - watermarkCanvas.height )
}
</script>
</body>
</html>
3.4canvas滤镜效果练习
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div style="margin: 20px auto; width:1700px;">
<canvas id="canvasa" width="800" height="560" style="display:block;float:left;border:1px solid #aaa;">
</canvas>
<canvas id="canvasb" width="800" height="560" style="display:block;float:right;border:1px solid #aaa;">
</canvas>
</div>
<div style="clear: both"></div>
<div style="text-align: center; margin-top:50px;font-size:20px;">
<a href = "javascript:greyEffect()" >Grey Effect</a>
<a href = "javascript:blackEffect()" >Black and White Effect</a>
<a href = "javascript:reverseEffect()" >Reverse Effect</a>
<a href = "javascript:blurEffect()" >Blur Effect</a>
<a href = "javascript:mosaicEffect()" >Mosaic Effect</a>
</div>
<script>
var canvasa = document.getElementById("canvasa")
var contexta = canvasa.getContext("2d")
var canvasb = document.getElementById("canvasb")
var contextb = canvasb.getContext("2d")
var image = new Image()
window.onload = function(){
image.src = "autumn.jpg"
image.onload = function(){
contexta.drawImage( image , 0 , 0 , canvasa.width , canvasa.height )
}
}
function greyEffect(){
var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var pixelData = imageData.data
for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){
var r = pixelData[i*4+0]
var g = pixelData[i*4+1]
var b = pixelData[i*4+2]
var grey = r*0.3+g*0.59+b*0.11
pixelData[i*4+0] = grey
pixelData[i*4+1] = grey
pixelData[i*4+2] = grey
}
contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
context.putImageData()
}
function blackEffect(){
var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var pixelData = imageData.data
for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){
var r = pixelData[i*4+0]
var g = pixelData[i*4+1]
var b = pixelData[i*4+2]
var grey = r*0.3+g*0.59+b*0.11
if(grey > 125){
pv = 255
}
else{
pv = 0
}
pixelData[i*4+0] = pv
pixelData[i*4+1] = pv
pixelData[i*4+2] = pv
}
contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasa.width , canvasa.height )
}
function reverseEffect(){
var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var pixelData = imageData.data
for( var i = 0 ; i < canvasb.width * canvasb.height ; i ++ ){
var r = pixelData[i*4+0]
var g = pixelData[i*4+1]
var b = pixelData[i*4+2]
pixelData[i*4+0] = 255 - r
pixelData[i*4+1] = 255 - g
pixelData[i*4+2] = 255 - b
}
contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
}
function blurEffect(){
var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var tmpPixelData = tmpImageData.data
var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var pixelData = imageData.data
var blurR = 3
var totalnum = (2*blurR + 1)*(2*blurR + 1)
for( var i = blurR ; i < canvasb.height - blurR ; i ++ )
for( var j = blurR ; j < canvasb.width - blurR ; j ++ ){
var totalr = 0 , totalg = 0 , totalb = 0
for( var dx = -blurR ; dx <= blurR ; dx ++ )
for( var dy = -blurR ; dy <= blurR ; dy ++ ){
var x = i + dx
var y = j + dy
var p = x*canvasb.width + y
totalr += tmpPixelData[p*4+0]
totalg += tmpPixelData[p*4+1]
totalb += tmpPixelData[p*4+2]
}
var p = i*canvasb.width + j
pixelData[p*4+0] = totalr / totalnum
pixelData[p*4+1] = totalg / totalnum
pixelData[p*4+2] = totalb / totalnum
}
contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width , canvasb.height )
}
function mosaicEffect(){
var tmpImageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var tmpPixelData = tmpImageData.data
var imageData = contexta.getImageData( 0 , 0 , canvasa.width , canvasa.height )
var pixelData = imageData.data
var size = 16
var totalnum = size*size
for( var i = 0 ; i < canvasb.height ; i += size )
for( var j = 0 ; j < canvasb.width ; j += size ){
var totalr = 0 , totalg = 0 , totalb = 0
for( var dx = 0 ; dx < size ; dx ++ )
for( var dy = 0 ; dy < size ; dy ++ ){
var x = i + dx
var y = j + dy
var p = x*canvasb.width + y
totalr += tmpPixelData[p*4+0]
totalg += tmpPixelData[p*4+1]
totalb += tmpPixelData[p*4+2]
}
var p = i*canvasb.width+j
var resr = totalr / totalnum
var resg = totalg / totalnum
var resb = totalb / totalnum
for( var dx = 0 ; dx < size ; dx ++ )
for( var dy = 0 ; dy < size ; dy ++ ){
var x = i + dx
var y = j + dy
var p = x*canvasb.width + y
pixelData[p*4+0] = resr
pixelData[p*4+1] = resg
pixelData[p*4+2] = resb
}
}
contextb.putImageData( imageData , 0 , 0 , 0 , 0 , canvasb.width, canvasb.height )
}
</script>
</body>
</html>
在使用上面的代码的时候会有跨域问题,解决方法如下:
npm install http-server -g
http-server -p 8081
canvas应用的场景有很多,写这篇文章参考了很多别人的总结,链接放在下面大家去看看:
炫丽的倒计时效果Canvas绘图与动画基础:https://www.imooc.com/learn/133
Canvas绘图详解:https://www.imooc.com/learn/185
Canvas玩转图像处理:https://www.imooc.com/learn/476
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。