Canvas-Study

目录

1、绘制矩形

2、路径

3、三个方法绘制圆弧:

4、绘制二次、三次贝塞尔曲线

5、绘制三次贝塞尔曲线:

6、线条的颜色

7、线宽

8、线条末端样式

9、同一个 path 内,设定线条与线条间接合处的样式

10、绘制虚线

11、绘制文本的两种方法

12、获取文本的宽度

13、设置文本对齐方式

14、给文本添加样式

15、使用 Path2D 封装路径

16、设置全局透明度

17、渐变

        (1)线性渐变 createLinearGradient();

        (2)径向渐变 createRadialGradient(x, y, r, x1, y1, r1);

        (3)圆锥渐变

18、阴影颜色

19、绘制图片的三种方式

20、canvas 处理视频

21、变换

        (1)位移

        (2)缩放

        (3)旋转

        (4)使用变换矩阵 transform

22、图像的合成样式 globalCompositeOperation

23、根据路径进行裁剪

24、状态保存与恢复

25、判断一个点是否在路径范围之内

26、清空画布的三种方法


考虑浏览器的支持(基本上都支持了):

        支持 <canvas> 的浏览器会只渲染 <canvas> 标签,而忽略其中的替代内容。不支持 <canvas> 的浏览器则 会直接渲染替代内容。

        用文本替换:

<canvas> 你的浏览器不支持 canvas,请升级你的浏览器。 </canvas>

        用 <img> 替换:

<canvas> <img decoding="async" src="./temp.jpg"> </canvas>

基本格式:


<canvas id="c1" width="1000" height="500"></canvas>

// 拿到画布
let c1 = document.getElementById('c1');

if(c1.getContext){
    // 拿到画笔 有画布和画笔就可以画图了
    let brush = c1.getContext('2d');

    
    
}

1、绘制矩形

canvast 提供了三种方法绘制矩形:

  • 1、fillRect(x, y, width, height):绘制一个填充的矩形。
  • 2、strokeRect(x, y, width, height):绘制一个矩形的边框。
  • 3、clearRect(x, y, widh, height):清除指定的矩形区域,然后这块区域会变的完全透明。

说明:这 3 个方法具有相同的参数。

  • x, y:指的是矩形的左上角的坐标。(相对于canvas的坐标原点)
  • width, height:指的是绘制的矩形的宽和高

2、路径

使用路径绘制图形需要一些额外的步骤:

  1. 创建路径起始点
  2. 调用绘制方法去绘制出路径
  3. 把路径封闭
  4. 一旦路径生成,可以通过描边或填充路径区域来渲染图形。

下面是需要用到的方法:

  1. beginPath() 新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径
  2. moveTo(x, y) 把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。
  3. closePath() 闭合路径之后,图形绘制命令又重新指向到上下文中
  4. stroke() 通过线条来绘制图形轮廓
  5. fill() 通过填充路径的内容区域生成实心的图形
  6. lineTo(x, y) 绘制从当前位置到指定坐标x,y的一条直线

3、三个方法绘制圆弧:

1、arc(x, y, r, startAngle, endAngle, anticlockwise):

        以(x, y) 为圆心,以r 为半径,从 startAngle 弧度开始到endAngle弧度结束。anticlosewise 是布尔值,true 表示逆时针,false 表示顺时针(默认是顺时针)。

2、arcTo(x1, y1, x2, y2, radius):

         根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点 ;控制点x1,y1,终点x2,y2,起点到终点的角度。

3、

ctx.beginPath();

// 起始点 50 50
ctx.moveTo(50, 50);

//参数1、2:控制点1坐标 ,参数3、4:控制点2坐标,参数5:圆弧半径
ctx.arcTo(200, 50, 200, 200, 100);

ctx.lineTo(200, 200);

ctx.stroke();

arcTo 方法的说明:

这个方法可以这样理解:绘制的弧形是由两条切线所决定。

第 1 条切线:起始点 和 控制点1决定的直线。

第 2 条切线:控制点1 和 控制点2决定的直线。

4、绘制二次、三次贝塞尔曲线

quadraticCurveTo(cp1x, cp1y, x, y)

需要一个起始点

参数1、2:控制点坐标,

参数3、4:结束点坐标。

5、绘制三次贝塞尔曲线:

同样需要一个起始点,

bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)

  • 参数 1 和 2:控制点 1 的坐标
  • 参数 3 和 4:控制点 2 的坐标
  • 参数 5 和 6:结束点的坐标

6、线条的颜色

两个属性

fillStyle = color 设置填充颜色

strokeStyle = color 设置图形轮廓的颜色

备注:

        1. color 可以是表示 css 颜色值的字符串渐变对象或者图案对象

        2. 默认情况下,线条和填充颜色都是黑色。

        3. 一旦设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果要给每个图形上不同的颜色,需要重新设置 fillStyle 或 strokeStyle 的值。

设置图案样式:

// 图案样式
let img = new Image();
img.src = 'https://xxxxxxx.xxx.xx.cn';
img.onload = function (){                   // 等图片加载好了再开始画
    // 设置图案 第一个参数是 图片对象,第二个参数是 决定图案是否重复
    let pattern = pencil.createPattern(img, 'no-repeat');
    pencil.fillStyle = pattern;
    pencil.fillRect(0, 0, 600, 600);
}

7、线宽

        属性:lineWidth

        ctx.lineWidth = 20;

8、线条末端样式

属性:lineCap

共有三个值:

        1、butt:线条末端以方形结束

        2、round:线条末端以圆形结束

        3、square: 线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域

9、同一个 path 内,设定线条与线条间接合处的样式

        属性:lineJoin

取值:

        1、round :通过填充一个额外的,圆心在相连部分末端的扇形,绘制拐角的形状。 圆角的半径是线段的宽度。

        2、bevel :在相连部分的末端填充一个额外的以三角形为底的区域, 每个部分都有各自独立的矩形拐角。

        3、miter:(默认) 通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。

10、绘制虚线

        用 setLineDash 方法和 lineDashOffset 属性来制定虚线样式。

        setLineDash 方法接受一个数组,来指定线段与间隙的交替;

        lineDashOffset 属性设置起始偏移量。

ctx.setLineDash([20, 5]);         // [实线长度, 间隙长度]

ctx.lineDashOffset = -0;

tx.strokeRect(50, 50, 210, 210);

11、绘制文本的两种方法

  • fillText(text, x, y [, maxWidth]) 在指定的 (x,y) 位置填充指定的文本,绘制的最大宽度是可选的。
  • strokeText(text, x, y [, maxWidth]) 在指定的 (x,y) 位置绘制文本边框,绘制的最大宽度是可选的。
ctx.font = "100px sans-serif";

ctx.fillText("难得逍遥", 10, 100);

ctx.strokeText("天若有情", 10, 200);

12、获取文本的宽度

        cxt.measureText(text).width 得到文本的宽度

13、设置文本对齐方式

        使用 textAlign (需要在设置字体大小和类型之后)

brush.font = '30 楷书';
crush.textAlign = 'center';
crush.strokeText('江南好,风景旧曾谙', 375, 250);

14、给文本添加样式

  1. font = value 当前我们用来绘制文本的样式。这个字符串使用和 CSS font 属性相同的语法。 默认的字体是 10px sans-serif。
  2. textAlign = value 文本对齐选项。 可选的值包括:start, end, left, right, center。 默认值是 start。
  3. textBaseline = value 基线对齐选项,可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。。
  4. direction = value 文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。

15、使用 Path2D 封装路径

// 使用 Path2D 封装路径
let arcPath = new Path2D();            // 创建Path2D对象
arcPath.arc(100, 100, 90, 0, Math.PI * 1.4);       // 该对象是专门画一个圆的

pencil.stroke(arcPath);                 // 利用画笔将这个对象要画的图形轮廓画出来
pencil.fill(arcPath);				    // 填充

16、设置全局透明度

        属性:globalAlpha

        ctx.globalAlpha = 0.4;

17、渐变

        (1)线性渐变 createLinearGradient();

// canvas 设置线性渐变
let clg = pencil.createLinearGradient(100, 100, 300, 300);       // 对角线渐变 渐变起始点坐标 左上至右下
clg.addColorStop(0, '#fff');
clg.addColorStop(1, 'blue');
pencil.fillStyle = clg;                         // 按规定的渐变色进行填充


pencil.fillRect(100, 100, 300, 300);            // 绘制矩形,矩形的范围刚好是渐变的范围

        (2)径向渐变 createRadialGradient(x, y, r, x1, y1, r1);

// 设置径向渐变
// 径向渐变 内圆圆心的坐标+半径 外圆圆心的坐标+半径
let crl = pencil.createRadialGradient(300, 300, 1, 300, 300, 200);     
crl.addColorStop(0, 'yellow');
crl.addColorStop(1, 'green');
pencil.fillStyle = crl;            // 规定在指定的范围内进行填充


pencil.fillRect(100, 100, 500, 500);

        (3)圆锥渐变

// 圆锥渐变
pencil.beginPath();

// 起始的角度,圆心位置 范围是整个画布
let ccg = pencil.createConicGradient(0, 300, 300);     
ccg.addColorStop(0, '#fff');
ccg.addColorStop(1, '#888');
pencil.fillStyle = ccg;


pencil.arc(300, 300, 600, 0, Math.PI * 2);
pencil.fill();
pencil.closePath();


pencil.beginPath();
pencil.arc(300, 300, 80, 0, Math.PI * 2);
pencil.fillStyle = '#fff';
pencil.fill();
pencil.closePath();

18、阴影颜色

// 设置阴影
pencil.shadowOffsetX = 10;          // 水平的偏移量
pencil.shadowOffsetY = 10;          // 垂直的偏移量
pencil.shadowBlur = 5;              // 模糊度
pencil.shadowColor = 'pink';        // 阴影颜色


pencil.arc(300, 300, 100, 0, Math.PI *2);
pencil.stroke();

19、绘制图片的三种方式

// 绘制图片的三种方式
let img = new Image();
img.src = './picture.webp';
// 等图片加载好了就开始绘制
img.onload = function (){
  // 第一种方式,没有任何缩放,  第一个参数是图片的对象,后两个参数为图片放置的位置
  // pencil.drawImage(img, 0, 0);


  // 第二种方式   第一个参数为图片对象,第二三个参数为图片放置的位置(最左上角的坐标),后两个参数为原图片宽和高分别缩放到多少
  // pencil.drawImage(img, 0, 0, 600, 600);


  // 第三种方式 第一个参数为图片对象,第二三个参数为对原图片矩形裁剪的起始坐标,第四五个参数为裁剪的矩形的大小,第六七个参数
  // 为将图片放到画布上的起始点,第八九个参数为缩放的比例,这里裁剪的结果和画布的大小一致,则不用缩放
  pencil.drawImage(img, 50, 50, 600, 600, 0, 0, 600, 600);
}

canvas 的图片右键点击可以下载,但下载下来的是经过canvas处理的图片,而不是原来的图片

20、canvas 处理视频

<canvas id="canvas1" width="600" height="600"></canvas>
<button class="btn">start video OR puase video</button>
<video 
    src="./391092495_401692.MP4"
    width="300"
    height="300"
    controls
  	hidden
></video>

// canvas 重绘视频
let video = document.getElementsByTagName('video')[0];          // 获取原有的视频对象
let img = new Image();                                          // 构造水印图片
img.src = 'https://img2.baidu.com/it/u=2425133085,3559224002&fm=253&fmt=auto&app=138&f=JPEG?w=450&h=450';


let btn = document.getElementsByClassName('btn')[0];
btn.onclick = function(){                            // 用户触发点击事件时 播放视频,并实时将画面绘制到canvas画布上
    if(video.paused){                                // 做出判断,当前播放则暂停,当前暂停则继续播放
        video.play();
        render();
    }else{
        video.pause();
    }
}


function render(){
    pencil.drawImage(video, 0, 0, 600, 600);         // 注意顺序,先视频,再水印
    pencil.drawImage(img, 0, 0, 100, 100);
    requestAnimationFrame(render);                   // 重复绘制的动画
}

html 中对 video 设置属性 hidden 将原视频隐藏,则用户只能看见的是 canvas 中的内容。

而 video 也可以在 js 中自行构造

21、变换

注意 :

位移、缩放、旋转 变化的都是整个坐标系,所以要先进行坐标轴变换,再绘制图形。

        (1)位移

// 位移 translate    注意 位移的是坐标系
pencil.fillRect(0,0,50,50);                 // 在原坐标系下作矩形


pencil.translate(50,50);                    // 坐标系整体向下和向右各位移50     原来的图形不受影响
pencil.fillRect(0,0,50,50);                 // 在新的坐标系下作图

需要注意的是,translate 位移 是对坐标轴的位移,原来绘制好的图形不会再受影响

        (2)缩放

// 缩放 scale    仍然是对坐标系的缩放
pencil.strokeRect(0, 0, 50, 50);               // 原来的图形


pencil.scale(3, 2);                            // 水平 放大到原来的三倍,竖直放大到原来的两倍
pencil.strokeRect(0, 0, 50, 50);

        (3)旋转

// 旋转  rotate
pencil.rotate(Math.PI / 4);                     // 将画布整体旋转 45度
pencil.strokeRect(100, 100, 50, 50);

        (4)使用变换矩阵 transform

22、图像的合成样式 globalCompositeOperation

共有26中属性值

Canvas学习:globalCompositeOperation详解

使用 destination-out 实现一个刮刮卡


<body>
    <div class="text">特等奖!!!</div>
    <canvas id="c1" width="600" height="600">你的浏览器不支持canvas</canvas>
</body>
<style>
        html,body{
            position: relative;
        }
        .text {
            width: 600px;
            height: 600px;
            text-align: center;
            line-height: 600px;
            font-size: 2rem;
            position: absolute;
            z-index: 0;
        }
        #c1 {
            position: absolute;
            top: 0;
            left: 0;
            z-index: 10;
        }
</style>
<script>
    let canvas = document.getElementById('c1');
    if (canvas.getContext) {                        // 判断是否可用 canvas
        let pencil = canvas.getContext('2d');       // 获取上下文对象,创建画笔
        pencil.fillStyle = 'rgba(245,0,0,1)';       // 先填充好内容 覆盖
        pencil.fillRect(0, 0, 600, 600);

        var isClear = false;                        // 是否可刮

        // 注意 监听的是 canvas元素 即画布,不是画笔
        canvas.onmousedown = function () {          // 监听鼠标点击事件
            isClear = true;                         // 鼠标按下则可刮
        }

        canvas.onmouseup = function () {            // 抬起鼠标键 不可刮
            isClear = false;
        }

        canvas.onmousemove = function (e) {         
            if (isClear) {
                pencil.globalCompositeOperation = 'destination-out';            // 设置图形重叠的方式
                pencil.arc(e.pageX, e.pageY, 10, 0, Math.PI * 2);                           // 在鼠标周围刮一个圆
                pencil.fill();                                                  // 填充
            }
        }
    }
</script>

23、根据路径进行裁剪

裁剪后,除参照对象以外,其他区域都变成透明

        pencil.clip()         // 默认按照前面的图形进行裁剪

        pencil.clip(obj of Path2D)         // 传入一个 Path2D 的对象,则画布按照该对象的范围进行裁剪

24、状态保存与恢复

储存在栈中,将上一次的样式推到栈顶,恢复时,从栈顶取出上一次使用过的样式。

        pencil.save();

        pencil.restore();

25、判断一个点是否在路径范围之内

        pencil.isPointInPath(路径对象,x,y) ,返回boolean值

26、清空画布的三种方法

1、使用一个背景色填充画布:

brush.fillStyle = '#ffffff';
brush.fill(0, 0, canvas.width, canvas.height);

2、清空区域的方法 clearReat()

brush.clearRect(0, 0, canvas.width, canvas.height);

3、重设 canvas 的宽高

let width = canvas.width;
let height = canvas.height;

canvas.width = width;
canvas.height = height;

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

bodyHealthy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值