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

2025-09-20 23:59:55

目标

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

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

前言

拖拽的事件:

针对被拖拽的元素:onDragStart:开始拖拽元素onDrag:元素拖拽中onDragEnd:结束拖拽元素针对目标元素:onDragEnter:拖拽的元素进入到目标元素时触发onDragLeave:拖拽的元素移出目标元素时触发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,设置样式如下:

style={{

position: "absolute",

width: "332px",

height: "235px",

top: `${top}px`,

left: `${left}px`,

zIndex: 999,

}}

onDragStart={(e) => handleDragStart(e)}

onDragEnd={(e) => handleDragEnd(e)}

>

src={imageSrc}

style={{

width: "332px",

height: "235px",

}}

onClick={() => {}}

/>

当鼠标开始拖动时,在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达到去掉拖拽过程中缩略图的效果。

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}

>

className="ant-image-preview-img"

src={currentSrc}

style={{

WebkitUserDrag: "none",

}}

/>

总结

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

position设置绝对定位,通过修改left和top可以实现将图片从位置A拖动到位置B,也可以实现图片跟着鼠标移动,释放鼠标后图片回到初始位置;position设置绝对定位,加上transform,通过修改x和y的偏移量实现图片跟着鼠标移动,释放鼠标后图片回到初始位置,也可以实现将图片从位置A拖动到位置B。 读者可以根据实际情况甄选使用,如有其他建议,欢迎讨论!