h5新增标签canvas0818

h5新增标签canvas

1.基本概念

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>01-Canvas开篇</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                background: red;
            }
        </style>
    </head>
    <body>
    <!--1.在body中创建一个canvas标签-->
    <!--
    注意点
    canvas标签有默认的宽度和高度
    默认的宽度是300px
    默认的高度是150px
    -->
    <canvas></canvas>
    <script>
        /*
        1.什么是Canvas?
        Canvas是H5新增的一个标签, 我们可以通过JS在这个标签上绘制各种图案
        Canvas 拥有多种绘制路径、矩形、圆形、字符以及图片的方法。
        * */
        // 2.通过js代码拿到canvas标签
        let oCanvas = document.querySelector("canvas");
        // 3.从canvas标签中获取到绘图工具
        let oCtx = oCanvas.getContext("2d");
        // 4.通过绘图工具在canvas标签上绘制图形
        // 4.1设置路径的起点
        oCtx.moveTo(50, 50);
        // 4.2设置路径的终点
        oCtx.lineTo(200, 50);
        // 4.3告诉canvas将这些点连接起来
        oCtx.stroke();
    </script>
    </body>
    </html>
    

2.注意点

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>02-Canvas注意点</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                background: red;
                /*width: 500px;*/
                /*height: 500px;*/
            }
        </style>
    </head>
    <body>
    <!--1.创建一个画布-->
    <canvas width="500" height="500"></canvas>
    <script>
        /*
        1.canvas有默认的宽度和高度
        默认宽300px, 高150px
        */
        /*
        2.不能通过CSS设置画布的宽高
        通过CSS设置画布宽高会在默认宽高的基础上拉伸
        如果需要设置canvas宽高请通过元素行内属性width和height设置
        */
        /*
        3.线条默认宽度和颜色
        通过canvas绘制的线条默认宽度是1px, 颜色是纯黑色
        但是由于默认情况下canvas会将线条的中心点和像素的底部对齐,
        所以会导致显示效果是2px和非纯黑色问题,解决办法就是加0.5或者减0.5
        * */
    
        // 2.拿到画布
        let oCanvas = document.querySelector("canvas");
        // 3.拿到绘制工具
        let oCtx = oCanvas.getContext("2d");
        // 4.利用绘制工具绘制直线
        // 4.1设置起始位置
        oCtx.moveTo(50, 50.5);
        // 4.2设置路径上的点
        oCtx.lineTo(200, 50.5);
        // 4.2绘制已定义的路径
        oCtx.stroke();
    </script>
    </body>
    </html>
    

3.线条属性

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>03-Canvas线条属性</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                background: yellowgreen;
            }
        </style>
    </head>
    <body>
    <canvas></canvas>
    <script>
        /*
        1.线条相关属性
        lineWidth: 线条宽度
        strokeStyle: 线条颜色
        lineCap: 线末端类型:(butt默认)、round、square
        * */
        let oCanvas = document.querySelector("canvas");
        let oCtx = oCanvas.getContext("2d");
        // 修改线条的高度
        oCtx.lineWidth = 50;
        // 修改线条的颜色
        oCtx.strokeStyle = "blue";
        // 修改线条的两端样式
        oCtx.lineCap = "round";
        oCtx.moveTo(50, 50);
        oCtx.lineTo(200, 50);
        oCtx.stroke();
    </script>
    </body>
    </html>
    

4.绘制多根线条

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>04-Canvas多根线条</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                background: yellowgreen;
            }
        </style>
    </head>
    <body>
    <canvas></canvas>
    <script>
        /*
        1.多根线条注意点
        如果是同一个路径, 那么路径样式会被重用(第二次绘制会复用第一次的样式)
        如果是同一个路径, 那么后设置的路径样式会覆盖先设置的路径样式
    
        2.如何给每根线条单独设置路径样式?
        每根线条都开启一个新的路径即可
        * */
        let oCanvas = document.querySelector("canvas");
        let oCtx = oCanvas.getContext("2d");
        oCtx.moveTo(50, 50);
        oCtx.lineTo(200, 50);
        oCtx.lineWidth = 20;
        oCtx.strokeStyle = "blue";
        oCtx.stroke();
    
        oCtx.beginPath(); // 重新开启一个路径
        oCtx.moveTo(50, 100);
        oCtx.lineTo(200, 100);
        oCtx.lineWidth = 10; // 重新设置当前路径样式
        oCtx.strokeStyle = "red";
        oCtx.stroke();
    
        oCtx.beginPath(); // 重新开启一个路径
        oCtx.moveTo(50, 150);
        oCtx.lineTo(200, 150);
        oCtx.lineWidth = 15; // 重新设置当前路径样式
        oCtx.strokeStyle = "green";
        oCtx.stroke();
    </script>
    </body>
    </html>
    

5.简单图形

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>05-Canvas简单图形</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="500"></canvas>
    <script>
        /*
        1.closePath
        自动创建从当前点回到起始点的路径
    
        2.lineJoin
        设置相交线的拐点样式 miter(默认)、round、bevel
        * */
        let oCanvas = document.querySelector("canvas");
        let oCtx = oCanvas.getContext("2d");
        oCtx.moveTo(50, 50);
        oCtx.lineTo(200, 50);
        oCtx.lineTo(200, 200);
        // 注意点: 如果通过lineTo来闭合图形, 那么是不能很好的闭合
        // oCtx.lineTo(50, 50);
        oCtx.closePath();
        oCtx.lineWidth = 20;
        oCtx.lineJoin = "round";
        // 注意点: 默认情况下不会自动从最后一个点连接到起点
        oCtx.stroke();
    </script>
    </body>
    </html>
    

6.填充图形

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>06-Canvas填充图形</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="500"></canvas>
    <script>
        /*
         1.stroke
        绘制已定义的路径
    
        2.fill
        填充已定义的路径
        */
        let oCanvas = document.querySelector("canvas");
        let oCtx = oCanvas.getContext("2d");
        
        oCtx.moveTo(100, 100);
        oCtx.lineTo(300, 100);
        oCtx.lineTo(300, 300);
        oCtx.lineTo(100, 300);
        oCtx.closePath();
        // oCtx.stroke();
    
        // oCtx.beginPath();
        /*
       oCtx.moveTo(150, 150);
       oCtx.lineTo(250, 150);
       oCtx.lineTo(250, 250);
       oCtx.lineTo(150, 250);
      */
       oCtx.moveTo(250, 150);
       oCtx.lineTo(150, 150);
       oCtx.lineTo(150, 250);
       oCtx.lineTo(250, 250);
    
        oCtx.closePath();
        /*
        注意点: 只要没有手动开启新的路径, 那么使用的都是默认路径
        如果都是默认路径, 那么设置的样式在同一个路径中都是有效的
        * */
        // oCtx.strokeStyle = "blue";
        // oCtx.stroke();
        oCtx.fill();
        /*
        对于同一路径,在填充的时候回遵循非零环绕规则
        从当前的区域拉出一条直线, 遇到顺时针相交的线就+1, 遇到逆时针相交的线就-1
        最终计算的结果如何是0就不填充, 如果不是0就填充 
        所以上面那两个填充的时候,里面的不会填充
        * */
    </script>
    </body>
    </html>
    

7.绘制虚线

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>07-Canvas虚线</title>
        <style>
            *{
                margin: 0px;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="500"></canvas>
    <script>
        let oCanvas = document.querySelector("canvas");
        let oCtx = oCanvas.getContext("2d");
        oCtx.moveTo(100, 100);
        oCtx.lineTo(400, 100);
        oCtx.lineWidth = 20;
        oCtx.strokeStyle = "blue";
        // oCtx.setLineDash([5, 20]);
        oCtx.setLineDash([5, 10, 20]);
        console.log(oCtx.getLineDash());
        oCtx.lineDashOffset = -50;
        oCtx.stroke();
        /*
        1.setLineDash
        [5,10] 数组是用来描述你的排列方式的
    
        2.getLineDash
        获取虚线的排列方式 获取的是不重复的那一段的排列方式
    
        3.lineDashOffset
        设置虚线的偏移位
        * */
    
    </script>
    </body>
    </html>
    

8.绘制表格

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>08-Canvas绘制表格</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="400"></canvas>
    <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        // 3.定义变量保存小方格的尺寸
        let gridSize = 50;
        // console.log(oCanvas.offsetWidth);
        // console.log(oCanvas.offsetHeight);
        // console.log(oCtx.canvas.width);
        // console.log(oCtx.canvas.height);
        //canvas里面就有获取宽高的属性,oCtx.canvas.width,所以就不用offsetWidth了
        // 4.拿到canvas的宽高
        let canvasWidth = oCtx.canvas.width;
        let canvasHeight = oCtx.canvas.height;
        // 5.计算在垂直方向和水平方向可以绘制多少条横线
        let row = Math.floor(canvasHeight / gridSize);
        let col = Math.floor(canvasWidth / gridSize);
        // 6.绘制垂直方向的横线
        for(let i = 0; i < row; i++){
            oCtx.beginPath();
            oCtx.moveTo(0, i * gridSize - 0.5);
            oCtx.lineTo(canvasWidth, i * gridSize - 0.5);
            oCtx.strokeStyle = "#ccc";
            oCtx.stroke();
        }
        // 7.绘制水平方向的横线
        for(let i = 0; i < col; i++){
            oCtx.beginPath();
            oCtx.moveTo(i * gridSize - 0.5, 0);
            oCtx.lineTo(i * gridSize - 0.5, canvasHeight);
            oCtx.strokeStyle = "#ccc";
            oCtx.stroke();
        }
    </script>
    </body>
    </html>
    

9.绘制坐标系

  • //在上面绘制好表格的基础上
    // 1.计算坐标系原点的位置
     let originX = gridSize;
     let originY = canvasHeight - gridSize;
     // 2.计算X轴终点的位置
     let endX = canvasWidth - gridSize;
     // 3.绘制X轴
     oCtx.beginPath();
     oCtx.moveTo(originX, originY);
     oCtx.lineTo(endX, originY);
     oCtx.strokeStyle = "#000";
     oCtx.stroke();
     // 4.绘制X轴的箭头
     oCtx.lineTo(endX - 10, originY + 5);
     oCtx.lineTo(endX - 10, originY - 5);
     oCtx.lineTo(endX, originY);
     oCtx.fill();
    
     // 5.计算Y轴终点的位置
     let endY = gridSize;
     // 3.绘制Y轴
     oCtx.beginPath();
     oCtx.moveTo(originX, originY);
     oCtx.lineTo(originX, endY);
     oCtx.strokeStyle = "#000";
     oCtx.stroke();
     // 4.绘制Y轴的箭头
     oCtx.lineTo(originX - 5, endY + 10);
     oCtx.lineTo(originX + 5, endY + 10);
     oCtx.lineTo(originX, endY);
     oCtx.fill();
    

10.绘制数据点

  • //在上面的基础上
    // 1.拿到服务器返回数据
        let list = [
            {
                x: 100,
                y: 300
            },
            {
                x: 200,
                y: 200
            },
            {
                x: 300,
                y: 250
            },
            {
                x: 400,
                y: 100
            },
        ];
        let dotLocation = {
            x: 100,
            y: 300
        }
        let dotSize = 20;
        /*
        // 2.绘制数据点
        oCtx.beginPath();
        oCtx.moveTo(dotLocation.x - dotSize / 2, dotLocation.y - dotSize / 2);
        oCtx.lineTo(dotLocation.x + dotSize - dotSize / 2, dotLocation.y - dotSize / 2);
        oCtx.lineTo(dotLocation.x + dotSize - dotSize / 2, dotLocation.y + dotSize - dotSize / 2);
        oCtx.lineTo(dotLocation.x - dotSize / 2, dotLocation.y + dotSize - dotSize / 2);
        oCtx.closePath();
        oCtx.fill();
        */
        for(let i = 0; i < list.length; i++){
            oCtx.beginPath();
            oCtx.moveTo(list[i].x - dotSize / 2, list[i].y - dotSize / 2);
            oCtx.lineTo(list[i].x + dotSize - dotSize / 2, list[i].y - dotSize / 2);
            oCtx.lineTo(list[i].x + dotSize - dotSize / 2, list[i].y + dotSize - dotSize / 2);
            oCtx.lineTo(list[i].x - dotSize / 2, list[i].y + dotSize - dotSize / 2);
            oCtx.closePath();
            oCtx.fill();
        }
    

11.绘制折线图

  • // 1.绘制折线
    oCtx.beginPath();
    for(let i = 0; i < list.length; i++){
        if(i === 0){
            oCtx.moveTo(list[i].x, list[i].y);
        }else{
            oCtx.lineTo(list[i].x, list[i].y);
        }
    }
    oCtx.stroke();
    

12.绘制矩形

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>13-Canvas绘制矩形</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="400"></canvas>
    <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        /*
        第一个参数: x的坐标
        第二个参数: y的坐标
        第三个参数: 矩形的宽度
        第四个参数: 矩形的高度
       */
       
        oCtx.rect(100, 100, 200, 200);
        oCtx.stroke();
        oCtx.fill();
      //还可以直接绘制填充的
        oCtx.fillRect(100, 100, 200, 200);
      
        //以下为清除绘制的图形
    
       let canvasWidth = oCtx.canvas.width;
       let canvasHeight = oCtx.canvas.height;
       oCtx.clearRect(0, 0, canvasWidth, canvasHeight);
    </script>
    </body>
    </html>
    

13.绘制柱状图

  • //绘制好坐标系后
    // 1.拿到服务器返回数据
    let list = [
        {
            x: 100,
            y: 300
        },
        {
            x: 200,
            y: 200
        },
        {
            x: 300,
            y: 250
        },
    ];
    let data = {
        x: 100,
        y: 300
    }
    // 2.绘制矩形
    for(let i = 0; i < list.length; i++){
        let barHeight = originY - list[i].y;
        oCtx.fillRect(list[i].x, list[i].y, gridSize, barHeight);
    }
    

14.绘制渐变色

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>15-Canvas渐变色</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="400"></canvas>
    <script>
        /*
        1.渐变背景颜色
        和普通的标签一样我们也可以给填充的图形设置线性渐变和径向渐变的背景颜色
    
        2.设置图形渐变背景颜色步骤
        2.1通过绘图工具创建渐变背景颜色
        2.2指定渐变的范围
        2.3将渐变背景颜色设置给对应的图形
        * */
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
    
        // 1.创建一个渐变的方案
        /*
        可以通过x0,y0 / x1,y1确定渐变的方向和渐变的范围
        * */
        let linearGradient = oCtx.createLinearGradient(100, 100, 300, 300);
        /*
        第一个参数是一个百分比 0~1
        第二个参数是一个颜色
        * */
        linearGradient.addColorStop(0, "green");
        linearGradient.addColorStop(0.5, "yellow");
        linearGradient.addColorStop(1, "blue");
    
        // oCtx.createRadialGradient();
        // oCtx.fillStyle = "blue";
        oCtx.fillStyle = linearGradient;
        oCtx.fillRect(100, 100, 200, 200);
    </script>
    </body>
    </html>
    

15.绘制圆弧

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>16-Canvas绘制圆弧</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="400"></canvas>
    <script>
        /*
        1.基本概念(请翻开初中数学课本)
        角度: 一个圆360度, 一个半圆是180度
        弧度: 一个圆2π, 一个半圆π
    
        2.角度转换弧度公式:
        ∵ 180角度 = π弧度
        ∴ 1角度 = π/180;
        ∴ 弧度 = 角度 * π/180;
           90角度 * π/180 = π/2
    
        3.弧度转换角度公式:
        ∵ π弧度 = 180角度
        ∴ 1弧度 = 180/π
        ∴ 角度 = 弧度 * 180/π
           π/2 * 180/π = 180/2 = 90度
        * */
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        /*
        x, y: 确定圆心
        radius: 确定半径
        startAngle: 确定开始的弧度
        endAngle: 确定结束的弧度
        Boolean: 默认是false, false就是顺时针绘制, true就是逆时针绘制
        context.arc(x, y, radius, startAngle, endAngle, Boolean);
        * */
        // oCtx.arc(100, 100, 100, 0, Math.PI);
        // oCtx.arc(100, 100, 100, 0, Math.PI, true);
        oCtx.arc(100, 100, 100, 0, Math.PI * 2);
        oCtx.stroke();
    </script>
    </body>
    </html>
    

16.绘制扇形

  • <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        oCtx.moveTo(100, 100);
        oCtx.arc(100, 100, 100, 0, Math.PI/2);
        oCtx.closePath();
        // oCtx.stroke();
        oCtx.fill();
    </script>
    

17.绘制文字

  • <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        // 3.绘制参考线
        let canvasWidth = oCtx.canvas.width;
        let canvasHeight = oCtx.canvas.height;
        oCtx.moveTo(0, canvasHeight/2);
        oCtx.lineTo(canvasWidth, canvasHeight/2);
        oCtx.stroke();
        oCtx.moveTo(canvasWidth/2, 0);
        oCtx.lineTo(canvasWidth/2, canvasHeight);
        oCtx.stroke();
        // 4.绘制文字
        let str = "知播渔教育";
        // 通过font属性可以设置文字的大小和样式
        oCtx.font = "50px 微软雅黑";
        // 通过textBaseline属性可以设置文字垂直方向的对齐方式
        // 注意点: 在对齐的时候是以绘制文字的y作为参考点进行对齐的
        oCtx.textBaseline = "middle";
        // 通过textAlign属性可以设置文字水平方向的对齐方式
        // 注意点: 在对齐的时候是以绘制文字的x作为参考点进行对齐的
        oCtx.textAlign = "center";
        /*
        注意点:
        在绘制文字的时候, 是以文字的左下角作为参考点进行绘制
        * */
        //以下一个是填充,一个不填充
        // oCtx.strokeText(str, canvasWidth/2, canvasHeight/2);
        oCtx.fillText(str, canvasWidth/2, canvasHeight/2);
    
        // oCtx.fillRect(canvasWidth/2, canvasHeight/2, 100, 100);
    </script>
    

18.绘制图片

  • <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        // 3.加载图片
        let oImg = new Image();
        oImg.onload = function () {
            // 如果只有三个参数, 那么第一个参数就是需要绘制的图片
            // 后面的两个参数是指定图片从什么位置开始绘制
            // oCtx.drawImage(oImg, 100, 100);
    
            // 如果只有五个参数, 那么第一个参数就是需要绘制的图片
            // 后面的两个参数是指定图片从什么位置开始绘制
            // 最后的两个参数是指定图片需要拉伸到多大
            // oCtx.drawImage(oImg, 100, 100, 100, 100);
    
            // 如果有九个参数, 那么第一个参数就是需要绘制的图片
            // 最后的两个参数是指定图片需要拉伸到多大
            // 第6~7个参数指定图片从什么位置开始绘制
            // 第2~3个参数指定图片上定位的位置
            // 第4~5个参数指定从定位的位置开始截取多大的图片
            oCtx.drawImage(oImg, 50, 50, 100, 100, 100, 100, 100, 100);
        }
        oImg.src = "images/lnj.jpg";
    </script>
    

19.逐帧动画

  • <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>23-Canvas帧动画</title>
        <style>
            *{
                margin: 0;
                padding: 0;
            }
            canvas{
                display: block;
                margin: 0 auto;
                background: red;
            }
        </style>
    </head>
    <body>
    <canvas width="500" height="400"></canvas>
    <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        /*
        面向对象思想:
        找到小人对象, 你给我画到指定的位置, 你给我走起来, 你给我停下来
        * */
        class Person{
            constructor(canvas, x, y){
                this.canvas = canvas;
                this.x = x;
                this.y = y;
                this.oCtx = canvas.getContext("2d");
                this.index = 1;
                this.timerId = null;
                // 0正面/1左面/2右面/3后面
                this.direction = 0;
            }
            render(){
                let oImg = new Image();
                oImg.onload = () => {
                    // 1.计算每一张图片的宽高
                    let imageWidth = oImg.width;
                    let imageHeight = oImg.height;
                    let personWidth = imageWidth / 4;
                    let personHeight = imageHeight / 4;
                    // 2.绘制图片
                    this.oCtx.drawImage(
                        oImg, // 需要绘制的图片
                        0, this.direction * personHeight, // 图片定位的位置
                        personWidth, personHeight, // 图片裁剪的大小
                        this.x, this.y, // 图片绘制的位置
                        personWidth, personHeight // 指定图片绘制的大小
                    );
                    this.oImg= oImg;
                    this.personWidth = personWidth;
                    this.personHeight = personHeight;
                }
                oImg.src = "images/person.png";
            }
            run(stepX, stepY){
                let canvasWidth = this.oCtx.canvas.width;
                let canvasHeight = this.oCtx.canvas.height;
                clearInterval(this.timerId);
                this.timerId = setInterval(() => {
                    if(stepX !== 0){
                        this.x += stepX;
                    }
                    if(stepY !== 0){
                        this.y += stepY;
                    }
                    this.oCtx.clearRect(0, 0, canvasWidth, canvasHeight);
                    this.oCtx.drawImage(
                        this.oImg, // 需要绘制的图片
                        this.index * this.personWidth, this.direction * this.personHeight, // 图片定位的位置
                        this.personWidth, this.personHeight, // 图片裁剪的大小
                        this.x, this.y, // 图片绘制的位置
                        this.personWidth, this.personHeight // 指定图片绘制的大小
                    );
                    this.index++;
                    if(this.index > 3){
                        this.index = 0;
                    }
                }, 500);
            }
            moveDown(){
                this.direction = 0;
                this.run(0, 5);
            }
            moveUp(){
                this.direction = 3;
                this.run(0, -5);
            }
            moveLeft(){
                this.direction = 1;
                this.run(-5, 0);
            }
            moveRight(){
                this.direction = 2;
                this.run(5, 0);
            }
            stop(){
                clearInterval(this.timerId);
            }
        }
        let person = new Person(oCanvas, 100, 100);
        person.render();
        person.moveDown();
        // person.run(0, 5);
        // person.run(0, -5);
        // person.run(-5, 0);
        // person.run(5, 0);
        // person.moveRight();
        // person.stop();
    
        window.onkeydown = function (event) {
            let key = event.key;
            // console.log(key);
            switch (key.toLowerCase()){
                case "w":
                    person.moveUp();
                    break;
                case "s":
                    person.moveDown();
                    break;
                case "a":
                    person.moveLeft();
                    break;
                case "d":
                    person.moveRight();
                    break;
            }
        }
    </script>
    </body>
    </html>
    

20.形变

  • <script>
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        // 注意点: 在canvas中所有的形变属性操作的都是坐标系, 而不是图形
        // oCtx.translate(100, 0);
        // oCtx.translate(0, 100);
        // oCtx.translate(100, 100);
    
        // oCtx.rotate(Math.PI/6);
    
        oCtx.scale(0.5, 1);
        // 3.绘制一个矩形
        oCtx.strokeRect(100, 100, 200, 100);
    </script>
    

21.事件监听

  • <script>
        /*
        因为整个canvas是一个标签, 所以只能通过监听鼠标在canvas上的位置来判断是否需要处理对应的图形
        当然也可以通过第三方框架来解决交互问题
        诸如: zrender.js / Knova.js /three.js / egret.js / pixi.js等等
        * */
        // 1.拿到canvas
        let oCanvas = document.querySelector("canvas");
        // 2.从canvas中拿到绘图工具
        let oCtx = oCanvas.getContext("2d");
        // 3.绘制矩形
        let rectX = 100;
        let rectY = 100;
        let rectWidth = 100;
        let rectHeight = 100;
        oCtx.rect(rectX, rectY, rectWidth, rectHeight);
        oCtx.fill();
    
        oCtx.beginPath();
        oCtx.rect(200, 200, 100, 100);
        oCtx.fill();
        // 4.添加点击事件
        oCanvas.onclick = function (event) {
            let x = event.offsetX;
            let y = event.offsetY;
            /*
            if(x >= rectX && x <= rectX + rectWidth &&
                y >= rectY && y <= rectY + rectHeight){
                console.log("矩形被点击了");
            }else{
                console.log("矩形没有被点击");
            }
            */
            /*
            注意点:
            isPointInPath方法如果开启了一个新的路径, 那么判断的就是点是否在新的路径的图形中
            * */
            console.log(oCtx.isPointInPath(x, y));
        }
    </script>
    
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容