美文网首页js
canvas初探

canvas初探

作者: 变量只提升声明不提升赋值 | 来源:发表于2022-08-16 22:07 被阅读0次

    要通过canvas绘制图形,首先得获取到canvas的上下文对象。这个对象里提供了各种api供我们去绘制图形

    <canvas width="800" height="500" id="mycanvas" style="border: 1px solid #ddd"></canvas>
    
      let cnv = document.getElementById('mycanvas')
      let ctx = cnv.getContext('2d')
    

    绘制边框,线

    ctx.moveTo(100,50) //起点坐标
    ctx.lineTo(200,100) //终点坐标
    ctx.lineWidth = 20 //线的粗细
    ctx.strokeStyle = 'pink' //线的颜色
    ctx.lineCap = 'round'  //直线两端的样式 默认butt,圆形round,方形 square
    ctx.stroke() //绘制线段
    

    多个点连成一个图形

       ctx.strokeStyle = 'red'
       ctx.moveTo(100,100)
       ctx.lineTo(200,100)
       ctx.lineTo(200,200)
       ctx.closePath()  //闭合
    

    填充颜色

    ctx.fillStyle = 'yellow'
    ctx.fill()
    

    绘制图片

    ctx.drawImage(image,图片左上角的x轴坐标,图片左上角的y轴坐标,图片的宽度,图片的高度)
    第一个参数可以是一个img元素,可以是video等等,具体的自行百度
    

    将canvas转成base64图片

    
    ctx.toDataURL('image/png')
    

    绘制一个圆

     /**
       * 绘制一个圆
       * 绘制圆形之前必须先开辟路劲,绘制结束之后调用closePath闭合
       * arc(圆心x坐标,圆心y坐标,半径,起始角度,结束角度)  起始角度是水平x轴开始
       * 1°等于 Math.PI/180
       * stroke绘制线条,fill绘制图形,可填充颜色
       */
      ctx.arc(150, 100, 50, 120* Math.PI/180, 60 * Math.PI/180)
      ctx.stroke()
      ctx.fill()
    

    绘制一个扇形

    扇形其实就是在绘制原型的基础上,将画出的圆弧和原型点进行闭合
     ctx.arc(150, 100, 50, 0, 60 * Math.PI/180) //这样能绘制出一个圆弧
     ctx.lineTo(150,100) //这个坐标点为圆心坐标点
     ctx.closePath() //闭合一下,就得到一个圆弧了,不过此时没有边框也没有填充颜色是看不到效果的
    ctx.fillStyle = 'yellow'
    ctx.fill()
    加上这两行,就可以看到一个黄色的扇形了
    

    几个需要注意的点,
    1.stroke就是和线条相关的api,stroke()可以绘制线条,其他以stroke开头的api可以设置线条的样式
    2.fill为填充相关api
    3.当需要重新绘制一个图形的时候需要调用beginPath函数来开辟一个新的路劲,不然后续绘制的样式都会基于上一次绘制的东西上。举个例子

      ctx.moveTo(100,50) //线的起始坐标X,Y
      ctx.lineTo(200,100) //线的结束坐标X,Y
       ctx.lineWidth = 20 //线的粗细
       ctx.strokeStyle = 'pink' //线的颜色
       ctx.lineCap = 'round'  //直线两端的样式 默认butt,圆形round,方形 square
      ctx.stroke() //连接两个坐标点
    
      ctx.beginPath() //重新开辟一个路劲,不然所有的线会沿用同一个样式
      ctx.moveTo(50,50) //线的起始坐标X,Y
      ctx.lineTo(100,100) //线的结束坐标X,Y
      ctx.lineWidth = 20 //线的粗细
      ctx.strokeStyle = 'red' //线的颜色
      ctx.lineCap = 'round'  //直线两端的样式 默认butt,圆形round,方形 square
      ctx.stroke() //连接两个坐标点
    

    4.canvas的坐标系是这样的


    edafb74caf78aca6133421e76b9ed28.jpg

    附上几个小demo

    canvas画一个仪表盘的进度条
    其实就是绘制一个缺了角的圆,不填充颜色,然后然线条的粗细调大一点,再给线条一个颜色就行了
      let oneAge = Math.PI / 180
      ctx.beginPath()
      let zhongdian = 120
      ctx.lineWidth = 10
      ctx.strokeStyle = 'pink'
      ctx.lineCap = 'round'
      ctx.fillStyle = 'pink'
      let t =  setInterval(()=>{
       if(zhongdian==60){
         clearInterval(t)
       }else{
         zhongdian+=10
         if(zhongdian == 360){
           zhongdian = 0
         }
         console.log(zhongdian)
         ctx.beginPath()
         ctx.fillStyle = 'pink'
         ctx.arc(150,100,50,120*oneAge,zhongdian*oneAge)
         ctx.stroke()
       }
      },30)
    
    image.png
    画一个大转盘,原理就是画扇形,再每个扇形的基础上读书递增,填满整个圆
      let deg = Math.PI/180 //1°
      ctx.strokeStyle = 'pink'
      ctx.fillStyle = 'yellow'
      for (let i = 0;i<12;i++){
        ctx.beginPath()
        ctx.arc(400,250,100,30*i*deg,30*(i+1)*deg)
        ctx.lineTo(400,250)
        ctx.closePath()
        ctx.fill()
        ctx.stroke()
      }
      ctx.beginPath()
      ctx.strokeStyle='red'
      ctx.moveTo(400,250)
      ctx.lineTo(400,180)
      ctx.stroke()
      cnv.style.transition = '10s'
      setTimeout(()=>{
        cnv.style.transform = 'rotateZ(1250deg)'
      },1000)
    
    image.png
    画一个建议的canvas签名板,原理就是监听鼠标移动事件,然后不停的去绘制线段,下一条线段的启示位置就是上一条线段的结束位置,这样就能无缝连接的绘制了
      ctx.mozImageSmoothingEnabled = false;
      ctx.webkitImageSmoothingEnabled = false;
      ctx.msImageSmoothingEnabled = false;
      ctx.imageSmoothingEnabled = false;
      ctx.lineWidth = 10;
      ctx.strokeStyle = '#333';
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';
      let isDrawing = false
      let initX
      let initY
      // 事件监听
      cnv.addEventListener('mousedown', (e) => {
        isDrawing = true;
        initX = e.offsetX;
        initY = e.offsetY
      });
      cnv.addEventListener('mousemove', draw);
      cnv.addEventListener('mouseup', () => isDrawing = false);
      cnv.addEventListener('mouseout', () => isDrawing = false);
    
      function draw(e) {
        console.log(e)
        if (!isDrawing) return;
        ctx.beginPath()
        //起点
        ctx.moveTo(initX, initY)
        //终点
        ctx.lineTo(e.offsetX, e.offsetY)
        ctx.stroke()
        initX = e.offsetX
        initY = e.offsetY
      }
      function clean(){
        ctx.clearRect(0, 0, cnv.width, cnv.height);
      }
    
    image.png

    canvas绘制长文本

    原理就是利用measureText方法,判断当前填充的文字有没有超过最大宽度限制,
    如果有,则说明填满一行了,那就另起一行接着开始绘制
                        let content = this.msg
                        let drawTxt = '' //需要被绘制的文本
                        let lineNum = 1 //行数
                        let drawIndex = 0 //文字索引
                        for (let i = 0; i < content.length; i++) {
                            drawTxt += content[i];
                                if (ctx.measureText(drawTxt).width >= 310) {
                                    ctx.fillText(drawTxt.substr(0,drawTxt.length-1), 20, lineNum * 30);
                                    drawIndex = i + 1;
                                    lineNum += 1;
                                    drawTxt = '';
                                } else {
                                    // 内容绘制完毕,但是剩下的内容宽度不到lineMaxWidth
                                    if (i === content.length - 1) {
                                        ctx.fillText(drawTxt.substr(0,drawTxt.length-1), 20, lineNum * 30);
                                    }
                                }
                            }
                        }
    

    相关文章

      网友评论

        本文标题:canvas初探

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