canvas

canvas基本用法

一、canvas简介

`<canvas>` 是 `HTML5` 新增的,一个可以使用脚本(通常为`JavaScript`)在其中绘制图像的 `HTML` 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
`Canvas`是由`HTML`代码配合高度和宽度属性而定义出的可绘制区域。`JavaScript`代码可以访问该区域,类似于其他通用的二维`API`,通过一套完整的绘图函数来动态生成图形。

二、Canvas基本使用

2.1canvas元素

<canvas>看起来和<img>标签一样,只是 <canvas> 只有两个可选的属性 width、heigth 属性,而没有 src、alt 属性。canvas中最后的canvas不可以省略,必须要写。

`<canvas id="tutorial" width="300" height="300"></canvas>`

​ 如果不给<canvas>设置widht、height属性时,则默认 width为300、height为150,单位都是px。也可以使用css属性来设置宽高,但是如宽高属性和初始比例不一致,他会出现扭曲。所以,建议永远不要使用css属性来设置<canvas>的宽高

2.2渲染上下文(Thre Rending Context)

<canvas>会创建一个固定大小的画布,会公开一个或多个 渲染上下文(画笔),使用 渲染上下文来绘制和处理要展示的内容。

let canvas = document.getElementById('tutorial');
//获得 2d 上下文对象
let ctx = canvas.getContext('2d');

三、矩形的绘制

3.1绘制矩阵的属性

fillStyle = color 使用内部方式描述颜色和样式的属性。

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

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

clearRect(x, y, widh, height) 清除指定的矩形区域,然后这块区域会变的完全透明。

x, y:指的是矩形的左上角的坐标。(相对于canvas的坐标原点)

width, height:指的是绘制的矩形的宽和高。

3.2绘制填充矩形

    let canvas = document.querySelector("canvas");
    let ctx = canvas.getContext("2d");
    ctx.fillStyle = "#ff6"  
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = "rgb(200,0,0)";
    ctx.fillRect(10, 10, 55, 50);

四、添加样式和颜色

4.1fillStyle

fillStyle = color设置图形的填充颜色

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

  1. color 可以是表示 css 颜色值的字符串、渐变对象或者图案对象。
  2. 默认情况下,线条和填充颜色都是黑色。
  3. 一旦您设置了 strokeStyle 或者 fillStyle 的值,那么这个新值就会成为新绘制的图形的默认值。如果你要给每个图形上不同的颜色,你需要重新设置 fillStylestrokeStyle 的值。
function draw(){
  var canvas = document.getElementById('tutorial');
  if (!canvas.getContext) return;
  var ctx = canvas.getContext("2d");
  for (var i = 0; i < 6; i++){
    for (var j = 0; j < 6; j++){
      ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ',' +
        Math.floor(255 - 42.5 * j) + ',0)';
      ctx.fillRect(j * 50, i * 50, 50, 50);
    }
  }
}
draw();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BGOnQ9ya-1597934678188)(/img/bVbLCXN)]

4.2strokeStyle

function draw() {
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    for (var i = 0; i < 6; i++) {
        for (var j = 0; j < 6; j++) {
            ctx.strokeStyle = `rgb(${randomInt(0, 255)},${randomInt(0, 255)},${randomInt(0, 255)})`;
            ctx.strokeRect(j * 50, i * 50, 40, 40);
        }
    }
}
draw();
function randomInt(from, to) {
    return parseInt(Math.random() * (to - from + 1) + from);
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TDhdxIXE-1597934678190)(/img/bVbLCYb)]

4.3Transparency(透明度)

4.3.1 lineWidth = value

线宽。只能是正值。默认是1.0

起始点和终点的连线为中心,上下各占线宽的一半

4.3.2 lineCap = type

线条末端样式。

共有3个值:

  1. butt:线段末端以方形结束

  2. round:线段末端以圆形结束

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

        let canvas = document.querySelector("canvas");
        let ctx = canvas.getContext("2d");

        let lineCaps = ["butt", "round", "square"];

        for (var i = 0; i < 3; i++) {
            ctx.beginPath();
            ctx.moveTo(20 + 30 * i, 30);
            ctx.lineTo(20 + 30 * i, 100);
            ctx.lineWidth = 20;
            ctx.lineCap = lineCaps[i];
            ctx.stroke();
        }

        ctx.beginPath();  
        ctx.moveTo(0, 30);
        ctx.lineTo(300, 30);

        ctx.moveTo(0, 100);
        ctx.lineTo(300, 100)

        ctx.strokeStyle = "red";
        ctx.lineWidth = 1;
        ctx.stroke();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KiflReHl-1597934678192)(/img/bVbLCY0)]

4.3.3 lineJoin = type

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

共有3个值round, bevelmiter

  1. round

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

  2. bevel

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

  3. miter(默认)

    通过延伸相连部分的外边缘,使其相交于一点,形成一个额外的菱形区域。

        function draw() {
            var canvas = document.getElementById('tutorial');
            if (!canvas.getContext) return;
            var ctx = canvas.getContext("2d");
            var lineJoin = ['round', 'bevel', 'miter'];
            ctx.lineWidth = 20;
            for (var i = 0; i < lineJoin.length; i++) {
                ctx.lineJoin = lineJoin[i];
                ctx.beginPath();
                ctx.moveTo(50, 50 + i * 50);
                ctx.lineTo(100, 100 + i * 50);
                ctx.lineTo(150, 50 + i * 50);
                ctx.lineTo(200, 100 + i * 50);
                ctx.lineTo(250, 50 + i * 50);
                ctx.stroke();
            }
        }
        draw();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iVx1x9ZE-1597934678195)(/img/bVbLC0s)]

4.3.4 虚线

setLineDash 方法和 lineDashOffset 属性来制定虚线样式. setLineDash 方法接受一个数组,来指定线段与间隙的交替;lineDashOffset属性设置起始偏移量.

 function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    
    ctx.setLineDash([20, 5]);  // [实线长度, 间隙长度]
    ctx.lineDashOffset = -0;
    ctx.strokeRect(50, 50, 210, 210);
}
draw(); 

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HFVbS90u-1597934678197)(/img/bVbLC0K)]

五、绘制路径(path)

图形的基本元素是路径。
路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。
一个路径,甚至一个子路径,都是闭合的。

使用路径绘制图形需要一些额外的步骤:
1.  创建路径起始点
2.  调用绘制方法去绘制出路径
3.  把路径封闭
4.  一旦路径生成,通过描边或填充路径区域来渲染图形。
绘制路径用到的方法
  1. beginPath()
    新建一条路径,路径一旦创建成功,图形绘制命令被指向到路径上生成路径

  2. moveTo(x, y)
    把画笔移动到指定的坐标(x, y)。相当于设置路径的起始点坐标。

  3. closePath()
    闭合路径之后,图形绘制命令又重新指向到上下文中

  4. stroke()
    通过线条来绘制图形轮廓

  5. fill()
    通过填充路径的内容区域生成实心的图形

5.1 绘制线段

function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath(); //新建一条path
    ctx.moveTo(50, 50); //把画笔移动到指定的坐标
    ctx.lineTo(200, 50);  //绘制一条从当前位置到指定坐标(200, 50)的直线.
    //闭合路径。会拉一条从当前点到path起始点的直线。如果当前点与起始点重合,则什么都不做
    ctx.closePath();
    ctx.stroke(); //绘制路径。
}
draw();

5.2 绘制三角形边框

function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(50, 50);
    ctx.lineTo(200, 50);
    ctx.lineTo(200, 200);
  	ctx.closePath(); //虽然我们只绘制了两条线段,但是closePath会closePath,仍然是一个3角形
    ctx.stroke(); //描边。stroke不会自动closePath()
}
draw();

5.3 填充三角形

function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(50, 50);
    ctx.lineTo(200, 50);
    ctx.lineTo(200, 200);
   
    ctx.fill(); //填充闭合区域。如果path没有闭合,则fill()会自动闭合路径。
}
draw();

5.4 绘制圆弧

方法1 radians=(Math.PI/180)*degrees //角度转换成弧度

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

方法2

arcTo(x1, y1, x2, y2, radius):
根据给定的控制点和半径画一段圆弧,最后再以直线连接两个控制点。

圆弧案例1:

function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.arc(50, 50, 40, 0, Math.PI / 2, false);
    ctx.stroke();
}
draw();

圆弧案例2:

function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.arc(50, 50, 40, 0, Math.PI / 2, false);
    ctx.stroke();

    ctx.beginPath();
    ctx.arc(150, 50, 40, 0, -Math.PI / 2, true);
    ctx.closePath();
    ctx.stroke();

    ctx.beginPath();
    ctx.arc(50, 150, 40, -Math.PI / 2, Math.PI / 2, false);
    ctx.fill();

    ctx.beginPath();
    ctx.arc(150, 150, 40, 0, Math.PI, false);
    ctx.fill();

}
draw();

圆弧案例3:

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

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

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

其实绘制的圆弧就是与这两条直线相切的圆弧。

function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    var ctx = canvas.getContext("2d");
    ctx.beginPath();
    ctx.moveTo(50, 50);
  	//参数1、2:控制点1坐标   参数3、4:控制点2坐标  参数4:圆弧半径
    ctx.arcTo(200, 50, 200, 200, 100);
    ctx.lineTo(200, 200)
    ctx.stroke();
    
    ctx.beginPath();
    ctx.rect(50, 50, 10, 10);
    ctx.rect(200, 50, 10, 10)
    ctx.rect(200, 200, 10, 10)
    ctx.fill()
}
draw();

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rBh8peK1-1597934678199)(/img/bVbLC6S)]

六、绘制文本

绘制文本的两个方法

canvas 提供了两种方法来渲染文本:

  1. fillText(text, x, y [, maxWidth])

    在指定的(x,y)位置填充指定的文本,绘制的最大宽度是可选的.

  2. strokeText(text, x, y [, maxWidth])

    在指定的(x,y)位置绘制文本边框,绘制的最大宽度是可选的.

var ctx;
function draw(){
    var canvas = document.getElementById('tutorial');
    if (!canvas.getContext) return;
    ctx = canvas.getContext("2d");
    ctx.font = "100px sans-serif"
    ctx.fillText("天若有情", 10, 100);
    ctx.strokeText("天若有情", 10, 200)
}
draw();

给文本添加样式

  1. font = value

    当前我们用来绘制文本的样式。这个字符串使用和 CSS font属性相同的语法. 默认的字体是 10px sans-serif

  2. textAlign = value

    文本对齐选项. 可选的值包括:start, end, left, right or center. 默认值是 start

  3. textBaseline = value

    基线对齐选项,可选的值包括:top, hanging, middle, alphabetic, ideographic, bottom。默认值是 alphabetic。

  4. direction = value

    文本方向。可能的值包括:ltr, rtl, inherit。默认值是 inherit。

七、绘制图片

7.1 由零开始创建图片

创建<img>元素

var img = new Image();   // 创建一个<img>元素
img.src = 'myImage.png'; // 设置图片源地址

脚本执行后图片开始装载

绘制img

//参数1:要绘制的img  参数2、3:绘制的img在canvas中的坐标   参数4,5img 的大小
ctx.drawImage(img,0,0,300,300); 

注意:
​ 考虑到图片是从网络加载,如果 drawImage 的时候图片还没有完全加载完成,则什么都不做,个别浏览器会抛异常。所以我们应该保证在 img 绘制完成之后再 drawImage

        var canvas = document.getElementById('tutorial');
        var ctx = canvas.getContext("2d");
        var img = new Image();   // 创建img元素
        img.src = './img/16.jpg'; // 设置图片源地址
        img.addEventListener("load", loadHandler);
        function loadHandler(e) {
            ctx.drawImage(img,0,0, 200, 300);
        }

7.2 绘制 img 标签元素中的图片

img 可以 new 也可以来源于我们页面的 <img>标签

<img src="./美女.jpg" alt="" width="300"><br>
<canvas id="tutorial" width="600" height="400"></canvas>
<script type="text/javascript">
    function draw(){
        var canvas = document.getElementById('tutorial');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        var img = document.querySelector("img");
        ctx.drawImage(img, 0, 0);
    }
    document.querySelector("img").onclick = function (){
        draw();
    }

</script>

7.3 缩放图片

drawImage() 也可以再添加两个参数:

drawImage(image, x, y, width, height)

​ 这个方法多了2个参数:widthheight,这两个参数用来控制 当像canvas画入时应该缩放的大小

 <img src="./img/16.jpg" alt="" width="300"><br>
    <canvas id="tutorial" width="600" height="400"></canvas>
    <script type="text/javascript">
        function draw() {
            var canvas = document.getElementById('tutorial');
            if (!canvas.getContext) return;
            var ctx = canvas.getContext("2d");
            var img = document.querySelector("img");
            // ctx.drawImage(img, 0, 0);
            ctx.drawImage(img, 0, 0, 400, 200)

        }
        document.querySelector("img").onclick = function () {
            draw();
        }

    </script>

7.4 切片(slice)

drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)

​ 第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。

其他8个参数:

​ 前4个是定义图像源的切片位置和大小,
​ 后4个则是定义切片的目标显示位置和大小。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UQsuZ0ay-1597934678199)(/img/bVbLDeR)]

八、状态的保存和恢复

Saving and restoring state是绘制复杂图形时必不可少的操作。

save()和restore()

saverestore 方法是用来保存和恢复 canvas 状态的,都没有参数。

Canvas 的状态就是当前画面应用的所有样式和变形的一个快照。

1. 关于 save()
Canvas状态存储在栈中,每当`save()`方法被调用后,当前的状态就被推送到栈中保存。一个绘画状态包括:
  • 当前应用的变形(即移动,旋转和缩放)

  • strokeStyle, fillStyle, globalAlpha, lineWidth, lineCap, lineJoin, miterLimit, shadowOffsetX, shadowOffsetY, shadowBlur, shadowColor, globalCompositeOperation 的值

  • 当前的裁切路径(clipping path

  • 可以调用任意多次 save方法。(类似数组的push())

2. 关于restore()

每一次调用 restore 方法,上一个保存的状态就从栈中弹出,所有设定都恢复。

    <canvas id="tutorial" width="300" height="300"></canvas>
    <script>
        var ctx;
        function draw() {
            var canvas = document.getElementById('tutorial');
            if (!canvas.getContext) return;
            var ctx = canvas.getContext("2d");
            ctx.fillRect(0, 0, 150, 150);   // 使用默认设置绘制一个矩形
            ctx.save();                  // 保存默认状态

            ctx.fillStyle = 'red'       // 在原有配置基础上对颜色做改变
            ctx.fillRect(15, 15, 120, 120); // 使用新的设置绘制一个矩形

            ctx.save();                  // 保存当前状态
            ctx.fillStyle = '#FFF'       // 再次改变颜色配置
            ctx.fillRect(30, 30, 90, 90);   // 使用新的配置绘制一个矩形

            ctx.restore();               // 重新加载之前的颜色状态
            ctx.fillRect(45, 45, 60, 60);   // 使用上一次的配置绘制一个矩形

            ctx.restore();               // 加载默认颜色配置
            ctx.fillRect(60, 60, 30, 30);   // 使用加载的配置绘制一个矩形
        }
        draw();

    </script>
九、应用缓存
方法
	1:MIME TYPE:text/cache-manifest 服务器配置MIME类型
		服务器配置响应头header("content-type: text/cache-manifest");
	2:需要由你创建的:NAME.manifest    创建manifest文件
		<html lang="en" manifest="main.mainfast">
	3:给 <html> 标签加 manifest 属性:<html manifest="path/to/NAME.manifest">
		CACHE MANIFEST
        CACHE:
        main.css

        NETWORK:

        FALLBACK:
        ./404.html

CACHE MANIFEST - 在此标题下列出的文件将在首次下载后进行缓存
NETWORK - 在此标题下列出的文件需要与服务器的连接,且不会被缓存
FALLBACK - 在此标题下列出的文件规定当页面无法访问时的回退页面(比如 404 页面)

HTML5 引入了应用程序缓存,这意味着 web 应用可进行缓存,并可在没有因特网连接时进行访问。
应用程序缓存为应用带来三个优势:
	- 离线浏览 - 用户可在应用离线时使用它们
	- 速度 - 已缓存资源加载得更快
	- 减少服务器负载 - 浏览器将只从服务器下载更新过或更改过的资源。
一旦应用被缓存,它就会保持缓存直到发生下列情况:
	- 用户清空浏览器缓存
	- manifest 文件被修改(参阅下面的提示)
	- 由程序来更新应用缓存
  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值