覆盖在图片上方的镂空遮罩,预览镂空区域所选图片

代码

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <title></title>
    <style>
      .bg {
        position: relative;
        width: 400px;
        height: 400px;
        background: url(./img/1.jpg); /* 自己选一个图片 */
        box-sizing: border-box;
      }
      .mask {
        position: absolute;
        width: 100px;
        height: 100px;
        border: solid rgba(255, 255, 255, 0.3);
      }
      .inner {
        position: relative;
        width: 100%;
        height: 100%;
        border: 1px dashed #8c8371;
        cursor: pointer;
        box-sizing: border-box;
      }
      
      #preview-img {
        width: 100px;
        height: 100px;
      }
    </style>
  </head>
  <body>
    <div class="bg">
      <!-- 通过设置border颜色及宽度实现中间镂空效果 -->
      <!-- 默认设置内部中心为镂空区域,长宽为100px,故默认border-width为150px -->
      <!-- 必须通过style设置,方便后续js覆盖 -->
      <div class="mask" style="border-width: 150px;">
      	<!-- 设置内部容器,宽高自动,需要根据此容器大小位置获取区域截图 -->
        <div class="inner"></div>
      </div>
    </div>
    
    <img id="preview-img" src="" alt="" />
  
    <script>
      const dom = document.querySelector('.mask')
      const innerDom = document.querySelector('.inner')
      
      // 通过canvas根据inner的大小位置制作截图
      function takeScreenshot(element) {
      	// 通过promise方便返回最终结果
        return new Promise((resolve, reject) => {
          const canvas = document.createElement('canvas')
          const ctx = canvas.getContext('2d')
          // 读取图片文件并绘制进canvas
          const image = new Image()
          // 设置图片路径,需与待截取图片为同一个
          image.src = './img/1.jpg'
          // 设置canvas大小与div相同
          canvas.width = element.offsetWidth
          canvas.height = element.offsetHeight
          // 将div区域的屏幕内容绘制到canvas上
          var rect = element.getBoundingClientRect()

          image.onload = () => { // 使用promise返回的原因
            ctx.drawImage(
              image,
              rect.left,
              rect.top,
              canvas.width,
              canvas.height,
              0,
              0,
              canvas.width,
              canvas.height
            )
            
            // 将canvas转换为Base64图片
            var imgData = canvas.toDataURL('image/png')
            resolve(imgData)
          }
        })
      }

      function mousedownFunc(e) {
        // mask的宽高
        const ow = 400
        const oh =  400
        // inner的宽高
        const iw = 100
        const ih = 100
        // 判断鼠标按住时是否在inner内
        if (e.target.className === 'inner') {
          // 获取此时鼠标位置
          let oX = e.screenX
          let oY = e.screenY
		  // 根据鼠标移动路径及距离处理inner的移动效果
          const mousemoveFunc = (ce) => {
            let mX = ce.screenX
            let mY = ce.screenY
            const dX = oX - mX
            const dY = oY - mY
            // 每次移动同步上次鼠标位置,方便差值计算
            oX = mX
            oY = mY
            const {
			  // 获取mask的border左上宽度,右下宽度根据左上宽度进行动态计算
			  // 计算方式为mask宽度减去移动距离再减去inner本身的宽度
              borderTopWidth: t, borderLeftWidth: l
            } = dom.style
            // 因为取到的值是带px的,强制转化number类型
            const [nT, nL] = [Number(parseInt(t)), Number(parseInt(l))]

            let bl, bt
            bl = nL - dX
            bt = nT - dY
            // 边缘判断,防止超出底部范围
            bl = bl < 0 ? 0 : bl > ow - iw ? ow - iw : bl
            bt = bt < 0 ? 0 : bt > oh - ih ? oh - ih : bt
			// 计算右下border宽度
            br = ow - iw - bl
            bb = oh - ih - bt
			// 赋值
            dom.setAttribute('style', `
              border-top-width: ${bt}px;
              border-left-width: ${bl}px;
              border-right-width: ${br}px;
              border-bottom-width: ${bb}px;
            `)
          }
          // 鼠标抬起后触发截图事件,同时回收内存
          const clearListener = async () => {
            let src = await takeScreenshot(innerDom)
            document.getElementById('preview-img').setAttribute('src', src)
            document.removeEventListener('mousemove', mousemoveFunc)
            document.removeEventListener('mouseup', clearListener)
          }
          document.addEventListener('mousemove', mousemoveFunc)
          document.addEventListener('mouseup', clearListener)
        }
      }
      
      document.addEventListener('mousedown', mousedownFunc)
    </script>
  </body>
</html>

演示

在这里插入图片描述
懒得搞img标签的默认图片了,不是出错,就是src为空
在这里插入图片描述
同步显示为透明框选区域

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值