canvas学习笔记

本文深入介绍了HTML5 Canvas的基本使用,包括如何创建和设置画布尺寸,以及通过JavaScript进行图形绘制。内容涵盖填充和描边矩形、路径绘制、圆弧绘制、透明度设置、线型和文本控制、渐变与阴影效果,以及图片绘制。此外,还探讨了使用面向对象思维来管理和更新Canvas上的图形,以及如何实现动画。
摘要由CSDN通过智能技术生成

canvas简介

以前,web上的动画都是由flash制作的,例如动画广告、游戏等。但是flash由许多缺点:要安装flash插件,漏洞多,卡顿、不流畅等…
h5提出的canvas标签,使得制作动画等变得轻量级

canvas基本使用

在页面中使用canvas,只需要在页面上添加一个canvas标签即可<canvas></canvas>
canvas标签有两个属性:widthheight,注意canvas的宽和高不要用css控制,负责会造成图片失真。

使用js绘制canvas步骤

  1. 获取画布,即获取到canvas的DOM元素getElementById()
  2. 得到画布的上下文,有两个:2d和3d。所有的图像绘制都是通过上下文的方法或者属性进行设置的getContext('2d')
  3. 绘制图形(所有颜色先设置,后绘制)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="myCanvas" width="300" height="400"></canvas>
    <script>
        // 1.获取画布元素
        let myCanvas = document.getElementById('myCanvas');
        // 2.获取上下文
        let ctx = myCanvas.getContext('2d')
        // 3.绘制图形--先设置颜色,后绘制元素
        ctx.fillStyle = 'orange'
        ctx.fillRect(10, 10, 100, 100)
    </script>
</body>
</html>

在这里插入图片描述

canvas的像素化

canvas一旦绘制图形成功,就会被像素化,也就是说canvas没有能力葱画布上再次得到这个图形,没有办法再去修改已经在画布上的内容。
如果想要这个canvas上的图形移动,就必须按照清屏-更新-渲染的逻辑进行编程,也就是重新画一次。这也是canvas的动画思想

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="myCanvas" width="300" height="400"></canvas>
    <script>
        const myCanvas = document.getElementById('myCanvas');
        const ctx = myCanvas.getContext('2d')
        let left = 0;
        ctx.fillStyle = 'orange'
        // 要重新绘制新图形  -- 擦除--更新--渲染
        setInterval(() => {
            // 擦除现有图形
            ctx.clearRect(0,0,300,400)
            // 重新绘制
            ctx.fillRect(left++, 10, 40, 40)
        }, 10)
    </script>
</body>
</html>

面向对象思维实现canvas

因为canvas不能得到已经绘制的对象,所以我们要维持对象的状态,此时我们使用面向对象的方式来维持canvas需要的属性和状态。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="myCanvas" width="500" height="500"></canvas>
    <script>
        const canvas = document.getElementById('myCanvas');
        const ctx = canvas.getContext('2d');

        // 创建一个矩形对象
        class Rect {
            constructor(x, y, width, height, color) {
                this.x = x;
                this.y = y;
                this.width = width;
                this.height = height;
                this.color = color;
            }

            update() {
                ++this.x
            }

            render() {
                ctx.fillStyle = this.color;
                ctx.fillRect(this.x, this.y, this.width, this.height);
            }
        }

        let rect1 = new Rect(0,20,20,10,'blue');
        let rect2 = new Rect(0,100,30,30,'green')
        setInterval(() => {
            ctx.clearRect(0,0,500,500);
            rect1.update();
            rect1.render();
            rect2.update();
            rect2.render();
        }, 10)
    </script>
</body>
</html>

canvas的绘制功能

mdn文档链接

绘制矩形

绘制填充一个矩形fillRect(x,y,width,height)

ctx.fillStyle='bule'
ctx.fillRect(0,0,200,50)

绘制一个矩形边框strokeRect(x,y,width,height)

ctx.strokeStyle='green'
ctx.strokeRect(0,70,200,50)

清除画布clearRect(x,y,width,height)

ctx.clearRect(0,0,600,600)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <button onClick="drawFillRect()">填充矩形</button>
    <button onClick="drawStokeRect()">矩形边框</button>
    <button onClick="clearRect()">擦除</button>

    <canvas id="myCanvas" width="200" height="200"></canvas>

    <script>
        const canvas = document.getElementById('myCanvas')
        const ctx = canvas.getContext('2d');
        
        // 绘制填充矩形
        function drawFillRect() {
            ctx.clearRect(0,0, 200, 200)
            ctx.fillStyle = 'green'
            ctx.fillRect(50, 50, 60, 70);
        }
        // 绘制矩形边框
        function drawStokeRect() {
            ctx.clearRect(0,0, 200, 200)
            ctx.strokeStyle = 'red';
            ctx.strokeRect(50, 50, 70, 70);
        }
        // 清除
        function clearRect() {
            ctx.clearRect(0, 0, 200, 200)
        }
    </script>
</body>
</html>

绘制路径

绘制路径的作用是为了设置一个不规则的多边形状态路径都是闭合的

绘制路径的步骤

  1. 开始路径并设置路径的起点beginPath(),也可通过moveTo(x,y)移动开始点到某位置
  2. 绘制路径(多次)lineTo(x,y)
  3. 闭合路径closePath()
  4. 填充或者绘制已经封闭路径的形状stroke()fill()
    在绘制路径时如果不封闭路径,会自动封闭(只针对fill)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="myCanvas" width="200" height="200"></canvas>

    <script>
        const canvas = document.getElementById('myCanvas')
        const ctx = canvas.getContext('2d');
        
        ctx.fillStyle = 'orange'
        ctx.strokeStyle = 'blue'
        // 1. 开始路径
        ctx.beginPath();
        // 2.绘制开始点
        ctx.moveTo(10, 20);
        // 3.绘制路径
        ctx.lineTo(20,100);
        ctx.lineTo(100, 100),
        ctx.lineTo(200,90);
        // 4.闭合路径
        ctx.closePath()
        // 5.填充或描边
        ctx.fill()
        ctx.stroke()
    </script>
</body>
</html>

在这里插入图片描述

绘制圆弧

arc(x,y,radius,startAngle,endAngle,anticclockwise)
画一个以(x,y)为圆心的以radius为半径的圆弧(圆),从startAngle开始到endAngle结束,按照anticlockwise给定的方向(默认为顺时针)来生成。

x,y:圆心
radius:半径
startAngle,endAngle:圆弧的起始位置,一个圆是2π,即2*Math.PI,0为三点钟方向
anticclockwise:顺时针还是逆时针,默认为false,顺时针

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <canvas id="myCanvas" width="500" height="500"></canvas>

    <script>
        const canvas = document.getElementById('myCanvas')
        const ctx = canvas.getContext('2d');
        
        ctx.fillStyle = 'blue';
        ctx.strokeStyle = 'red';
        
        // 以100,100为圆心,100为半径,从0到90顺时针的圆弧
        ctx.beginPath();
        ctx.arc(100, 100, 100, 0, 0.5 * Math.PI, false)
        ctx.stroke()
        ctx.closePath()
        
        // 绘制圆弧, 以100,100为圆心,100为半径,从0到90逆时针的圆弧
        ctx.beginPath();
        ctx.arc(300, 300,80, 0, 0.5 * Math.PI, true)
        ctx.fill()
    </script>
</body>
</html>

透明度

ctx.globalAlpha,值为0到1的数字

线型

  1. 线的粗细 lineWidth:默认为1.0,属性值为数字,没有单位
  2. 线的形状 lineCap:可选值为butt:线段末端以方形结束、round:线段末端圆形结束、square:线段末端以方形结束,但是增加了一个宽度和线段相同,高度是线段厚度一半的矩形区域。在这里插入图片描述
  3. 两段连接处的样式lineJoin:可选值round、bevel、miter
  4. 虚线的样式setLineDash([n1,n2,n3,n4...]),表示虚线的交替状态,最少接收两个参数,奇数位置表示画线的长度,偶数位置表示间隔长度, lineDashOffset:可以设置虚线的起始偏移量

文本

  1. font 设置文字样式
  2. textAlign设置文字水平对齐方式,可选值left, center, right, end, start,默认start
  3. fillText('文本', x, y)

渐变

渐变有两种方式:线性渐变和径向渐变

线性渐变

  1. createLinerGradient(x1,y1,x2,y2),指定渐变的开始点和结束点
  2. addColorStop(n, color),n为0到1的值,表示当前渐变的位置,color表示渐变的颜色

径向渐变

  1. createRadialGradient(x1,y1,r1,x2,y2,r2),指定渐变的开始圆形和结束圆形的xy坐标以及半径
  2. addColorStop(n, color),n为0到1的值,表示当前渐变的位置,color表示渐变的颜色

阴影

  1. shadowOffsetX,shadowOffsetY,偏移量
  2. shadowBlur,模糊值
  3. shadowColor,阴影颜色

图片

在这里插入图片描述

  1. 创建一个image元素 let img = new Image()
  2. 设置img的src
  3. 在图片加载完成后(onLoad)绘制图片: drawImage(image, x, y, width, height, cx, cy, cwidth, cheight) , width,height可选,如果没有则宽高保持原图片宽高。四个参数表示图片的位置和宽高。如果有8个参数,代表的是从x,y的位置开始,切下宽为width高为height的图形切片,将切片拉伸为cwidth,cheight的图片再放到cx,cy的位置

变形

canvas的变形指的是整个画布的变形,而不是元素的变形。
因为变形实际上是将整个画布进行变形,所以一旦变形操作多了,会让会不变得不可控。下面先学习保存和恢复画布状态。
save()保存画布状态;restore() 恢复canvas状态这两个API的使用相当于一个入栈出栈的过程:save()入栈,restore()出栈。

一个绘画状态包括:

  1. 当前应用的变形(即移动,旋转和缩放等)
  2. 以下这些属性:strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, lineDashOffset, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation, font, textAlign, textBaseline, direction, imageSmoothingEnabled
  3. 当前的裁切路径(clipping path)
    变形之前先备份,变形完成后恢复,不要影响下一次的操作
  1. 移动translate(x, y)
  2. 旋转rotate(deg:number)
  3. 缩放scale(xScale:number, yScale:number)

合成

合成其实就是我们常见的蒙版状态,本质就是如何进行压盖,如何进行显示
globalCompositeOpration

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值