canvas圆形裁切


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0" />
    <title>圆形裁剪</title>
    <style>
      * {
        margin: 0;
        padding: 0;
        box-sizing: border-box;
      }
      body {
        padding: 20px;
      }
      img {
        width: 500px;
      }
      img,
      canvas {
        outline: 1px solid #999;
      }
    </style>
  </head>
  <body>
    <img src="./test.jpg" class="origin" alt="" />
    <button type="button" class="btn-crop">圆形裁剪</button>
    <img class="clip" alt="" />

    <script>
      const origin = document.querySelector('.origin');
      const btnCrop = document.querySelector('.btn-crop');
      const clip = document.querySelector('.clip');

      const canvas = document.createElement('canvas');
      const context = canvas.getContext('2d');
      const width = origin.offsetWidth;
      const height = origin.offsetHeight;
      canvas.width = width * devicePixelRatio;
      canvas.height = width * devicePixelRatio;
      canvas.style.width = `${100}px`;
      canvas.style.height = `${100}px`;
      clip.style.width = `${100}px`;
      clip.style.height = `${100}px`;

      const scalex = origin.naturalWidth / width;
      const scaley = origin.naturalHeight / height;

      context.drawImage(origin, 0, 0, width, height);

      context.beginPath();
      context.arc(canvas.width / 2, canvas.height / 2, canvas.width / 2, 0, 2 * Math.PI);
      context.clearRect(0, 0, width, height);
      context.clip();

      let mask = null;
      origin.addEventListener('mouseenter', () => {
        mask = document.createElement('div');
        const { left, top } = origin.getBoundingClientRect();
        mask.style.cssText = `
          position: fixed;
          top: 0;
          left: 0;
          width: ${canvas.offsetWidth}px;
          height: ${canvas.offsetHeight}px;
          border-radius: 50%;
          background-color: rgba(0, 0, 0, 0.5);
          translate:${left}px ${top}px;
          will-change: translate;
          z-index: 999;
          pointer-events: none;
        `;
        document.body.append(mask);
      });
      origin.addEventListener('mouseleave', () => {
        if (mask) {
          document.body.removeChild(mask);
        }
      })

      window.onmousemove = (e) => {

        let x = e.clientX - origin.offsetLeft - canvas.offsetWidth / 2;
        let y = e.clientY - origin.offsetTop - canvas.offsetHeight / 2;

        x = Math.max(x, 0);
        y = Math.max(y, 0);
        x = Math.min(x, origin.offsetWidth - origin.offsetLeft - canvas.offsetWidth / 2);
        y = Math.min(y, origin.offsetHeight - origin.offsetTop - canvas.offsetHeight / 2);

        if (mask) {

          mask.style.translate = `${e.clientX - canvas.offsetWidth / 2}px ${
            e.clientY - canvas.offsetHeight / 2
          }px`;
        }

        context.clearRect(0, 0, canvas.width, canvas.height);
        context.drawImage(
          origin,
          x * scalex,
          y * scaley,
          canvas.offsetWidth * scalex,
          canvas.offsetHeight * scaley,
          0,
          0,
          canvas.offsetWidth * scalex * devicePixelRatio,
          canvas.offsetHeight * scaley * devicePixelRatio
        );
      };

      origin.addEventListener('click', () => {
        // clip.src = canvas.toDataURL();
        canvas.toBlob(
          (blob) => {
            const url = URL.createObjectURL(blob);
            clip.src = url;
            // open(url);
            // URL.revokeObjectURL(url);
          },
          'image/jpeg',
          1
        );
      });

      document.body.append(canvas);
    </script>
  </body>
</html>
posted @ 2024-04-28 16:21  _clai  阅读(28)  评论(0编辑  收藏  举报