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函数也必须运行在服务器上。