基于 outline 实现头像剪裁以及预览

outline 是真正意义上的不占据任何空间的属性。

outline 不会影响任何元素的任何布局,并且 outline 轮廓可穿透。

核心布局代码:

.crop {
    overflow: hidden;
}

.crop > .crop-area {
    width: 80px;
    height: 80px;
    outline: 256px solid rgba(0, 0, 0, .5);
    cursor: move;
}

效果预览

头像剪裁效果预览

<!DOCTYPE html>
<html lang="zh-CN">
  <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>outline 与镂空效果</title>
    <style>
      .crop-box,
      .preview-box {
        display: inline-block;
        vertical-align: top;
      }

      .crop,
      .preview {
        position: relative;
        overflow: hidden;
      }

      .crop-area,
      .preview {
        width: 80px;
        height: 80px;
      }

      .crop-area {
        position: absolute;
        left: 80px;
        top: 56px;
        outline: 256px solid rgba(0, 0, 0, 0.5);
        cursor: move;
      }

      .crop img,
      .preview img {
        display: block;
        width: 256px;
        height: 192px;
      }

      .preview img {
        position: absolute;
        /* 初始位置与 crop-area 位置对应 */
        left: -88px;
        top: -56px;
      }
    </style>
  </head>
  <body>
    <div class="crop-box">
      <h4>剪裁(仅演示移动)</h4>
      <div class="crop">
        <div id="cropArea" class="crop-area"></div>
        <img src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTS6ESEyK8IGsYRNb31pBZQFhi21oVIn8k5pQ&usqp=CAU" alt="剪裁预备图片" />
      </div>
    </div>
    <div class="preview-box">
      <h4>预览</h4>
      <div class="preview">
        <img
          id="previewImg"
          src="https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTS6ESEyK8IGsYRNb31pBZQFhi21oVIn8k5pQ&usqp=CAU"
          alt="剪裁图片"
        />
      </div>
    </div>

    <script>
      const elCropArea = document.getElementById("cropArea"),
        elPreviewImg = document.getElementById("previewImg");

      let data = {};

      // 记录剪裁框初始位置
      elCropArea.addEventListener("mousedown", function (event) {
        data = {
          moving: true,
          left: elCropArea.offsetLeft,
          top: elCropArea.offsetTop,
          x: event.pageX,
          y: event.pageY,
        };
      });

      // 监听具体鼠标移动事件
      document.addEventListener("mousemove", function (event) {
        if (data.moving) {
          event.preventDefault();
          // 移动距离
          const moveX = event.pageX - data.x,
            moveY = event.pageY - data.y;

          // 目标坐标
          let left = data.left + moveX,
            top = data.top + moveY;

          // 边界判断
          if (left < 0) {
            left = 0;
          } else if (left + 80 > 256) {
            left = 176;
          }

          if (top < 0) {
            top = 0;
          } else if (top + 80 > 192) {
            top = 112;
          }

          // 剪裁框和预览框重定位
          /* elCropArea.style.left = left + "px";
          elCropArea.style.top = top + "px"; */

          elCropArea.style.cssText = `
            left: ${left}px;
            top: ${top}px;
          `;

          //   elPreviewImg.style.left = -left + "px";
          //   elPreviewImg.style.top = -top + "px";

          elPreviewImg.style.cssText = `
            left: ${-left}px;
            top: ${-top}px;
          `;
        }
      });

      document.addEventListener("mouseup", function () {
        data.moving = false;
      });
    </script>
  </body>
</html>

基于 outline 实现头像剪裁以及预览 - JS Bin

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值