块状元素和图片的拖拽实现

785 阅读4分钟

Image.png

前言:为什么会写这篇文章?这周的一个任务就是需要实现图片放大缩小和拖拽的功能,功能比我现在写的demo要难一些。在别人眼中三下五除二就能写完的功能,然而菜菜的我用了一天才写完!!写到这我留下了菜菜的泪水...

77a3da8bd924b8d398ee4b4cb3e5529f.jpeg

**我按照导图分别写了3个简单的demo,每个类型我只用了一种方式去解决,当然还有其他方式可以实现,你们可以自己去思考啦~

小声哔哔:如果你们赏脸点赞的话我愿意花时间把其他方式也实现出来!嘻嘻嘻( •̀ ω •́ )✧**

每个demo我特地做了gif图来辅助解释,请把贴心打在评论里!!(其实是因为我这周还被我领导说我写的文档他看不懂,说到这我的泪水又浸湿了眼眶...)

好啦,废话不多说,开始吧!

  • 实现在矩形内拖拽,拖拽不能超出矩形边界

方块拖拽.gif 拆分一下功能,要做的就是拖拽范围限制 先看下我的html的结构

Image1.png

Image2.png 子级使用了绝对定位,通过改变top、left的值来实现拖动 拖拽的部分

Image3.png 判断限制的部分

Image4.png 加上解释和完整的代码

const childDoc = document.getElementById("children")
const parentDoc = document.getElementById("parent")
// 我在标签中添加了onmousedown事件,截图在上面
// 鼠标按下执行事件
function onMouseDown(e) {
	childDoc.style.cursor="move"
	//onMouseDown方式执行时子元素的left值
	dragBeforeX = childrenLeft = childDoc.offsetLeft
	//onMouseDown方式执行时子元素的top值
	dragBeforeY = childrenTop = childDoc.offsetTop
	// onMouseDown方式执行时鼠标在横轴的位置
	mouseX = e.x
	// onMouseDown方式执行时鼠标在纵轴的位置
	mouseY = e.y
	// 给子元素添加移动和松开鼠标的监听事件
	childDoc.addEventListener("mousemove", onMouseMove)
	childDoc.addEventListener("mouseup", onMouseUp)
}

function onMouseMove(e) {
	//移动
	const dx = e.x - mouseX //e.x是移动过程中鼠标的x值,dx是鼠标移动后x轴的距离差
	childrenLeft = dragBeforeX + dx //用子元素初始时的left加上移动后x轴的距离差就是最后的left值
	const dy = e.y - mouseY //e.y是移动过程中鼠标的y值,dy是鼠标移动后y轴的距离差
	childrenTop = dragBeforeY + dy //用子元素初始时的top加上移动后y轴的距离差就是最后的top值
	// 添加判断限制
	if(childrenLeft < 0) {  // 判断已经移动超过最左边界时left为0
		childrenLeft = 0
	}
	// 判断已经移动超过最右边界时left为父元素的宽度减去子元素的宽度
	if(childrenLeft > parentDoc.offsetWidth - childDoc.offsetWidth) {
		childrenLeft = parentDoc.offsetWidth - childDoc.offsetWidth
	}
	if(childrenTop < 0) {  // 判断已经移动超过最上边界时top为0
		childrenTop = 0
	}
	// 判断已经移动超过最下边界时top为父元素的高度减去子元素的高度
	if(childrenTop > parentDoc.offsetHeight - childDoc.offsetHeight) {
		childrenTop = parentDoc.offsetHeight - childDoc.offsetHeight
	}
	childDoc.style.left= childrenLeft + 'px'
	childDoc.style.top= childrenTop + 'px'
	if(e.preventDefault) e.preventDefault()
}

function onMouseUp() {
	childDoc.removeEventListener("mousemove", onMouseMove)
	childDoc.removeEventListener("mouseup", onMouseUp)
	childDoc.style.cursor="default"
}

  • 实现在矩形内拖拽,拖拽不能超出矩形边界

图片拖拽.gif 这个的代码和实现div拖拽的差不多,有个地方需要注意一下:需要在移动的监听事件中添加if(e.preventDefault) e.preventDefault()这句话,去除拖拽图片时的默认操作,不然会导致拖到一半就拖不动了,具体效果如何你们可以复制代码然后把这句话删掉运行看看

那这个的实现代码我就不过多赘述了,在下面的放大缩小的实现方式中我会一并放出完整代码


  • 实现图片的放大缩小和拖拽 拖拽功能 - Google Chrome 2021-12-19 22-28-14.gif

先看html的结构

Image5.png

Image6.png

同样的,也对图片元素使用了绝对定位

放大缩小的部分 Image7.png 拖拽的部分

Image8.png 拖拽的限制部分

Image9.png 加上解释和完整的代码

let ratio = 1  // 初始倍率值
// 鼠标按下执行事件
function onMouseDown(e) {
	childDoc.style.cursor="move"
	//onMouseDown方式执行时子元素的left值
	dragBeforeX = childrenLeft = childDoc.offsetLeft
	//onMouseDown方式执行时子元素的top值
	dragBeforeY = childrenTop = childDoc.offsetTop
	// onMouseDown方式执行时鼠标在横轴的位置
	mouseX = e.x
	// onMouseDown方式执行时鼠标在纵轴的位置
	mouseY = e.y
	// 给子元素添加移动和松开鼠标的监听事件
	childDoc.addEventListener("mousemove", onImgMove)
	childDoc.addEventListener("mouseup", onMouseUp)
}
function onImgMove(e) {
	//移动
	const dx = e.x - mouseX
	childrenLeft = dragBeforeX + dx 
	const dy = e.y - mouseY
	childrenTop = dragBeforeY + dy
	// 添加判断限制
	if(ratio == 1) { // 当图片的比例是初始比例时,和div拖拽的限制一样
		if(childrenLeft < 0) {
			childrenLeft = 0
		}
		if(childrenLeft > parentDoc.offsetWidth - childDoc.offsetWidth) {
			childrenLeft = parentDoc.offsetWidth - childDoc.offsetWidth
		}
		if(childrenTop < 0) {
			childrenTop = 0
		}
		if(childrenTop > parentDoc.offsetHeight - childDoc.offsetHeight) {
			childrenTop = parentDoc.offsetHeight - childDoc.offsetHeight
		}
	}else { // 当图片放大后图片的宽高均已超过父元素的宽高时进行拖拽
		if(childrenLeft > 0) {  //向右拖拽,图片的最左边超过父元素的最左边时
			childrenLeft = 8 //赋值8像素是因为想留出点空隙
		}
		//向左拖拽,图片的最右边超过父元素的最右边时
		if(childrenLeft < parentDoc.offsetWidth - childDoc.offsetWidth) {
			childrenLeft = parentDoc.offsetWidth - childDoc.offsetWidth - 8
		}
		//向下拖拽,图片的最上边超过父元素的最上边时
		if(childrenTop > 0) {
			childrenTop = 8
		}
		//向上拖拽,图片的最下边超过父元素的最下边时
		if(childrenTop < parentDoc.offsetHeight - childDoc.offsetHeight) {
			childrenTop = parentDoc.offsetHeight - childDoc.offsetHeight - 8
		}
	}
	childDoc.style.left= childrenLeft + 'px'
	childDoc.style.top= childrenTop + 'px'
	if(e.preventDefault) e.preventDefault()
}

function onMouseUp() {
	// 在松开鼠标时记得移除监听哦
	childDoc.removeEventListener("mousemove", onImgMove)
	childDoc.removeEventListener("mouseup", onMouseUp)
	childDoc.style.cursor="default"
}

上面我只说了一种情况下图片的移动限制,还有比如放大后高度超过父元素,宽度没超过怎么做?宽度超过,高度又没超过怎么做等等?这些坑我有时间再接着写...其实也要结合需求去写。

是的,我遇到了这个需求!又想起我写了好久,暴风哭泣!

还有放大缩小除了去计算宽高这么麻烦,还可以使用transform属性的scale来实现,顺着这条思路写下去也是一种实现方式,这个我下次也一起写...

我真是挖坑第一人(amazing)

我的分享就到这里啦,哪里有不足的地方,欢迎大家指出,大家一起进步~😉

我npy说我写完这篇就可以找他拿100块。赶紧写完,我要去拿钱了!

b17f4f3fbfc1f5d0ec5fd7a0b5913f55.jpeg