img图片拖拽平移(position和transform):图片从位置A拖动到位置B,跟随鼠标移动,且解决拖拽过程中出现小的缩略图和黑色禁止符号的问题(通用,笔者以react为例)

目标

1,position:absolute实现一个可以拖拽的图片,从位置A拖动到位置B

2,transform实现一个可以拖拽的图片,跟着鼠标移动,释放鼠标后图片回到初始位置

前言

拖拽的事件:

  • 针对被拖拽的元素:
  1. onDragStart:开始拖拽元素
  2. onDrag:元素拖拽中
  3. onDragEnd:结束拖拽元素
  • 针对目标元素:
  1. onDragEnter:拖拽的元素进入到目标元素时触发
  2. onDragLeave:拖拽的元素移出目标元素时触发
  3. onDragOver:拖拽的元素在目标元素(容器)范围内拖拽时触发

解决拖拽过程中出现小的缩略图和黑色禁止符号的问题:-webkit-user-drag和draggable

笔者是基于react和ant design,其他框架(或没用框架)也是一样的使用。

一、实现目标:position:absolute将图片从位置A拖动到位置B

        笔者这里使用的是绝对定位(position:absolute),原理就是通过改变top和left来修改图片的位置。如果初始位置是固定需要通过bottom和right定位的,可以先转成top和left,例如:

    let h =
      window.innerHeight ||
      document.documentElement.clientHeight ||
      document.body.clientHeight;
    let w =
      window.innerWidth ||
      document.documentElement.clientWidth ||
      document.body.clientWidth;
    setLeft(w - 352);
    setTop(h - 295);

        首先获取可视窗口的宽高,用这个宽减去图片的(宽+右边距)即可得到left,高度亦如此,得出top的值,笔者这里为了满足其他需求,在img外层套了个div,设置样式如下:

<div
    style={{
        position: "absolute",
        width: "332px",
        height: "235px",
        top: `${top}px`,
        left: `${left}px`,
        zIndex: 999,
    }}
    onDragStart={(e) => handleDragStart(e)}
    onDragEnd={(e) => handleDragEnd(e)}
>
    <img 
        src={imageSrc}
        style={{
            width: "332px",
            height: "235px",
        }}
        onClick={() => {}}
    />
</div>

        当鼠标开始拖动时,在onDragStart中记录当前鼠标点击的位置,当鼠标停止拖动时,在onDragEnd中获取两次鼠标位置之差,这个差也就是两次left之差,得出最新的left值,top亦是如此:

  const handleDragStart = (e) => {
    setClickLeft(e.clientX);
    setClickTop(e.clientY);
  };
  const handleDragEnd = (e) => {
    setLeft(left - clickLeft + e.clientX);
    setTop(top - clickTop + e.clientY);
  };

        现在,已经实现将图片从A拖到B的需求,但还要些优化,例如鼠标拖动过程中,显示了黑色禁止图标(cursor),这是因为当我们把拖拽元素拖动到其他地方(目标元素),但目标元素不允许这种行为,所以在目标元素上设置如下:

onDragEnter={(e) => e.preventDefault()}
onDragLeave={(e) => e.preventDefault()}
onDragOver={(e) => e.preventDefault()}

        现在黑色的禁止图标已经没有了。

        针对拖拽过程中img会出现小的缩略图的问题,针对img设置WebkitUserDrag(对应css的-webkit-user-drag)为none,会发现这时不可拖拽了,不要慌,这是因为外层的div和img尺寸一样,img作为里层元素不可拖拽,但是只需要在div上加上draggable={true},此时会发现又可以拖拽了,且小的缩略图已经没有了,取而代之的是与img尺寸相同的图片,这是因为拖拽的是整个div,img是div内的元素,所以这个图其实是div的内容

二、实现目标:transform实现图片跟着鼠标移动,释放鼠标后图片回到初始位置

        笔者这里使用的是绝对定位和transform,通过设置偏移量改变图片的位置。这里鼠标移动的距离就是偏移量,因为需要根据鼠标移动,所以加上事件onDrag,代码如下:

  const handleDragStart = (e) => {
    setClickLeft(e.clientX);
    setClickTop(e.clientY);
    e.dataTransfer.effectAllowed = "move";
  };
  const handleDrag = (e) => {
    e.preventDefault && e.preventDefault();
    setTranslateX(e.clientX - clickLeft);
    setTranslateY(e.clientY - clickTop);
  };
  const handleDragEnd = (e) => {
    setTranslateX(0);
    setTranslateY(0);
  };

        根据上文,我们可以很自然的将拖拽元素加上onDragStart和onDragEnd事件,在目标元素上设置onDragEnter、onDragLeave和onDragOver达到拖拽过程中不显示黑色禁止图标的目的。通过draggable={true}和img设置WebkitUserDrag达到去掉拖拽过程中缩略图的效果。

      <div
        className="ant-image-preview-img-wrapper"
        style={{
          transform: `translate3d(${translateX}px, ${translateY}px, 0px)`,
        }}
        onDragStart={(e) => handleDragStart(e)}
        onDrag={(e) => handleDrag(e)}
        onDragEnd={(e) => handleDragEnd(e)}
        draggable={true}
      >
        <img
          className="ant-image-preview-img"
          src={currentSrc}
          style={{
            WebkitUserDrag: "none",
          }}
        />
      </div>

总结

        本篇介绍了两种拖拽图片的方法:

  • position设置绝对定位,通过修改left和top可以实现将图片从位置A拖动到位置B,也可以实现图片跟着鼠标移动,释放鼠标后图片回到初始位置;
  • position设置绝对定位,加上transform,通过修改x和y的偏移量实现图片跟着鼠标移动,释放鼠标后图片回到初始位置,也可以实现将图片从位置A拖动到位置B。

        读者可以根据实际情况甄选使用,如有其他建议,欢迎讨论!

要实现同时实现图片拖拽鼠标位置放大缩小,可以参考以下步骤: 1. 在 HTML 插入一张图片,设置图片的宽度和高度,并将其放置在一个容器。 2. 使用 CSS 设置容器的样式,将容器的宽度和高度设置为图片的一半,并将 overflow 属性设置为 hidden,这样当图片放大时,容器可以隐藏超出容器范围的部分。 3. 使用 JavaScript 监听鼠标按下事件,当鼠标按下时,记录下鼠标位置和容器的位置。 4. 使用 JavaScript 监听鼠标移动事件,当鼠标移动时,根据鼠标位置和容器的位置计算出容器应该移动的距离,并将容器移动到新的位置。 5. 当鼠标离开容器时,停止拖拽。 6. 使用 JavaScript 监听鼠标滚轮事件,根据滚轮的方向计算出图片应该放大或缩小的比例,并将图片缩放到新的大小。 下面是一个示例代码: HTML代码: ``` <div class="container"> <img src="image.jpg" width="400" height="300" /> </div> ``` CSS样式: ``` .container { width: 200px; height: 150px; overflow: hidden; position: relative; } .container img { transition: all 0.3s ease-out; position: absolute; left: 0; top: 0; } .container:hover img { transform: scale(2); } ``` JavaScript代码: ``` var container = document.querySelector('.container'); var img = container.querySelector('img'); var containerWidth = container.offsetWidth; var containerHeight = container.offsetHeight; var isDragging = false; var startX = 0; var startY = 0; var containerLeft = 0; var containerTop = 0; container.addEventListener('mousedown', function(e) { isDragging = true; startX = e.clientX; startY = e.clientY; containerLeft = container.offsetLeft; containerTop = container.offsetTop; }); container.addEventListener('mousemove', function(e) { if (!isDragging) return; var deltaX = e.clientX - startX; var deltaY = e.clientY - startY; container.style.left = containerLeft + deltaX + 'px'; container.style.top = containerTop + deltaY + 'px'; }); container.addEventListener('mouseup', function() { isDragging = false; }); container.addEventListener('mouseleave', function() { isDragging = false; }); container.addEventListener('wheel', function(e) { e.preventDefault(); var delta = e.deltaY < 0 ? 0.1 : -0.1; var scaleX = img.offsetWidth / containerWidth + delta; var scaleY = img.offsetHeight / containerHeight + delta; img.style.transform = 'scale(' + scaleX + ',' + scaleY + ')'; }); ``` 注意:这个示例只是一个简单的实现,实际应用可能需要处理更多的细节问题,比如边界处理、拖拽的范围限制等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值