canvas

作者: 欢欣的膜笛 | 来源:发表于2021-02-18 19:43 被阅读0次

    用法

    1. rect():指定矩形的轨迹

      • 参数:左上角顶点的坐标 x、y 和矩形的宽高
      • 说明:不会描边,需要自己手动调用 stroke 方法实现描边
    2. strokeRect():直接绘制出一个描边的矩形

    3. fillRect():直接绘制出一个填充的矩形

    4. stroke():绘制描边的图形

      • stroke 内部不会自动将未闭合的区域闭合起来
      • 如果需要闭合,可以通过 closePath() 来闭合
    5. fill():绘制实心的图形
      fill 方法内部会自动闭合区域(原理就跟 closePath 一样)

    6. closePath:闭合区域
      将终点和起点用一条线连接起来

    7. 设置颜色

      • strokeStyle:设置描边图形的颜色
      • fillStyle:设置填充图形的颜色
      • 值是一个字符串的值,可以是任意颜色值(如:"red", "#fff", "rgba(255,0,0,0.1)", "rgb(255,0,0)"
    8. 非零环绕规则

      • 每一次 fill 方法内部绘制图形的时候都遵循非零环绕规则
      • 通过非零环绕规则来判断该区域中的每一个像素点是否需要填充(在绘制多个图形的时候,多个图形有重合的区域,默认情况下,后绘制的就会覆盖之前绘制的部分)
      • 规则内容:选定区域内部的某个点,往区域外部任意方向发一条射线,设置射线的起点为0,射线每一次与图形的轨迹相交,判断该轨迹是顺时针还是逆时针,如果是逆时针-1,顺时针+1,最终一起计算结果,如果最终计算结果为0该点不需要填充,不为0就是需要填充的
    9. setLineDash():绘制虚线

      • 参数是一个数组
      • 数组中没有元素,那么绘制的就是实线
      • 数组中1个元素([5]),表示实线和空白部分长度都为5
      • 数组中2个元素([10,5]),表示实线部分长度为10,空白部分长度为5
      • 数组中3个元素([10,5,5]),表示第一个实线部分长度为10,第一个空白部分长度为5,第二个实线长度为5,第二个空白长度为10,第三个实现长度为5,第三个空白长度位5,后面以此类推
    10. clearRect:清除画布中指定的矩形区域

      • 参数:跟 rect 方法相同
      • 实现清空画布:ctx.clearRect(0,0,canvas.width,canvas.height);
    11. HTML 标签的一些属性很多时候会直接映射到该 DOM 元素中,作为这个对象的属性存在,就可以直接通过访问对象的属性来进行操作

      • canvas.width=200; console.log(canvas.width);
      • 但是这种方式不能操作自定义属性,对于自定义属性只能通过getAttribute / setAttribute 来进行操作
    12. 绘制文本

      • strokeText("文本内容", x轴, y轴)
      • fillText("文本内容", x轴, y轴)
        1. 文本是不会产生路径的,也不会因为状态的影响而造成混乱的结果
        2. 如果只需要绘制文本,不需要 beginPath ,当然在实际开发中保守起见还是习惯性的 beginPath();
        3. font 属性:设置文本的格式,比如 font="30px Microsoft Yahei";
        4. textAlign:文本的水平对齐方式(默认值是 start : 左对齐)
          • left 文本左对齐(文字的最左边靠着起点x轴所在)
          • right 文本右对齐
          • center 文本居中对齐
          • start 相当于 left
          • end 相当于 right
        5. textBaseLine:文本的垂直对齐方式(默认值是 alphabetic)
          • top:文本基线在文本块的顶部。
          • hanging:文本基线是悬挂基线。
          • middle:文本基线在文本块的中间。(文字垂直居中)
          • alphabetic:文本基线是标准的字母基线(英语四线格的第三条线)
          • bottom:文本基线在文本块的底部。
        6. measureText("文本内容")
          • 返回一个对象,该对象中含有 width 属性表示文本的宽度
          • 在计算的时候会根据当前设置过的字体大小和字体类型,动态分析出指定文字要占用多少宽度
    13. 绘制折线图以及折线图上面的点

      • 绘制坐标线
      • 绘制坐标轴上的文字
      • 绘制点 ctx.fillRect(x-3, y-3, 6, 6);
      • 将点连成线 ctx.moveTo(100, 100); ctx.lineTo(700, 500);
    14. 绘制圆弧

      • arc(圆心x,圆心y,半径,开始弧度,结束弧度,是否以逆时针方式绘制)
      • 整个圆是 2 * Math.PI 的,0的位置位于圆心水平往右拉直线,Math.PI/2 就位于圆心的正下方
      • 默认的绘制方式是:顺时针,可以通过 arc 方法的第6个参数传递值为 true 表示逆时针方式绘制
    15. 创建图片

    var img=document.createElement("img");
    // or
    var img=new Image();
    
    img.src="";
    
    1. drawImage(图片对象, sx, sy, sw, sh, x, y, width, height)

      • 参数1:图片对象
      • 将图片的以 sx, sy 点为顶点,宽度为 sw,高度为 sh 的矩形区域内的部分绘制到 canvas 的以 x, y 为顶点,宽为 width,高为 height 的区域内
      • 保持纵横比:
      • 注意:需要在图片加载完成之后,才能绘制该图片
    2. ctx.translate(x, y):平移变换

      • x 为正数表示 canvas 顶点沿着 x 轴向右移动,负数表示向左移动
      • y 为正数表示 canvas 顶点沿着 y 轴向下移动,负数表示向上移动
      • 举例:ctx.translate(100,200):坐标轴向右移动 100px,向下移动 200px
    3. 伸缩变换

      • scale(1, 1):不伸缩
      • scale(0.5, 1):x轴压缩一半
      • scale(1, 0.5):y轴压缩一半
    4. 状态的保存与恢复

      • save()
      • restore()
    5. 时钟

      • 绘制外层大圆
        bigX, bigY, bigRadius
      • 绘制刻度线
        1. 刻度线属性(长度、线宽)
        2. 整个表盘中具有60个刻度线,刻度线有大小两种,每5格就有一个粗刻度线
      • 绘制刻度盘文字
        文字属性(颜色、大小、字体类型)
      • 绘制指针
        时针、分针、秒针的属性(长度、线宽、颜色)
        function Clock(opt){
            //参数必填
            if(!opt){ throw new Error("参数必填!"); }
            //必填参数
            var props = {canvas:"",radius:""};
            for(var key in props){
                if(!opt.hasOwnProperty(key)){
                    throw new Error("请填入"+key+"参数");
                }
            }
            //选填参数
            var defaultObj = {
                clockX:400,
                clockY:300,
                smallLength:10,
                smallWidth:4,
                bigLength:25,
                bigWidth:10
            };
            for(var key in defaultObj){
                opt[key] = opt[key] || defaultObj[key];
            }
    
            for(var key in opt){
                this[key] = opt[key]
            }
            this.ctx = this.canvas.getContext("2d");
            this.startRad = -Math.PI/3;
            this.init();
            var self = this;
            this.timer = setInterval(function () {
                self.ctx.clearRect(0,0,self.canvas.width,self.canvas.height);
                self.init();
            },1000);
        }
        Clock.prototype = {
            constructor:Clock,
            init: function (){
                //绘制表盘
                this.drawBigCircle();
                //绘制所有刻度线
                this.drawTicks();
                //绘制所有指针
                this.drawPoints();
            },
            //绘制表盘
            drawBigCircle: function () {
                this.ctx.beginPath();
                this.ctx.save();
                this.ctx.arc(this.clockX,this.clockY,this.radius,0,2*Math.PI);
                this.ctx.lineWidth = 10;
                this.ctx.strokeStyle = "deepskyblue";
                this.ctx.stroke();
                this.ctx.restore();
            },
            //绘制所有刻度线
            drawTicks: function () {
                this.ctx.font = "24px 微软雅黑";
                this.ctx.textAlign = "center";
                this.ctx.textBaseline = "middle";
                var singleRad = 2*Math.PI/60;
                var length,width;
                for(var i = 0;i < 60;i++){
                    var rad = this.startRad+singleRad*i;
                    if(i%5 == 0){
                        length = this.bigLength;
                        width = this.bigWidth;
                        //绘制表盘上数字
                        this.drawText(rad,length,i);
                    }else{
                        length = this.smallLength;
                        width = this.smallWidth;
                    }
                    //绘制单个刻度线
                    this.drawTick(rad,length,width);
                }
            },
            //绘制单个刻度线
            drawTick: function (rad,length,width) {
                var radius = this.radius - 5;
                this.ctx.lineWidth = width;
                var x1 = this.clockX+Math.cos(rad)*(radius-length);
                var y1 = this.clockY+Math.sin(rad)*(radius-length);
                var x2 = this.clockX+Math.cos(rad)*radius;
                var y2 = this.clockY+Math.sin(rad)*radius;
                this.ctx.beginPath();
                this.ctx.moveTo(x1,y1);
                this.ctx.lineTo(x2,y2);
                this.ctx.stroke();
            },
            //绘制所有指针
            drawPoints: function () {
                var date = new Date();
                var hour = date.getHours();
                hour = hour<12?hour:hour-12;
                var minute = date.getMinutes();
                var second = date.getSeconds();
    
                var hourRad = hour*2*Math.PI/12+minute/60*2*Math.PI/12-Math.PI/2;
                var minuteRad = minute*2*Math.PI/60-Math.PI/2;
                var secondRad = second*2*Math.PI/60-Math.PI/2;
    
                this.ctx.save();
    
                //绘制时针
                this.drawPoint("deepskyblue",60,8,hourRad);
    
                //绘制分针
                this.drawPoint("yellow",90,6,minuteRad);
    
                //绘制秒针
                this.drawPoint("red",120,4,secondRad);
    
                this.ctx.restore();
            },
            //绘制单个指针
            drawPoint: function (color,length,width,rad) {
                this.ctx.beginPath();
                this.ctx.strokeStyle = color;
                this.ctx.lineWidth = width;
                var x = this.clockX+Math.cos(rad)*length;
                var y = this.clockY+Math.sin(rad)*length;
                this.ctx.moveTo(this.clockX,this.clockY);
                this.ctx.lineTo(x,y);
                this.ctx.stroke();
            },
            //绘制表盘上数字
            drawText: function (rad,length,i) {
                var x = this.clockX+Math.cos(rad)*(this.radius-length-24);
                var y = this.clockY+Math.sin(rad)*(this.radius-length-24);
                this.ctx.fillText(i/5+1,x,y);
            }
        }
    
        var canvas = document.querySelector("canvas");
        var obj = {
            canvas:canvas,
            //表盘参数
            clockX:400,
            clockY:300,
            radius:160,
            //刻度参数
            smallLength:10,
            smallWidth:4,
            bigLength:25,
            bigWidth:10,
        };
        var clock1 = new Clock(obj);
    

    理论与实践相结合

      <canvas width="650" height="500"></canvas>
    
      // 获取画布
      var canvas = document.querySelector('canvas')
      // 获取绘制的对象
      var ctx = canvas.getContext('2d')
      // 开始一条路径,或重置当前的路径
      ctx.beginPath()
      ctx.moveTo(50, 50)
      ctx.lineTo(200, 100)
      ctx.lineTo(50, 150)
      // 闭合路径
      ctx.closePath()
      ctx.strokeStyle="red"
      // 设置连接处样式,lineJoin: round、bevel、miter(默认)
      ctx.lineJoin = "round"
      ctx.lineWidth = 10
      ctx.stroke()
    
      // 渐变
      // 起始位置的横纵坐标,结束位置的横纵坐标
      var lgd = ctx.createLinearGradient(250, 100, 550, 100)
      // 添加渐变的颜色,0 表示开始,1 表示结束
      lgd.addColorStop(0, 'pink')
      lgd.addColorStop(0.7, 'red')
      lgd.addColorStop(0.9, 'yellow')
      // 把渐变的方案给 strokeStyle
      ctx.strokeStyle = lgd
      ctx.beginPath()
      ctx.moveTo(250, 100)
      ctx.lineTo(550, 100)
      ctx.stroke()
    
      // 镜像渐变
      // 起始位置的横纵坐标、半径,结束位置的横纵坐标、半径
      var rgd = ctx.createRadialGradient(250, 250, 30, 250, 250, 100)
      rgd.addColorStop(0, 'red')
      rgd.addColorStop(1, 'yellow')
      ctx.fillStyle = rgd
      ctx.beginPath()
      ctx.moveTo(150, 150)
      ctx.lineTo(350, 150)
      ctx.lineTo(350, 350)
      ctx.lineTo(150, 350)
      ctx.closePath()
      // 填充
      ctx.fill()
    
      // 非零环绕
      // 如果需要判断某一个区域是否需要填充颜色,就从该区域中随机的选取一个点。
      // 从这个点拉一条直线出来, 一定要拉到图形的外面,此时以该点为圆心。
      // 看穿过拉出的直线的线段,顺时针方向记为 +1, 逆时针方向记为 -1,最终看求和的结果。
      // 如果是 0 就不填充,如果是非零就填充
      ctx.beginPath()
      ctx.strokeStyle = 'yellow'
      // 顺时针
      ctx.moveTo(450, 200)
      ctx.lineTo(450, 300)
      ctx.lineTo(550, 300)
      ctx.lineTo(550, 200)
      ctx.closePath()
    
      // 逆时针
      ctx.moveTo(400, 150)
      ctx.lineTo(600, 150)
      ctx.lineTo(600, 350)
      ctx.lineTo(400, 350)
      ctx.closePath()
      ctx.stroke()
      ctx.fillStyle = 'pink'
      ctx.fill()
    
      // 虚线
      ctx.beginPath()
      ctx.moveTo(50, 380)
      ctx.lineTo(300, 380)
      // 第一个参数代表线的长度,第二个参数代表空白部分的长度
      ctx.setLineDash([20, 10])
      // 线-空白-线-空白(循环)
      // ctx.setLineDash([20, 5, 10])
      ctx.strokeStyle = 'pink'
      ctx.lineWidth = 2
      ctx.stroke()
    
      // 绘制移动的矩形
      // 刚开始时矩形的横坐标
      var x = 0
      // 每次移动的步数
      var step = 5
      // 标记,当矩形移动到右侧后再回来
      var i = 1
      setInterval(() => {
          // 清理画布
          ctx.clearRect(0, 400, canvas.width, 50)
          ctx.fillStyle = 'pink'
          // 横纵坐标、宽、高
          ctx.fillRect(x, 400, 50, 50)
          ctx.stroke()
          x += step * i
          if (x > canvas.width - 50) {
              i = -1
          } else if (x <= 0) {
              i = 1
          }
      }, 10);
    
      // 绘制文本
      ctx.beginPath()
      // 设置文本的像素、字体
      ctx.font = '50px 宋体'
      // 设置文本的左右对齐方式:  center、left、right
      ctx.textAlign = 'center'
      // 设置文本的上下对齐方式:top、bottom、middle、alphabetic(默认)
      ctx.textBaseline = 'middle'
      // 设置阴影颜色
      ctx.shadowColor = 'red'
      // 设置阴影偏移量
      ctx.shadowOffsetX = 15
      // 设置阴影模糊度
      ctx.shadowOffsetY = 5
      ctx.shadowBlur = 5
      ctx.strokeStyle = 'black'
      ctx.strokeText('好无聊', 100, 500)
    

    相关文章

      网友评论

          本文标题:canvas

          本文链接:https://www.haomeiwen.com/subject/azunxltx.html