前言:为什么会写这篇文章?这周的一个任务就是需要实现图片放大缩小和拖拽的功能,功能比我现在写的demo要难一些。在别人眼中三下五除二就能写完的功能,然而菜菜的我用了一天才写完!!写到这我留下了菜菜的泪水...
**我按照导图分别写了3个简单的demo,每个类型我只用了一种方式去解决,当然还有其他方式可以实现,你们可以自己去思考啦~
小声哔哔:如果你们赏脸点赞的话我愿意花时间把其他方式也实现出来!嘻嘻嘻( •̀ ω •́ )✧**
每个demo我特地做了gif图来辅助解释,请把贴心打在评论里!!(其实是因为我这周还被我领导说我写的文档他看不懂,说到这我的泪水又浸湿了眼眶...)
好啦,废话不多说,开始吧!
- 实现在矩形内拖拽,拖拽不能超出矩形边界
拆分一下功能,要做的就是拖拽和范围限制
先看下我的html的结构
子级使用了绝对定位,通过改变top、left的值来实现拖动
拖拽的部分
判断限制的部分
加上解释和完整的代码
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"
}
- 实现在矩形内拖拽,拖拽不能超出矩形边界
这个的代码和实现div拖拽的差不多,有个地方需要注意一下:需要在移动的监听事件中添加
if(e.preventDefault) e.preventDefault()这句话,去除拖拽图片时的默认操作,不然会导致拖到一半就拖不动了,具体效果如何你们可以复制代码然后把这句话删掉运行看看
那这个的实现代码我就不过多赘述了,在下面的放大缩小的实现方式中我会一并放出完整代码
- 实现图片的放大缩小和拖拽
先看html的结构
同样的,也对图片元素使用了绝对定位
放大缩小的部分
拖拽的部分
拖拽的限制部分
加上解释和完整的代码
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块。赶紧写完,我要去拿钱了!