05. 图形渲染
于2023-01-03 11:08:54发布
34
线性渐变
使用createLinearGradient 和 addColorStop 函数可以实现线性渐变功能。
createLinearGradient(x1,y1,x2,y2);
x1:渐变的起始点x
y1:渐变的起始点y
x2:渐变的终点x
y2:渐变的终点y
该函数主要控制渐变的方向。如 :
paint.createLinearGradient(0, 0, 200, 0) // 从左到右
paint.createLinearGradient(0, 0, 0, 200) // 从上到下
paint.createLinearGradient(0, 0, 200, 200) // 左上角到右下角
paint.createLinearGradient(200, 200, 0, 0) // 右下角到左上角
addColorStop(position, color);
position : 此参数为一个0到1之间的数值。表示颜色占多少百分比
color : 颜色
该函数至少要有2个或者2个以上。和css的动画类似,代表从0%到100%的变化过程
例子
<!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>Document</title>
</head>
<body>
<canvas width="500" height="500" style="background:#000;"></canvas>
<script>
const paint = document.querySelector('canvas').getContext('2d');
var grd = paint.createLinearGradient(0, 0, 200, 0); // 从左到右
grd.addColorStop(0, 'red'); // 红色从0%开始
grd.addColorStop(1, 'yellow'); // 黄色从1%结束
paint.fillStyle = grd;
paint.fillRect(0, 0, 200, 200);
</script>
</body>
</html>
径向渐变
使用createRadialGradient和 addColorStop 函数可以实现径向渐变功能。
createRadialGradient(sx,sy,sr,ex, ey, er);
sx: 开始圆的圆心x坐标
sy: 开始圆的圆心y坐标
sr: 开始圆的圆心直径
ex: 结束圆的圆心x坐标
ey: 结束圆的圆心y坐标
er: 结束圆的圆心直径
例子
<!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>Document</title>
</head>
<body>
<canvas width="500" height="500" style="background:#000;"></canvas>
<script>
const paint = document.querySelector('canvas').getContext('2d');
const x = 250;
const y = 150;
const r = 20;
var grd = paint.createRadialGradient(x, y, r, x + 30, y + 30, r + 50);
grd.addColorStop(0, 'yellow');
grd.addColorStop(1, 'rgba(0,0,0,0)');
paint.fillStyle = grd;
paint.fillRect(0, 0, 500, 500);
</script>
</body>
</html>
颜色反转
颜色反转,就是对图形的每个像素进行颜色取反。
例子
const paint = document.querySelector('canvas').getContext('2d');
const img = new Image();
img.src = './mario.png';
img.onload = function () {
paint.drawImage(img, 0, 0);
const imgData = paint.getImageData(0,0,500,500);
const pexels = imgData.data;
for (let i = 0; i < pexels.length; i += 4) {
pexels[i] = 255 - pexels[i]; // R
pexels[i + 1] = 255 - pexels[i + 1]; // G
pexels[i + 2] = 255 - pexels[i + 2]; // B
}
paint.putImageData(imgData, 0, 0);
}
需要注意是即使是一张很小的图片,其像素点几乎都大于10万以上。也就是说上面的for循环至少需要循环10万次才能完成对图片的颜色取反。
灰度控制
有时候需要将图片变为灰色,其做法和上面的例子相似。
const paint = document.querySelector('canvas').getContext('2d');
const img = new Image();
img.src = './mario.png';
img.onload = function () {
paint.drawImage(img, 0, 0);
const imgData = paint.getImageData(0, 0, 500, 500);
const pexels = imgData.data;
for (let i = 0; i < pexels.length; i += 4) {
// 灰度计算
const color = pexels[i] * 0.3 + pexels[i + 1] * 0.59 + pexels[i + 2] * 0.11;
pexels[i] = color; // R
pexels[i + 1] = color; // G
pexels[i + 2] = color; // B
}
paint.putImageData(imgData, 0, 0);
}
阴影效果
const paint = document.querySelector('canvas').getContext('2d');
const img = new Image();
img.src = './mario.png';
img.onload = function () {
paint.shadowColor = '#ccc'; // 影子的颜色
paint.shadowBlur = 10; // 影子的羽化程度
paint.shadowOffsetX = 5; // 影子的x坐标
paint.shadowOffsetY = 15; // 影子的y坐标
paint.drawImage(img, 0, 0);
}
透明度
const paint = document.querySelector('canvas').getContext('2d');
const img = new Image();
img.src = './mario.png';
img.onload = function () {
paint.globalAlpha = 0.5;
paint.drawImage(img, 0, 0);
}
截取画布的内容
有时候我们需要把一个画布的内容复制到另外一个画布中,这是就需要借助getImageData 和 putImageData函数
getImageData(x,y,w,h)
/*
截取画布的x坐标
截取画布的y坐标
截取画布的宽
截取画布的高
*/
putImageData(imageData,x,y,sx,sy,sw,sh)
/*
调用getImageData返回的ImageData对象
x坐标
y坐标
图片绘制的起始位置x
图片绘制的起始位置y
绘制图片的区域的
绘制图片的区域的高
*/
putImageData从第4个参数开始可以省略,即:putImageData(imageData,x,y)传3个参数即可。这样代表将得到的ImageData对象数据全部绘制到新的画布上。
例子
<!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>Document</title>
</head>
<body>
<canvas id="c1" width="500" height="500" style="background:#000;"></canvas>
<canvas id="c2" width="500" height="500" style="background:#000;"></canvas>
<script>
const paint = document.getElementById('c1').getContext('2d');
const paint2 = document.getElementById('c2').getContext('2d');
const img = new Image();
img.src = './mario.png';
img.onload = function () {
paint.drawImage(img, 0, 0);
const imgDate = paint.getImageData(0, 0, 500, 500);
paint2.putImageData(imgDate, 0, 0);
}
</script>
</body>
</html>
需要注意的是,getImageData 和 putImageData函数不能在本地上运行。必须要服务器上运行,并且图片的目录必须和html文 件在同一个目录,否则将会报以下错误 :
把画布转换成图片
有时候,我们玩游戏的时候,经常想把精彩的一瞬间截取下来。这时可以使用toDataURL函数。该函数返回一串base64数据。
例子
<!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>Document</title>
</head>
<body>
<canvas width="500" height="500" style="background:#000;"></canvas>
<img src="" alt="">
<script>
const cvs = document.querySelector('canvas');
const paint = cvs.getContext('2d');
const img = new Image();
img.src = './mario.png';
img.onload = function () {
paint.drawImage(img, 0, 0);
document.querySelector('img').src = cvs.toDataURL("image/png");
}
</script>
</body>
</html>
长按图片即可保存,需要注意的是,toDataURL函数也必须运行在服务器上。