JavaScript 30天编码挑战——第 8 天

159 阅读2分钟

这是我参与更文挑战的第10天,活动详情查看: 更文挑战

Fun with HTML5 Canvas

一、效果展示

1.index-START.html

1.gif 不要有丝毫怀疑,因为他真的什么也没显示,仅仅只有一个空白的 canvas 画布。

2.index-FINISHED.html

2.gif 随心所欲的效果,看起来很不错,值得尝试一波。

二、实现

用 HTML5 中的 Canvas 的路径绘制实现一个画板,移动鼠标,可以画出渐变色的颜色效果,画笔大小同样呈渐变效果。

最终代码

<script>
  (function(){

      let canvas = document.querySelector('#draw');
      let ctx = canvas.getContext('2d');
      let cololrDeg = 0;
      let lineWidth = 50;
      let direction = -1;
      let alpha = 1;
      let alphaDirect = 0.1;
      ctx.strokeStyle = `hsla(${cololrDeg},100%,50%,${alpha})`;
      ctx.lineWidth = lineWidth;
      ctx.lineCap = "round";
      ctx.lineJoin = "round";  //有 round | bevel | miter 圆交、斜交、斜接三种
      let drawing = false;
      let x = 0 ,
          y = 0;
      canvas.addEventListener('mousedown',(e)=>{
          drawing = true;
          [x,y] = [e.offsetX,e.offsetY];
      })
      canvas.addEventListener('mousemove',(e)=>{
        if(!drawing) return;
        console.log('drawing');

        ctx.beginPath();
        cololrDeg = cololrDeg < 360 ? cololrDeg + 1 : 0 ;
        if(alpha <= 0.25 || alpha >= 1){
          alphaDirect *= -1;
        }
        alpha += alphaDirect;
        ctx.strokeStyle = `hsla(${cololrDeg},100%,50%,${alpha})`;
        if(lineWidth < 1 || lineWidth > 50){
            direction *= -1;
        }
        lineWidth = lineWidth > 1 ? lineWidth - 1 : 1;
        ctx.lineWidth = lineWidth;
        ctx.moveTo(x,y);
        ctx.lineTo(e.offsetX,e.offsetY);
        [x,y] = [e.offsetX,e.offsetY];
        ctx.strokeStyle();
      })
      canvas.addEventListener('mouseup' ,()=>{
        drawing = false;
      })
      canvas.addEventListener('mousedown',()=>{
        drawing = false;
      })

})()
</script>

三、总结回顾

这部门内容主要涉及的是 canvas 的一些基本属性、鼠标的事件处理和路径的绘制。

1.基本操作:

  • getContext()
  • strokeStyle
  • fillStyle
  • lineCap
  • lineJoin 2.鼠标事件处理:
  • mousemove
  • mousedown
  • mouseup
  • mouseout 3.绘制路径线条:
  • beginPath()
  • lineTo()
  • moveTo()

过程分解

  1. 获取 HTML 中的 canvas 元素
let canvas = document.querySelector('#draw');
  1. 鼠标事件
canvas.addEventListener('mousedown',()=>{

      })
      canvas.addEventListener('mousemove',()=>{
        
      })
      canvas.addEventListener('mouseup',()=>{
        
      })
      canvas.addEventListener('mousedown',()=>{
        
      })

这里最后多了一个 mouseout 事件,为什么要添加这个事件呢,是我们在滑动的时候可能会划出画布的范围,这个时候我们就要设置这个事件。

另外,大家感兴趣的去了解一下 mouseoutmouseleave 的区别。

接下来就该设置画画的状态了

let drawing = false;
      canvas.addEventListener('mousedown',()=>{
          drawing = true;
      })
      canvas.addEventListener('mousemove',()=>{
        
      })
      canvas.addEventListener('mouseup',()=>{
        drawing = false;
      })
      canvas.addEventListener('mousedown',()=>{
        drawing = false;
      })

那么现在是一个什么样的效果呢?我们打印看一下现在的状态:

canvas.addEventListener('mousemove',()=>{
        console.log('drawing')
      })

3.gif 现在的状态就是只要我移动鼠标,他就会一直在画,这当然不是我们想要的效果,我们想要的是当我们点击按下的时候它才开始画。

    canvas.addEventListener('mousemove',()=>{
        if(!drawing) return;
        console.log('drawing')
      })
  1. getContext('2d') 获取上下文
let ctx = canvas.getContext('2d');
  1. 设置 ctx 的基本属性
  • 描边和线条颜色
  • 线条宽度
  • 线条末端形状
  • 转折角的形状
      ctx.strokeStyle = "hsl(0,100%,50%)";
      ctx.lineWidth = 100;
      ctx.lineCap = 'round';
      ctx.lineJoin = 'round';  //有 round | bevel | miter 圆交、斜交、斜接三种
  1. 开始画线
      let x = 0 ,
          y = 0;
      canvas.addEventListener('mousedown',(e)=>{
          drawing = true;
          [x,y] = [e.offsetX,e.offsetY];
      })
      canvas.addEventListener('mousemove',()=>{
        if(!drawing) return;
        console.log('drawing');

        ctx.beginPath();

        ctx.moveTo(x,y);
        ctx.lineTo(ex.offsetX,e.offsetY);
        [x,y] = [e.offsetX,e.offsetY];
        ctx.strokeStyle();
      })

效果展示: 4.gif

6.渐变色

      let cololrDeg = 0;
      ctx.strokeStyle = `hsl(${cololrDeg},100%,50%)`;
      
      canvas.addEventListener('mousemove',(e)=>{
        if(!drawing) return;
        console.log('drawing');

        ctx.beginPath();
        
        //这里
        cololrDeg = cololrDeg < 360 ? cololrDeg + 1 : 0 ;
        ctx.strokeStyle = `hsl(${cololrDeg},100%,50%)`;
        
        ctx.moveTo(x,y);
        ctx.lineTo(e.offsetX,e.offsetY);
        [x,y] = [e.offsetX,e.offsetY];
        ctx.strokeStyle();
      })

5.gif

四、重难点

今天的重点难部分内容稍微有写杂,还是有挺多个小地方需要注意的,我想单独拿出来去做一个整理,这个我们下一篇再见。

也可能会在后面会对今天的模块做一个修改。

后面想要实现橡皮擦的功能,单纯的个人比较感兴趣罢了,就当是继续总结的动力吧。