# mouse事件

  1. mousedown

    mousedown事件在指针设备按钮按下时触发

  2. mouseup

    当指针在元素中时, mouseup事件在指针设备(如鼠标或触摸板)按钮放开时触发。mouseup 事件与mousedown事件相反。

  3. mousemove

    当指针设备 ( 通常指鼠标 ) 在元素上移动时,mousemove 事件被触发。

    下面展示一个canvas绘制线条的小例子, 可以用于移动端的签字逻辑。 完成之后把canvas转换成图片上传即可。具体操作可以查看Blob。 把mouse事件改为touch事件即可兼容移动端

    <!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>
          * {
            margin: 0;
            padding: 0;
          }
          html,
          body {
            height: 100%;
            width: 100%;
          }
          .canvas__wrapper {
            width: 667px;
            height: 375px;
            overflow: hidden;
            border: 1px solid #333;
          }
          canvas {
            width: 100%;
            height: 100%;
          }
        </style>
      </head>
      <body>
        <div class="canvas__wrapper">
          <canvas id="canvas"></canvas>
        </div>
        <div>
          <button onclick="handleFinish()">Finish</button>
        </div>
    
        <script>
          const canvas = initCanvas();
          let isSigned = false;
          function initCanvas() {
            // 判断用户是否有移动
            let canvas = document.querySelector('#canvas');
            const canvasRect = canvas.getBoundingClientRect();
            let _context = canvas.getContext('2d');
    
            let _drawSign = false;
            const canvas__wrapper = document.querySelector('.canvas__wrapper');
            canvas.setAttribute('width', canvas__wrapper.clientWidth);
            canvas.setAttribute('height', canvas__wrapper.clientHeight);
    
            // 绘制一个白色的底色
            _context.rect(0, 0, canvas__wrapper.clientWidth, canvas__wrapper.clientHeight);
            _context.fillStyle = '#ffffff';
            _context.fill();
    
            _context.strokeStyle = 'black';
            _context.lineWidth = 3;
            let startPageX, startPageY;
            canvas.addEventListener(
              'mousedown',
              e => {
                e.preventDefault();
                _context.beginPath();
                _context.moveTo(e.pageX - canvasRect.left, e.pageY - canvasRect.top);
                _context.lineTo(e.pageX - canvasRect.left, e.pageY - canvasRect.top);
                startPageX = e.pageX;
                startPageY = e.pageY;
                _context.stroke();
                _drawSign = true;
              },
              false
            );
            canvas.addEventListener(
              'mousemove',
              e => {
                console.log('touchmove');
                e.preventDefault();
    
                if (_drawSign) {
                  if (!isSigned) {
                    if (Math.abs(e.pageX - startPageX) >= 10 || Math.abs(e.pageY - startPageY) >= 10) {
                      isSigned = true;
                    }
                  }
                  _context.lineTo(e.pageX - canvasRect.left, e.pageY - canvasRect.top);
                  _context.stroke();
                }
              },
              false
            );
            canvas.addEventListener(
              'mouseup',
              e => {
                e.preventDefault();
                if (_drawSign) {
                  _drawSign = false;
                  _context.closePath();
                }
              },
              false
            );
            return canvas;
          }
          function handleFinish() {
            if (!isSigned) {
              console.log('请绘制一些内容');
              return;
            }
            if (canvas) {
              const imgBase64 = canvas.toDataURL('image/png');
              rotateBase64Img(imgBase64, 0, async dataUrl => {
                console.log(dataUrl);
                const img = new Image();
                img.src = dataUrl;
                img.style.border = '1px solid #666';
                document.body.appendChild(img);
                // this.form.signUrl = dataUrl;
                // const blob = dataURLtoBlob(dataUrl);
                /* const formData = new FormData();
                formData.append('file', blob, 'path.png');
                const { data: res } = await axios({
                  url: '',
                  method: 'POST',
                  data: formData
                });
                if (res && res.code === 200) {
                  const url = res.data.reourceAddress;
                } */
              });
            }
          }
          function rotateBase64Img(src, edg, callback) {
            var canvas = document.createElement('canvas');
            var ctx = canvas.getContext('2d');
            var imgW; //图片宽度
            var imgH; //图片高度
            var size; //canvas初始大小
            if (edg % 90 != 0) {
              console.error('旋转角度必须是90的倍数!');
              throw '旋转角度必须是90的倍数!';
            }
            edg < 0 && (edg = (edg % 360) + 360);
            const quadrant = (edg / 90) % 4; //旋转象限
            const cutCoor = { sx: 0, sy: 0, ex: 0, ey: 0 }; //裁剪坐标
            var image = new Image();
            image.crossOrigin = 'anonymous';
            image.src = src;
            image.onload = function () {
              imgW = image.width;
              imgH = image.height;
              size = imgW > imgH ? imgW : imgH;
              canvas.width = size * 2;
              canvas.height = size * 2;
              switch (quadrant) {
                case 0:
                  cutCoor.sx = size;
                  cutCoor.sy = size;
                  cutCoor.ex = size + imgW;
                  cutCoor.ey = size + imgH;
                  break;
                case 1:
                  cutCoor.sx = size - imgH;
                  cutCoor.sy = size;
                  cutCoor.ex = size;
                  cutCoor.ey = size + imgW;
                  break;
                case 2:
                  cutCoor.sx = size - imgW;
                  cutCoor.sy = size - imgH;
                  cutCoor.ex = size;
                  cutCoor.ey = size;
                  break;
                case 3:
                  cutCoor.sx = size;
                  cutCoor.sy = size - imgW;
                  cutCoor.ex = size + imgH;
                  cutCoor.ey = size + imgW;
                  break;
              }
              ctx.translate(size, size);
              ctx.rotate((edg * Math.PI) / 180);
              ctx.drawImage(image, 0, 0);
              var imgData = ctx.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey);
              if (quadrant % 2 == 0) {
                canvas.width = imgW;
                canvas.height = imgH;
              } else {
                canvas.width = imgH;
                canvas.height = imgW;
              }
              ctx.putImageData(imgData, 0, 0);
              callback(canvas.toDataURL('image/png'));
            };
          }
    
          function dataURLtoBlob(dataurl) {
            var arr = dataurl.split(','),
              mime = arr[0].match(/:(.*?);/)[1],
              bstr = atob(arr[1]),
              n = bstr.length,
              u8arr = new Uint8Array(n);
            while (n--) {
              u8arr[n] = bstr.charCodeAt(n);
            }
            return new Blob([u8arr], { type: mime });
          }
        </script>
      </body>
    </html>
    
    

    几个注意点

    1、注意canvas的width attribute和css的width属性

    2、如果是移动端一般是横屏, 需要自己旋转图像

  4. mouseenter

    当定点设备(通常指鼠标)移动到元素上时就会触发 mouseenter 事件.

    TIP

    主要是和mouseover的区别, 区别就是mouseenter不会冒泡,也就是说当指针从它的子层物理空间移到它的物理空间上时不会触发。但是从父元素移动到子元素上面还是会触发子元素的mouseenter

  5. mouseover

    当定点设备(通常指鼠标)移动到元素上时就会触发 mouseover 事件.

  6. mouseout

    当移动指针设备(通常是鼠标),使指针不再包含在这个元素或其子元素中时,mouseout 事件被触发。当指针从一个元素移入其子元素时,mouseout 也会被触发,因为子元素遮盖了父元素的可视区域。 从子元素移入父元素时,父子元素的mouseout都会触发。

  7. mouseleave

    指点设备(通常是鼠标)的指针移出某个元素时,会触发mouseleave事件。

    TIP

    mouseleavemouseout (en-US) 是相似的,但是两者的不同在于mouseleave 不会冒泡而mouseout 会冒泡。 这意味着当指针离开元素及其所有后代时,会触发mouseleave,而当指针离开元素或离开元素的后代(即使指针仍在元素内)时,会触发mouseout

  8. mousewheel

    鼠标滚轮事件, 其实还是需要各种兼容的, 我们看一下这个mousewheel, 其实也不是兼容的很好目前。查看一个例子吧

    <!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>
          .container {
            width: 200px;
            height: 200px;
            background-color: green;
          }
        </style>
      </head>
      <body>
        <div class="container"></div>
        <script>
          const container = document.querySelector('.container');
          container.onmousewheel = function (event) {
            event = event || window.event;
            let wheelDirection = '';
            if (event.wheelDelta > 0 || event.detail < 0) {
              wheelDirection = 'top';
            } else {
              wheelDirection = 'bottom';
            }
            let h = container.clientHeight + (wheelDirection === 'top' ? -10 : 10);
            if (h < 200) {
              h = 200;
            }
            container.style.height = h + 'px';
            return false;
          };
          bindEvent(container, 'mousewheel', container.onmousewheel);
          function bindEvent(context, eventName, callback) {
            if (context.addEventListener) {
              context.addEventListener(eventName, callback, false);
            } else {
              context.attachEvent('on' + eventName, function () {
                callback.call(context);
              });
            }
          }
        </script>
      </body>
    </html>
    
    
上次更新: 1/22/2025, 9:39:13 AM