美文网首页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