canvas核心内容

文章目录

  • canvas核心内容
    • 1、概念
            • 提示:
    • 2、绘制直线
        • 案例:
    • 3、绘制矩形
        • 案例:绘制柱状图
    • 4、绘制曲线
        • 案例一:时钟
        • 案例二:饼状图
    • 5、绘制文本信息
        • 案例:
    • 6、绘制图片
        • 案例:
    • 7、清除画布指定元素
        • 案例:橡皮擦

canvas核心内容

1、概念

canvas是画布,其实就是h5的一个新标签,他自己有一套画图的语法标准。

canvas本身没有任何的绘图能力,所有的绘图工作都是通过js来实现的。通常我们在js通过getElementById来获取要操作的canvas(这意味着咱得给canvas设个id):

<canvas id="myCanvas"></canvas>

<script>
var c = document.getElementById("myCanvas"); //获取要操作的canvas
//操作canvas的代码...
</script>

注意最好在一开始的时候就给canvas设置好其宽高(若不设定宽高,浏览器会默认设置canvas大小为宽300、高100像素),而且不能使用css来设置(会被拉伸,有失真的风险),建议直接写于canvas标签内部:

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

当然,也可以在脚本中设置:

<canvas id="myCanvas"></canvas>

<script>
var c = document.getElementById("myCanvas");
c.width=200;
c.height=200;
</script>

要知道的是;超出此大小范围的部分是不可见的。顾名思义,可以把canvas看成一块画布,其大小是咱设定好的宽高,那么无论你怎么画,画布外的地方自然是画不到的。

.getContext() 是canvas的绘图对象/方法,要让canvas执行绘图工作必须先获取canvas的.getContext()对象来执行。

.getContext()只接受一个参数,该参数用于获取canvas的绘图环境,例如.getContext(“2d”)表示该canvas的绘图环境为2D平面(可以绘制文本、直线、弧线、矩形、圆形等)。还有3D环境,自行研究。

提示:

vscode中获取提示内容,在script脚本中加入:

        /** @type {HTMLCanvasElement} */

上面这一行代码,表示引入canvas,就会出现提示内容。

2、绘制直线

<canvas id="myCanvas" width="200" height="200" style="border:solid 1px #CCC;">
您的浏览器不支持canvas,建议使用最新版的Chrome
</canvas>

<script>
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d"); //获取该canvas的2D绘图环境对象
ctx.moveTo(10,10);   //定义绘画开始的位置
ctx.lineTo(150,50);  //画一条直线,结束点坐标是x=150,y=50
ctx.stroke();  //描边
</script>

效果如下:

canvas核心内容_第1张图片

  • .moveTo(x坐标 , y坐标) 可以理解为定位画笔在画布上的位置(注意所有绘图方法所定义的坐标是相对canvas而言的而不是浏览器窗口,对canvas来说,最左上角的点的坐标是(0,0))

  • .lineTo(x坐标 , y坐标) 顾名思义,就是画一条直线到某个点,很好理解。需要知道的是此方法仅仅做路径运动,而不存在任何视觉上的绘图效果(上色、描边)。如果不另外设置moveTo则自动把上一条边的终点作为下一条边的起点。

  • .stroke() 描边方法,canvas想要运动路径轨迹能有视觉效果,需要使用相应的上色/描边方法。

  • .strokeStyle = “red”; 设定描边颜色为红色,只要写在.stroke()方法前面即可。

  • ctx.strokeStyle可获值的形式有三种:用的时候查一查

    ctx.strokeStyle=color|gradient|pattern;  //即支持 “颜色/渐变/图案笔刷” 的赋值
    

如果要绘制两条不一样颜色的直线,就需要给第二条边绘制时,开启另外一条轨道,不然就算设置了两个颜色也不会显示出两条不同颜色的线。

案例:

<script>
  var c = document.getElementById("myCanvas");
  var ctx = c.getContext("2d"); 
  ctx.moveTo(0,0);   
  ctx.lineTo(150,50);  
  ctx.lineTo(20,100); 
  ctx.strokeStyle = "blue";    //设定描边颜色为蓝色
  ctx.stroke();  
  
  ctx.beginPath();  //告诉canvas咱们要重新绘制一条全新的路径了,之前画的东西从此再无关系
  ctx.moveTo(90,90); 
  ctx.lineTo(80,150);  
  ctx.strokeStyle = "red";    //设定描边颜色为红色
  ctx.stroke();  
</script>

效果如下:

canvas核心内容_第2张图片

3、绘制矩形

canvas本身就自带绘制矩形的方法;ctx.rect(x,y,w,h);

参数说明:

  • x,y:表示起点坐标,以画布左上角为坐标中心,x向右增大,y向下增大。

  • w,h:分别代表矩形的宽高。

<canvas id="box" width="500" height="500"></canvas>
<script>
    var canvas = document.getElementById("box");

    var ctx = canvas.getContext("2d");

    ctx.strokeStyle = "red";

    ctx.fillStyle = "blue";

    ctx.lineWidth = 5;

    ctx.beginPath();

    ctx.rect(100, 100, 200, 200);

    ctx.closePath();  //闭合通道

    ctx.fill();  //填充

    ctx.stroke(); //描边
</script>

效果如下:

canvas核心内容_第3张图片

如果我们想给一个图像不仅要填充,还要绘制边框,那我们要先填充,后绘制边框,这样我们的边框才会正常显示。

所以还有另外的方法:fillRect(x,y,w,h)和strokeRect(x,y,w,h);

<canvas id="box" width="500" height="500"></canvas>
<script>
    var canvas = document.getElementById("box");
    var ctx = canvas.getContext("2d");

    ctx.strokeStyle = "red";
    ctx.fillStyle = "blue";
    ctx.lineWidth = 5;
    ctx.strokeStyle = 'red';
    ctx.fillRect(100, 100, 200, 200);
    ctx.strokeRect(100, 100, 200, 200);
</script>

效果如上一样。

案例:绘制柱状图

<style>
#box {
    border: 2px solid pink;
}
</style>
<canvas id="box" width="600" height="600"></canvas>

<body>

<script>
    /** @type {HTMLCanvasElement} */
    var canvas = document.querySelector('#box');
    var ctx = canvas.getContext('2d');

    var arr = [234, 535, 2343, 4266, 2345, 7895];
    var arr1 = ['红烧肉', '鸡腿', '肘子', '火锅', '串串', '冒菜']
    ctx.lineTo(50, 500);
    ctx.lineTo(580, 500);
    ctx.stroke();

    var h = 450 / Math.max(...arr);
    for (let i = 0; i < arr.length; i++) {
        ctx.fillStyle = 'blue';
        ctx.strokeText(arr1[i], 100 + i * 73, 520);
        ctx.fillRect(100 + i * 70, 500 - h * arr[i], 50, h * arr[i]);
    }
</script>
</body>

效果如下:

canvas核心内容_第4张图片

4、绘制曲线

方法:ctx.arc():在当前子路经添加一条弧线;

语法:context.arc(x,y,r,sAngle,eAngle,counterclockwise);

参数 描述
x 圆的中心的 x 坐标。
y 圆的中心的 y 坐标。
r 圆的半径。
sAngle 起始角,以弧度计。(弧的圆形的三点钟位置是 0 度)。
eAngle 结束角,以弧度计。
counterclockwise 可选。规定应该逆时针还是顺时针绘图。False = 顺时针,true = 逆时针。

案例一:时钟

    <style>
        #box {
            border: 2px solid black;
        }
    </style>
</head>

<body>
    <canvas id="box" width="600" height="600"></canvas>

    <script>
        /** @type {HTMLCanvasElement} */
        var canvas = document.querySelector('#box');
        var ctx = canvas.getContext('2d');


        //角度转换单位度
        let deg = Math.PI / 180;

        //表盘的绘制
        function biaopan() {
            //圆心(300,300) 半径:200,从0度-360度画圆
            ctx.arc(300, 300, 200, 0, 360 * deg)
            //刻度
            //设置开始角度6度 刻盘上每两个刻度之间的角度是6度
            var startAnge = 6,
                r = 200,
                y1 = 300,
                x1 = 300;
            var kedu = 10; //刻度的长度
            for (let i = 0; i < 60; i++) {
                var kedu = 10; //刻度的长度,i%5为真时刻度不变,为假时长度变为二倍
                let a;
                if (i % 5) {
                    a = kedu;
                } else {
                    a = kedu * 2;
                }

                //计算每个刻度所在的坐标
                var y2 = y1 + r * Math.sin(i * startAnge * deg);
                var x2 = x1 + r * Math.cos(i * startAnge * deg);

                var y3 = y1 + (r - a) * Math.sin(i * startAnge * deg);
                var x3 = x1 + (r - a) * Math.cos(i * startAnge * deg);

                //刻度连线
                ctx.moveTo(x2, y2);
                ctx.lineTo(x3, y3);
                ctx.stroke();
            }

        }

        //绘制表针
        function biaozhen() {
            //三根针的长度
            var sh = 160,
                mh = 130,
                hh = 100;
            var s = new Date().getSeconds();
            ctx.moveTo(300, 300);
            //秒针
            var x4 = 300 + sh * Math.cos(s * 6 * deg);
            var y4 = 300 + sh * Math.sin(s * 6 * deg);
            //分针,一秒钟分针转动1/10度
            var x5 = 300 + mh * Math.cos(s * 1 / 10 * deg);
            var y5 = 300 + mh * Math.sin(s * 1 / 10 * deg);
            //时针,一秒钟分针转动1/120度
            var x6 = 300 + hh * Math.cos(s * 1 / 120 * deg);
            var y6 = 300 + hh * Math.sin(s * 1 / 120 * deg);

            ctx.lineTo(x4, y4);
            ctx.moveTo(300, 300);
            ctx.lineTo(x5, y5);
            ctx.moveTo(300, 300);
            ctx.lineWidth = 2;
            ctx.lineTo(x6, y6);
            ctx.stroke();

        }
        setInterval(() => {
            canvas.width = canvas.width; //清除上一次的直线
            biaopan()
            biaozhen()
        }, 1000)
    </script>
</body>

效果图:

canvas核心内容_第5张图片

案例二:饼状图

<body>
    <canvas id="box" width="600" height="600"></canvas>

    <script>
        /** @type {HTMLCanvasElement} */
        var canvas = document.querySelector('#box');
        var ctx = canvas.getContext('2d');
        //模拟数据,一个月的消费统计
        var arr = [{
                name: '食物',
                money: 1870
            },
            {
                name: '出行',
                money: 2470
            },
            {
                name: '衣服',
                money: 3470
            },
            {
                name: '药物',
                money: 470
            },
            {
                name: '其他',
                money: 1470
            },
        ]
        //添加元素记录总金额
        arr.total = 0;
        for (let j = 0; j < arr.length; j++) {
            //计算总金额
            arr.total += arr[j].money;
        }


        //开始绘制的角度位置
        var start = 0;
        for (let i = 0; i < arr.length; i++) {
            //每一次绘制扇形呈现不一样的颜色,所以要开启新的轨道
            ctx.beginPath()
            //每一个扇形的比例
            var bili = arr[i].money / arr.total * 360;
            //换算一度的单位deg保存
            var deg = Math.PI / 180;
            //绘制扇形
            ctx.arc(300, 300, 200, start * deg, (start + bili) * deg);
            //每次扇形绘制的终点,为下一个扇形绘制的起点


            //添加文字到每个角度的中心线
            var x = 300 + 230 * Math.cos(((start + bili) - bili / 2) * deg);
            var y = 300 + 230 * Math.sin(((start + bili) - bili / 2) * deg);
            //设置文字大小,字体样式
            ctx.font = " 14px sans-serif"
            //设置文字颜色
            ctx.fillStyle = 'black';
            //设置文字水平方向居中
            ctx.textAlign = "center";
            //设置垂直方向居中
            ctx.textBaseline = "middle"
            ctx.fillText(`${arr[i].name}`, x, y)
            start = start + bili;
            //每次扇形绘制的终点与圆心连接起来
            ctx.lineTo(300, 300);

            //生成随机色
            let r = parseInt(Math.random() * (255));
            let g = parseInt(Math.random() * (255));
            let b = parseInt(Math.random() * (255));
            ctx.fillStyle = `rgb(${r},${g},${b})`;

            //填充颜色
            ctx.fill()
            //绘制图形
            ctx.stroke()
        }
    </script>

</body>

效果图:

canvas核心内容_第6张图片

5、绘制文本信息

1、font属性:可以设置字体的大小和字体名称。

fillText方法的作用:填充文字。

ctx.fillText("我是微软雅黑",100,100);

第一个参数:填充的文字内容。

第二、三个参数: 绘制的内容; 起点x坐标; 起点y坐标。

2、textAlign属性的作用:文字水平的对齐方式。

ctx.textAlign = "left";

3、textBaseline则指定垂直方向,可选值:top、hanging,middle,等

ctx.textBaseline='middle';

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PRTI5J4b-1658633907279)(C:\Users\Lenovo\AppData\Roaming\Typora\typora-user-images\image-20220724111833533.png)]

案例:

   <style>
        canvas{
            border: 1px solid black;
        }
    </style>
</head>
<body>
    <canvas width="600" height="400" id="myCanvas"></canvas>
</body>
</html>
<script>
    var canvas = document.getElementById("myCanvas");
    var ctx = canvas.getContext("2d");
    //写文字
    ctx.font = "30px 微软雅黑";
    ctx.textAlign = "left";
    ctx.fillText("我是微软雅黑",100,100); // (100,100)是绘制文字的位置
</script>

效果如下:

canvas核心内容_第7张图片

6、绘制图片

drawImage():将原图片像素的内容复制到画布上;

​ 第一个参数是源图片,可以是img元素或Image构造函数创建的屏幕外图片对象;

​ 三个参数时: 指定图片绘制的x、y坐标;

​ 五个参数时: 指定图片绘制的x、y坐标,以及图片的宽度、高度;

​ 九个参数时: 裁剪的对象 裁剪的位置(x,y); 裁剪的宽度和高度(w,h); 裁剪后图片绘制的位置(x,y); 图片显示出来的宽度和高度(w,h);

参数 描述
img 规定要使用的图像、画布或视频。
sx 可选。开始剪切的 x 坐标位置。
sy 可选。开始剪切的 y 坐标位置。
swidth 可选。被剪切图像的宽度。
sheight 可选。被剪切图像的高度。
x 在画布上放置图像的 x 坐标位置。
y 在画布上放置图像的 y 坐标位置。
width 可选。要使用的图像的宽度。(伸展或缩小图像)
height 可选。要使用的图像的高度。(伸展或缩小图像)

绘制的两种方法:

案例:

  1. 获取页面已经存在的图片节点,绘制到画布上。

    <style>
        #box {
            border: 2px solid black;
        }
    </style>
    </head>
    
    <body>
        <canvas id="box" width="800" height="200"></canvas>
        <img src="../dom/image/flower1.png" alt="">
    
        <script>
            /** @type {HTMLCanvasElement} */
            var canvas = document.querySelector('#box');
            var img1 = document.querySelector('img')
            var ctx = canvas.getContext('2d');
    
            img1.onload = function () {
                ctx.drawImage(img1, 20, 20, 100, 100);
            }
        </script>
    </body>
    
  2. 创建构造函数加载图片

    <style>
        #box {
            border: 2px solid black;
        }
    </style>
    </head>
    
    <body>
        <canvas id="box" width="800" height="200"></canvas>
    
    
        <script>
            /** @type {HTMLCanvasElement} */
            var canvas = document.querySelector('#box');
            var ctx = canvas.getContext('2d');
            var imgobj = new Image();
            imgobj.src = '../dom/image/flower1.png'
            imgobj.onload = function () {
                ctx.drawImage(imgobj, 20, 20, 100, 100);
            }
        </script>
    </body>
    
    

    效果如下:

    canvas核心内容_第8张图片

7、清除画布指定元素

clearRect() 方法清空给定矩形内的指定像素 ;

JavaScript 语法:

context.clearRect(x,y,width,height);
参数 描述
x 要清除的矩形左上角的 x 坐标
y 要清除的矩形左上角的 y 坐标
width 要清除的矩形的宽度,以像素计
height 要清除的矩形的高度,以像素计

案例:橡皮擦

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        #box {
            border: 2px solid black;
        }

        .cut {
            width: 60px;
            height: 60px;
            background: url(./image/橡皮擦.png);
            background-size: cover;
            /* background-color: green; */
            position: absolute;
            display: inline-block;
        }
    </style>
</head>

<body>
    <canvas id="box" width="600" height="600">
    </canvas>
    <div class="cut"></div>
    <h2>画布内点击生花,拖动右方橡皮擦擦除画布</h2>

    <script>
        /** @type {HTMLCanvasElement} */

        var canvas = document.querySelector('#box');
        var ctx = canvas.getContext("2d");
        var cut = document.querySelector('.cut');
        cut.addEventListener('mousedown', function (e) {
            // console.log(1111);
            var x = e.pageX - cut.offsetLeft;
            var y = e.pageY - cut.offsetTop;

            document.addEventListener('mousemove', move);

            function move(e) {
                cut.style.left = (e.pageX - x) + 'px';
                cut.style.top = (e.pageY - y) + 'px';
                ctx.clearRect(e.pageX - x, e.pageY - y, 40, 40);
            }

            document.addEventListener('mouseup', function () {
                document.removeEventListener('mousemove', move);
            })
        })


        var imgobj = new Image();
        imgobj.src = '../dom/image/flower1.png';
        //点击生花
        imgobj.onload = function () {
            canvas.addEventListener('click', function (e) {
                var x = e.pageX - 30,
                    y = e.pageY - 30;
                ctx.drawImage(imgobj, x, y, 60, 60);
            })
        }
    </script>
</body>

</html>

效果如下:

canvas核心内容_第9张图片

你可能感兴趣的:(javascript,前端,vscode,canvas)