拖拽拉伸图片

本文介绍了一个使用原生JS和React开发的图片编辑器,支持图片拖拽调整位置和拉伸大小的功能。通过自定义的拖拽和缩放组件,用户可以在限定区域内自由调整图片,实现直观的视觉编辑体验。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近公司开发图片组合(React),选择的图片要求可以拖拽位置、拉伸大小,就用原生js写了一个,代码就不做太多修改(es6语法,需要的自行修改,可直接运行),有需要的可以直接拿去(为了防止图片拖拽出区域,有限制区域大小,可以自行修改)。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Document</title>
  </head>
  <style>
    /* 拖拽,缩放组件相关class */
    .drage_box {
      position: absolute;
    }

    .drage_box > img {
      width: 100%;
      height: 100%;
      cursor: all-scroll;
    }

    /* 四个边以及4个顶点 */
    .drage_top,
    .drage_right,
    .drage_bottom,
    .drage_left {
      position: absolute;
      z-index: 1;
      background: #666;
    }

    /* 左右高度100%  */
    .drage_left,
    .drage_right {
      width: 2px;
      height: 100%;
      cursor: w-resize;
      background-image: linear-gradient(
        to bottom,
        #fff 0%,
        #ccc 50%,
        transparent 50%
      );
      background-size: 2px 20px;
      background-repeat: repeat-y;
    }

    /* 上下宽度100% */
    .drage_top,
    .drage_bottom {
      width: 100%;
      height: 2px;
      cursor: n-resize;
      background-image: linear-gradient(
        to right,
        #fff 0%,
        #ccc 50%,
        transparent 50%
      );
      background-size: 20px 2px;
      background-repeat: repeat-x;
    }

    .drage_top {
      top: 0;
    }

    .drage_right {
      right: 0;
    }

    .drage_bottom {
      bottom: 0;
    }

    .drage_left {
      left: 0;
    }

    /* 四个角 */
    .drage_top_right,
    .drage_top_left,
    .drage_bottom_right,
    .drage_bottom_left {
      width: 6px;
      height: 6px;
      position: absolute;
      background: #fff;
      z-index: 2;
    }

    .drage_top_right {
      right: -2px;
      top: -2px;
      cursor: nesw-resize;
    }

    .drage_top_left {
      left: -2px;
      top: -2px;
      cursor: nwse-resize;
    }

    .drage_bottom_right {
      right: -2px;
      bottom: -2px;
      cursor: nwse-resize;
    }

    .drage_bottom_left {
      left: -2px;
      bottom: -2px;
      cursor: nesw-resize;
    }

    /* 删除图标 */
    .drage_box_delete {
      position: absolute;
      top: -16px;
      right: -16px;
      border-radius: 50%;
      width: 16px;
      height: 16px;
      line-height: 16px;
      vertical-align: middle;
      text-align: center;
      color: #fff;
      cursor: pointer;
      background: #ff606c;
      z-index: 1;
    }
  </style>
  <body>
    <div class="drage_box" id="xxDrageBox">
      <span class="drage_top"></span>
      <span class="drage_right"></span>
      <span class="drage_bottom"></span>
      <span class="drage_left"></span>
      <span class="drage_top_right"></span>
      <span class="drage_top_left"></span>
      <span class="drage_bottom_right"></span>
      <span class="drage_bottom_left"></span>
      <img id="xxDrageImage" draggable="false" src="https://cn.bing.com/th?id=OHR.BardenasDesert_ZH-CN1357611840_1920x1080.jpg&rf=LaDigue_1920x1080.jpg&pid=hp" />
    </div>
  </body>
  <script>
    window.onload = () => {
      const xx_box = document.getElementById("xxDrageBox");
      const xx_img = document.getElementById("xxDrageImage");

      // 给4个角和4个边绑定拖拉方法(只改变大小)
      const xx_drag_border = xx_box.getElementsByTagName("span");

      new Array(xx_drag_border.length)
        .fill(1)
        .forEach((item, index) =>
          this.drag(xx_box, xx_drag_border[index], index)
        );

      // 给图片绑定拖拽方法(只改变位置)
      xx_img.onmousedown = event => {
        if (this._isUnMount) {
          return;
        }
        /*再次点击时使得图标任然在那个位置,鼠标可以点击到图标上*/
        const ol = event.clientX - xx_box.offsetLeft;
        const ot = event.clientY - xx_box.offsetTop;
        /*鼠标点击*/
        document.onmousemove = event => {
          xx_box.style.left = event.clientX - ol + "px"; /*赋值*/
          xx_box.style.top = event.clientY - ot + "px";
        };
        /*鼠标松开*/
        document.onmouseup = event => {
          document.onmousemove = () => this.limitDragAxis(xx_box);
          document.onmouseup = null;
        };
      };
    };

    function drag(box, obj, index) {
      obj.onmousedown = ev => {
        if (this._isUnMount) {
          return;
        }
        const oEv = ev || event;
        // 获取初始宽高
        const oldWidth = box.offsetWidth;
        const oldHeight = box.offsetHeight;
        // 获取初始位置(top、left)
        const oldLeft = box.offsetLeft;
        const oldTop = box.offsetTop;
        // 获取鼠标的坐标
        const oldX = oEv.clientX;
        const oldY = oEv.clientY;

        document.onmousemove = ev => {
          const oEv = ev || event;
          // 顺序:上右下左 上右、上左、下右、下左
          switch (index) {
            case 0:
              box.style.height = oldHeight - (oEv.clientY - oldY) + "px";
              box.style.top = oldTop + (oEv.clientY - oldY) + "px";
              break;
            case 1:
              box.style.height = oldHeight + "px";
              box.style.width = oldWidth + (oEv.clientX - oldX) + "px";
              box.style.right = oldLeft - (oEv.clientX - oldX) + "px";
              break;
            case 2:
              box.style.height = oldHeight + (oEv.clientY - oldY) + "px";
              box.style.bottom = oldTop - (oEv.clientY + oldY) + "px";
              break;
            case 3:
              box.style.height = oldHeight + "px";
              box.style.width = oldWidth - (oEv.clientX - oldX) + "px";
              box.style.left = oldLeft + (oEv.clientX - oldX) + "px";
              break;
            case 4:
              box.style.width = oldWidth + (oEv.clientX - oldX) + "px";
              box.style.height = oldHeight - (oEv.clientY - oldY) + "px";
              box.style.right = oldLeft - (oEv.clientX - oldX) + "px";
              box.style.top = oldTop + (oEv.clientY - oldY) + "px";
              break;
            case 5:
              box.style.width = oldWidth - (oEv.clientX - oldX) + "px";
              box.style.height = oldHeight - (oEv.clientY - oldY) + "px";
              box.style.left = oldLeft + (oEv.clientX - oldX) + "px";
              box.style.top = oldTop + (oEv.clientY - oldY) + "px";
              break;
            case 6:
              box.style.width = oldWidth + (oEv.clientX - oldX) + "px";
              box.style.height = oldHeight + (oEv.clientY - oldY) + "px";
              box.style.right = oldLeft - (oEv.clientX - oldX) + "px";
              box.style.bottom = oldTop + (oEv.clientY + oldY) + "px";
              break;
            case 7:
              box.style.width = oldWidth - (oEv.clientX - oldX) + "px";
              box.style.height = oldHeight + (oEv.clientY - oldY) + "px";
              box.style.left = oldLeft + (oEv.clientX - oldX) + "px";
              box.style.bottom = oldTop + (oEv.clientY + oldY) + "px";
              break;
            default:
              break;
          }
          this.drawImage();
        };

        document.onmouseup = () => {
          if (this._isUnMount) {
            return;
          }
          document.onmousemove = () => this.limitDragAxis(box);
        };
        return false;
      };
    }

    // 计算拖拽的最大范围
    function limitDragAxis(box) {
      // 计算最大x和y
      const  width = 1920;
      const height = 1080;

      // 移除px
      const rmPX = str => (str ? str.replace(/px$/, "") : 0);
      const [top, left, _width, _height] = [
        rmPX(box.style.top),
        rmPX(box.style.left),
        rmPX(box.style.width),
        rmPX(box.style.height)
      ];

      if (top > height) {
        box.style.top = height - 20 + "px";
      } else if (left + _width < 0) {
        box.style.left = 20 - _width + "px";
      } else if (left > width) {
        box.style.left = width - 20 + "px";
      } else if (top + _height < 0) {
        box.style.top = 20 - _height + "px";
      }
      return;
    }
  </script>
</html>


预览图如下:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值