携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情
前言
大家好,我是小阵 🔥,一路奔波不停的码字业务员
如果喜欢我的文章,可以关注 ➕ 点赞,与我一同成长吧~😋
加我微信:zzz886885,邀你进群,一起学习交流,摸鱼学习两不误🌟
开开心心学技术大法~~
来了来了,他真的来了~
正文
先看效果
实现思路
-
刚看到这个的第一个想法是什么?
-
是否是:
mousedown
的时候拿到该元素本身于该元素的位置信息,然后根据鼠标移动同步控制移动该dom- 同时监听
mouseover
事件,跟任意一个其他dom的位置信息比较,如果在位置信息内且该dom可以承载下移动dom,也就是宽高要大于可移动dom,如果满足条件的话给可承载移动dom的容器dom
添加一些样式,让我们一眼可以看出该移动dom
可以被放置到该容器dom
中 - 之后监听mosedown事件,看是否鼠标位置在
容器dom
内
-
以上思路当然也可以解决,但是有更好的方案可以实现这些效果
-
这就用到了
dragstart
、dragend
、dragenter
、dragleave
、drop
等事件可以看到这一系列的事件兼容性还是可以的。
-
当然
dragestart
一系列事件还需要跟dom
的draggable='true'
属性一起使用- 顾名思义,dom上添加
draggable='true'
表示可以被拖拽,默认是auto
- 顾名思义,dom上添加
-
依据以上思路,我们需要:
-
移动dom
触发dragstart
的时候,给该dom添加一些拖拽样式-
注意,试想一下,我们拖拽前和拖拽后给被拖拽dom添加样式时有什么不一样
-
我们知道,对于一般dom来说,添加的所有样式都会按照预期生效,拖拽前的dom就是这种状态。
-
但是拖拽后的dom会在原来的位置上保留原dom,然后在拖拽的dom其实是一个副本dom。我们要做的其实就是两点
- 拖拽时隐藏掉原dom
- 拖拽的同时给副本dom一个样式
-
要实现以上效果,需要同步异步一起用,同步的给原本dom与副本dom添加一个拖拽样式,然后异步给一个隐藏原本dom的样式。
-
因为在拖拽前原dom已经同步更改成了
拖拽样式
,所以被拖拽dom也就有了拖拽样式
-
又因为异步将原dom隐藏的时候,被拖拽dom已经被拖拽了,所以原dom的隐藏样式就没办法在被拖拽dom上生效了。
-
这也就达成了我们的目的
-
-
-
之后简单了,触发
dragenter
的dom就是被拖拽元素进入到可放置元素
的时候,这时可以更改下可放置元素的样式
- 这里有
可放置元素
的概念,这个其实就是比大小,可放置元素一定要比拖拽元素大,也就是之前提到过的内容
- 这里有
-
drageleave
触发时同理 -
drop
触发时将被拖拽dom塞入到该可放置元素
中即可- 那还用删除掉原dom吗?不用的,因为这就是
dragEvent
的又一个方便之处呀
- 那还用删除掉原dom吗?不用的,因为这就是
具体实现
基础html
<div class="empty">
<div class="fill" draggable="true"></div>
</div>
<div class="empty"></div>
<div class="empty"></div>
<div class="empty"></div>
<div class="empty"></div>
设置几个dom容器,设置一个填充img的元素用作拖拽元素
实现基础样式
.empty {
height: 150px;
width: 150px;
margin: 10px;
border: solid 3px black;
background: white;
}
.empty-small {
height: 50px;
width: 50px;
margin: 10px;
border: solid 3px black;
background: white;
}
.fill {
background-image: url('https://images.unsplash.com/photo-1658786335140-e42b16e8f462?crop=entropy&cs=tinysrgb&fit=crop&fm=jpg&h=150&ixid=MnwxfDB8MXxyYW5kb218MHx8fHx8fHx8MTY2MDEzNjk3NQ&ixlib=rb-1.2.1&q=80&w=150');
height: 145px;
width: 145px;
cursor: pointer;
}
.hold {
border: solid 5px #ccc;
}
.hovered {
background-color: #333;
border-color: white;
border-style: dashed;
}
这个基本都是静态css
添加拖拽事件
const fill = document.querySelector('.fill')
const empties = document.querySelectorAll('.empty')
fill.addEventListener('dragstart', dragStart)
fill.addEventListener('dragend', dragEnd)
for (const empty of empties) {
empty.addEventListener('dragover', dragOver)
empty.addEventListener('dragenter', dragEnter)
empty.addEventListener('dragleave', dragLeave)
empty.addEventListener('drop', dragDrop)
}
function dragStart() {
this.className += ' hold'
setTimeout(() => this.className = 'invisible', 0)
}
function dragEnd() {
this.className = 'fill'
}
function dragOver(e) {
console.log('dragOver')
e.preventDefault()
}
function dragEnter(e) {
console.log('dragEnter')
e.preventDefault()
this.className += ' hovered'
}
function dragLeave() {
console.log('dragEnter')
this.className = 'empty'
}
function dragDrop() {
this.className = 'empty'
this.append(fill)
}
关键是dragEvent
的使用
注意,dragOver
中一定要设置e.preventDefault()
,否则drag
事件触发后会触发dragOver
事件导致append
失败
完整代码
总结
- 关键
dragEvent
事件的使用 - 还有一点就是对拖拽元素施加拖拽样式时的细节处理
结语
如果文章真的有帮到你,希望可以多多点赞、收藏、关注支持一波呀!!小阵会很开心哒~
热爱开源,支持开源,拥抱开源!
文章如有错误或不严谨之处,还望指出,感谢感谢!!!
往期好文推荐「我不推荐下,大家可能就错过了史上最牛逼vscode插件集合
啦!!!(嘎嘎嘎~)😄」