zoukankan      html  css  js  c++  java
  • html5中canvas(2)

    1、绘制图片(drawImage)(重点)

    1.1 基本绘制图片的方式

    • context.drawImage(img, x, y);
    • 参数:
      • img 可以为:图片、视频或者canvas画布
      • x,y 绘制图片左上角的坐标, img是绘制图片的dom对象。

    1.2 在画布上绘制图像,并规定图像的宽度和高度

    • context.drawImage(img, x, y, width, height);
    • width:绘制到canvas中展示的宽度
    如果指定宽高,最好成比例,不然图片会被拉伸
    等比公式:  toH = Height * toW / Width;
                设置高 = 原高度 * 设置宽/ 原宽度;
    

    1.3 图片裁剪,并在画布上定位被剪切的部分

    • context.drawImage(img, sx, sy, swidth, sheight, x, y, width, height);
    • 参数:
      • sx, sy:被剪裁图片的其实位置
      • swidth:裁剪图片的高度 sheight:裁剪的高度
      • x, y : 要绘制到画布上的位置
      • width :要绘制到画布上的宽度
      • height:要绘制到画布上的高度

    1.4 用JavaScript创建img对象

    • 第一种方式:
    • var img = document.createElement("img");

    • 第二种方式:

    var img = new Image(); //这个就是 img标签的dom对象
    img.src = "imgs/arc.gif";
    img.alt = "文本信息";
    img.onload = function() {
        //图片加载完成后,执行此方法
    }
    

    1.5 绘制图片的步骤

    • 1 创建图片对象
    • 2 等待图片加载完成
    • 3 开始绘制图片

    1.5.1 加载图片的问题

    • 需要使用 onload事件 等待图片加载完成之后,再绘制!

    练习

    • 练习1: 绘制整个图片
    • 练习2: 绘制图片的一部分
    • 练习3: 绘制序列帧动画

    2、变换 (重点)

    2.1 平移

    • ctx.translate(x,y) 方法重新映射画布上的 (0,0) 位置
    • 参数说明:
    • x: 添加到水平坐标(x)上的值
    • y: 添加到垂直坐标(y)上的值
    • 发生位移后,相当于把画布的0,0坐标 更换到新的x,y的位置,所有绘制的新元素都被影响。
    • 位移画布一般配合缩放和旋转等。

    2.2 缩放

    • scale() 方法缩放当前绘图,更大或更小
    • 语法:context.scale(scalewidth,scaleheight)
      • scalewidth : 缩放当前绘图的宽度 (1=100%, 0.5=50%, 2=200%, 依次类推)
      • scaleheight : 缩放当前绘图的高度 (1=100%, 0.5=50%, 2=200%, etc.)
    • 注意:缩放的是整个画布,缩放后,继续绘制的图形会被放大或缩小。

    2.3 旋转

    • context.rotate(radian); 旋转当前的画布
    • 注意参数是弧度(PI)
    • 如需将角度转换为弧度,请使用 degrees*Math.PI/180 公式进行计算。

    练习

    • 在画布左右两侧分别绘制两个圆
    • 绘制两个正方形(宽度:100 和 50)
    • 绘制旋转的矩形

    3 环境

    前面提到 Canvas 是含有状态的, 也就是说需要修改颜色, 直线样式, 
    绘图方式等效果时需要开启一个新的状态. 但是有时在绘制过程中需要修改状态, 
    同时绘制完当前状态后又需要回到之前的状态中继续绘制另外的形状. 
    那么只有再将修改过的样式载更改回来. 如果在该状态中修改的属性较多, 
    那么每次在回到之前状态时就有很多的代码.
    
    Canvas 中引入了状态的保持机制. 使用 CanvasRenderingContext2D.save() 
    方法可以保存当前状态. 如果需要恢复到已经保存的状态, 只需要调用 
    CanvasRenderingContext2D.restore() 方法即可.
    
    状态保持的机制是基于状态栈实现的. 也就是说 save 一次就存储一个状态. restore 
    一次就将刚刚存入的恢复. 如果 save 两次, 就需要 restore 两次, 才可以恢复到最先的状态.
    
    一般在封装绘图的时候都会采用开始绘制之前, save 一次, 然后 开启一个新路径, 然后绘制结束后 
    restore, 然后再开启一个新路径. 这样保持当前状态不会对其他绘图代码构成影响.
    

    3.1 优化

    canvas 在绘制图片的时候, drawImage 方法还支持将一个 canvas 绘制到另一个 canvas 中.
    因此使用该功能, 可以在内存中完成复杂的绘图, 将绘制好的半成品再绘制到 canvas 
    中合成需要的效果.
    

    3.2 绘制环境保存和还原(重要)

    • ctx.save() 保存当前环境的状态
    • ctx.restore() 返回之前保存过的路径状态和属性

    4 canvas的其他样式设置

    4.1 设置阴影(,少用,性能差)

    • 类比于CSS3的阴影。
    • shadowColor : 设置或返回用于阴影的颜色
    • shadowBlur : 设置或返回用于阴影的模糊级别,大于1的正整数,数值越高,模糊程度越大
    • shadowOffsetX: 设置或返回阴影距形状的水平距离
    • shadowOffsetY: 设置或返回阴影距形状的垂直距离
        ctx.fillStyle = "rgba(255,0,0, .9)"
        ctx.shadowColor = "teal";
        ctx.shadowBlur = 10;
        ctx.shadowOffsetX = 10;
        ctx.shadowOffsetY = 10;
        ctx.fillRect(100, 100, 100, 100);
    

    4.2 创建线性渐变的样式

    • 一般不用,都是用图片代替,canvas绘制图片效率更高。
    • 线性渐变可以用于 矩形、圆形、文字等颜色样式
    • 线性渐变是一个对象
    • 语法:ctx.createLinearGradient(x0,y0,x1,y1);
      • 参数:x0,y0起始坐标,x1,y1结束坐标
        例如:
        //创建线性渐变的对象,
        var grd = ctx.createLinearGradient(0,0,200,0);
        grd.addColorStop(0,"green");  //添加一个渐变颜色,第一个参数介于 0.0 与 1.0 之间的值,表示渐变中开始与结束之间的位置。
        grd.addColorStop(1,"white");  //添加一个渐变颜色
        ctx.fillStyle = grd;           //关键点,把渐变设置到 填充的样式
        ctx.fillRect(10, 10, 200, 100);
    

    4.3 设置圆形渐变(径向渐变)

    • 创建放射状/圆形渐变对象。可以填充文本、形状等
    • context.createRadialGradient(x0,y0,r0,x1,y1,r1);
    • radial 半径的;放射状的;光线的;光线状的 英 ['reɪdɪəl] 美 ['redɪəl]
    • 参数详解:
      • x0: 渐变的开始圆的 x 坐标
      • y0: 渐变的开始圆的 y 坐标
      • r0: 开始圆的半径
      • x1: 渐变的结束圆的 x 坐标
      • y1: 渐变的结束圆的 y 坐标
      • r1: 结束圆的半径
        var rlg = ctx.createRadialGradient(300,300,10,300,300,200);
        rlg.addColorStop(0, 'teal');    //添加一个渐变颜色
        rlg.addColorStop(.4, 'navy');
        rlg.addColorStop(1, 'purple');
        ctx.fillStyle = rlg;//设置 填充样式为延续渐变的样式
        ctx.fillRect(100, 100, 500, 500);
    

    4.4 绘制背景图(了解)

    • ctx.createPattern(img,repeat) 方法在指定的方向内重复指定的元素了解
    • pattern:n. 模式;图案;样品 英 ['pæt(ə)n] 美 ['pætɚn]
    • 第一参数:设置平铺背景的图片,第二个背景平铺的方式。
      • image : 规定要使用的图片、画布或视频元素。
      • repeat : 默认。该模式在水平和垂直方向重复。
      • repeat-x : 该模式只在水平方向重复。
      • repeat-y : 该模式只在垂直方向重复。
      • no-repeat: 该模式只显示一次(不重复)。
        var ctx = c.getContext("2d");
        var img = document.getElementById("lamp");
        var pat = ctx.createPattern(img,"repeat");
        ctx.rect(0,0,150,100);
        ctx.fillStyle=pat;//  把背景图设置给填充的样式
        ctx.fill();
    

    4.5 设置绘制环境的透明度

    • ctx.globalAlpha = number;
    • number: 透明值。必须介于 0.0(完全透明) 与 1.0(不透明) 之间。
    • 注意:设置透明度是 全局的 透明度的样式

    4.6 画布限定区域绘制

    • ctx.clip(); 方法从原始画布中剪切任意形状和尺寸
    • 一旦剪切了某个区域,则所有之后的绘图都会被限制在被剪切的区域内(不能访问画布上的其他区域)
    • 一般配合绘制环境的保存和还原。
        // Create clipping region
        ctx.arc(100, 100, 75, 0, Math.PI*2, false);
        ctx.clip();
    
        ctx.fillRect(0, 0, 100,100);
    

    4.7 画布保存base64编码内容(重要)

    • 把canvas绘制的内容输出成base64内容。
    • 语法:canvas.toDataURL(type, encoderOptions);
    • 例如:canvas.toDataURL("image/jpg",1);
    • 参数:
      • type,设置输出的类型,比如 image/png image/jpeg等
      • encoderOptions: 0-1之间的数字,用于标识输出图片的质量,1表示无损压缩,类型为: image/jpeg 或者 image/webp 才起作用。
        var canvas = document.getElementById("canvas");
        var dataURL = canvas.toDataURL();
        console.log(dataURL);
        // "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNby
        // blAAAADElEQVQImWNgoBMAAABpAAFEI8ARAAAAAElFTkSuQmCC"
    
        var img = document.querySelector("#img-demo");//拿到图片的dom对象
        img.src = canvas.toDataURL("image/png");      //将画布的内容给图片标签显示
    

    4.8 画布渲染画布(重要)

    • ctx.drawImage(img,x,y);
    • img 参数也可以是画布,也就是把一个画布整体的渲染到另外一个画布上。
        var canvas1 = document.querySelector('#cavsElem1');
        var canvas2 = document.querySelector('#cavsElem2');
        var ctx1 = canvas1.getContext('2d');
        var ctx2 = canvas2.getContext('2d');
        ctx1.fillRect(20, 20, 40, 40);      //在第一个画布上绘制矩形
    
        ctx2.drawImage(canvas1, 10, 10);    //将第一个画布整体绘制到第二个画布上
    

    5 了解贝塞尔曲线

    5.1 绘制一条二次方曲线。

    • 微软的画图板中的曲线的颜色。
    • quadratic:二次方的意思, 英 [kwɒ'drætɪk] 美 [kwɑ'drætɪk]
    • Curve:曲线的意思, 英 [kɜːv] 美 [kɝv]
    • 语法: context.quadraticCurveTo(cpx,cpy,x,y);
    • 参数:
      • cpx: 贝塞尔控制点的 x 坐标
      • cpy: 贝塞尔控制点的 y 坐标
      • x : 结束点的 x 坐标
      • y : 结束点的 y 坐标

        ctx.beginPath();
        ctx.moveTo(20,20);
        //绘制2次方曲线,贝赛尔曲线
        ctx.quadraticCurveTo(20,100,200,20);
        ctx.stroke();
    

    5.2 绘制贝塞尔曲线

    • 绘制一条三次贝塞尔曲线
    • 语法:context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
    • 提示:三次贝塞尔曲线需要三个点。前两个点是用于三次贝塞尔计算中的控制点,第三个点是曲线的结束点。曲线的开始点是当前路径中最后一个点。如果路径不存在,那么请使用 beginPath() 和 moveTo() 方法来定义开始点。
    • 参数说明:
      • cp1x: 第一个贝塞尔控制点的 x 坐标
      • cp1y: 第一个贝塞尔控制点的 y 坐标
      • cp2x: 第二个贝塞尔控制点的 x 坐标
      • cp2y: 第二个贝塞尔控制点的 y 坐标
      • x: 结束点的 x 坐标
      • y: 结束点的 y 坐标
        //绘制复杂的贝塞尔曲线
        ctx.beginPath();
        ctx.moveTo(400,400);
        //参数说明:context.bezierCurveTo(cp1x,cp1y,cp2x,cp2y,x,y);
        // cp1x: 第一个贝塞尔控制点的 x 坐标
        // cp1y: 第一个贝塞尔控制点的 y 坐标
        // cp2x: 第二个贝塞尔控制点的 x 坐标
        // cp2y: 第二个贝塞尔控制点的 y 坐标
        // x: 结束点的 x 坐标
        // y: 结束点的 y 坐标
        ctx.bezierCurveTo(500, 200, 600, 600, 700, 300);
        ctx.stroke();  
    

    6、其他API说明

    6.1 创建两条切线的弧

    • 在画布上创建介于当前起点和两个点形成的夹角的切线之间的弧
    • 语法: context.arcTo(x1,y1,x2,y2,r); //类比:css3中的圆角。
    • 例如: ctx.arcTo(240, 100, 240, 110, 40);
    • 参数:
      • x1: 弧的端点1的 x 坐标
      • y1: 弧的端点1的 y 坐标
      • x2: 弧的端点2(终点)的 x 坐标
      • y2: 弧的端点2(终点)的 y 坐标
      • r : 弧的半径
        //代码demo:
        ctx.beginPath();
        ctx.moveTo(100,100);
        ctx.lineTo(200,100);
        //context.arcTo(x1,y1,x2,y2,r); //类比:css3中的圆角。
        ctx.arcTo(240, 100, 240, 110, 40);
        ctx.lineTo(240, 300);
        ctx.stroke();   
    

    6.2 判断点是否在路径中

    • context.isPointInPath(x,y);
    • 解释:如果指定的点位于当前路径中,返回 true;否则返回 false
    • 作用:判断坐标 x, y 是否在当前的路径中。
        ctx.rect(10, 10, 100, 100);
        ctx.stroke();
        console.log(ctx.isPointInPath(10, 10)); // true
    

    6.3 如果以后做canvas游戏方向开发深入学习可以扩展内以下容:

    • setTransform() 将当前转换重置为单位矩阵。然后运行 transform()
    • transform() 替换绘图的当前转换矩阵
    • globalCompositeOperation 设置或返回新图像如何绘制到已有的图像上
    • 像素操作
  • 相关阅读:
    LeetCode OJ-- 二战 Palindrome Number
    Cracking-- 17.13 将二叉树转换成双向链表
    Cracking-- 4.7 在一颗二叉树中找两个节点的第一个共同祖先
    priority_queue 示例
    heap c++ 操作 大顶堆、小顶堆
    【转】当你在浏览器地址栏输入一个URL后回车,将会发生的事情?
    Cracking-- 1.1 判断字符串中是否有重复字符
    如何取得SharePoint Timer Job的历史成功数和失败数,并按照日期计算排列
    SharePoint document 右键菜单和【...】菜单不一致的解决办法
    SharePoint Search 分词(WordBreaker)
  • 原文地址:https://www.cnblogs.com/lsy0403/p/5877272.html
Copyright © 2011-2022 走看看