这里分为主文件和图片组件两个部分
话不多说,直接上代码
// index.vue
<template>
<div class="content-pic-wrap">
<ContentPic class="content-pic"
v-for="(item, index) in picList"
:key="item"
:index="index"
:picSrc="item"
@setCurDragImg="setCurDragImg"
@clearCurDragImg="clearCurDragImg"
@beHit="beHit"
></ContentPic>
</div>
</template>
<script>
import ContentPic from './ContentPic.vue'
export default {
data() {
return {
// 图片列表
picList: [
'http://xxxx1.jpg',
'http://xxxx2.jpg',
'http://xxxx3.jpg'
],
curImgIndex: null // 当前被拖动图片的index
}
},
methods: {
setCurDragImg(index){
this.curImgIndex = index
},
clearCurDragImg(){
this.curImgIndex = null
},
// 图片被撞击
beHit(index){ // 被撞击图片的index
if(index === this.curImgIndex) return
let newList = [...this.form.picList]
let curImg = this.form.picList[this.curImgIndex] // 当前拖动图片
let hitImg = this.form.picList[index] // 被撞击的图片
// 两张图片交换位置
newList.splice(this.curImgIndex, 1, hitImg)
newList.splice(index, 1, curImg)
// 修改当前拖动图片的index,此时已经变成被撞击图片的位置了
this.curImgIndex = index
this.picList = newList
}
},
components: {
ContentPic
}
}
</script>
ContentPic.vue
<template>
<div class="outer-pic"
@dragstart="dragStartHandler"
@dragover.prevent="dragOverHandler"
@dragenter="dragEnterHandler"
@dragend="dragEndHandler">
<img class="content-pic" :src="picSrc" alt="">
</div>
</template>
<script>
export default {
props:{
index:{
type: Number,
required: true
},
picSrc:{
type: String,
required: true
}
},
methods:{
deleteImg(){
this.$emit('deleteImg', this.index)
},
dragStartHandler(){
// 设置当前正在被拖动的图片
this.$emit('setCurDragImg', this.index)
},
dragEndHandler(e){
this.$emit('clearCurDragImg')
},
dragOverHandler(e){
// 在dragEnter中针对放置目标来设置
e.dataTransfer.dropEffect = 'move'
},
dragEnterHandler(e){
e.dataTransfer.effectAllowed = "move"
this.$emit('beHit', this.index)
},
}
}
</script>
刚开始准备使用鼠标事件来进行碰撞检测的,这样会比较麻烦,因为伴随着x、y坐标以及元素大小的各种计算。
之后在找资料的时候,惊喜的发现HTML5新增了拖拽事件,也就是上述代码中使用的。
下面简述一下鼠标事件和拖拽事件
鼠标事件
- click:单击事件
- dblclick:双击事件
- mousedown:按下鼠标键时触发
- mouseup:释放按下的鼠标键时触发
- mousemove:鼠标移动事件
- mouseover:移入事件
- mouseout:移出事件
- mouseenter:移入事件
- mouseleave:移出事件
- contextmenu:右键事件
mouseover事件和mouseenter事件,都是鼠标进入一个节点时触发。两者的区别是:mouseenter事件只触发一次,而只要鼠标在节点内部移动,mouseover事件会在子节点上触发多次。
<style>
div{
height: 100px;
border: 1px solid #000;
}
p{
border: 1px solid red;
}
</style>
<body>
<div id="page">
<p id="word">its test</p>
</div>
<script>
let div = document.getElementById('page')
let p = document.getElementById('word')
div.addEventListener('mouseover', function(e){
console.log('div mouseover')
}, false)
div.addEventListener('mouseenter', function(e){
console.log('div mouseenter')
}, false)
p.addEventListener('mouseover', function(e){
console.log('p mouseover')
}, false)
p.addEventListener('mouseenter', function(e){
console.log('p mouseenter')
}, false)
</script>
</body>
上述页面将鼠标从body移入div,会先后打印: div mouseover、div mouseenter
然后将鼠标从div移入p,会先后打印:p mouseover、div mouseover、p mouseenter
发现会多打印出一个 div mouseover,也就是说mouseover事件也会在自己的子节点中触发
这是因为事件冒泡导致的,如果不想让mouseover在子节点中触发,那么只需要在 p 的监听函数中阻止冒泡就行了。
p.addEventListener('mouseover', function(e){
console.log('p mouseover')
e.stopPropagation()
}, false)
鼠标事件属性
- MouseEvent.altKey
- MouseEvent.ctrlKey
- MouseEvent.metaKey
- MouseEvent.shiftKey
分别代表鼠标事件发生时,是否按下了对应的键盘按键,返回值是 true or false
document.body.addEventListener('click', function(e){
let e = e || window.event
console.log("altKey:"+e.altKey); //是否按下alt键
console.log("ctrlKey:"+e.ctrlKey); //是否按下Ctrl键
console.log("metaKey:"+e.metaKey); //是否按下meta键
console.log("shiftKey:"+e.shiftKey); //是否按下shift键
}, false)
MouseEvent.button属性返回一个数值,表示事件发生时按下了鼠标的哪个键
- 0代表左键
- 1代表中键
- 2代表右键
document.body.addEventListener('mousedown', function(e){
e=e||window.event
console.log(e.button)
}, false)
鼠标滚轮事件
滚轮事件在火狐浏览器中是DOMMouseScroll,而在其他浏览器中是onmousewheel。
火狐:e.detail 、向上滚动返回值为大于0、向下滚动返回值为小于0
非火狐:e.wheelDelta、向上滚动返回值为小于0、向下滚动返回值为大于0
function wheelEvent(e) {
e = e || window.event;
if (e.detail) {
//判断是否支持e.detail 支持的话说明是火狐
if (e.detail < 0) {
console.log("向上滚动");
} else {
console.log("向下滚动");
}
} else {
//不支持,说明是其他浏览器
if (e.wheelDelta < 0) {
console.log("向下滚动");
} else {
console.log("向上滚动");
}
}
}
document.body.onmousewheel = wheelEvent;
document.body.addEventListener("mousewheel", wheelEvent); //非火狐
document.body.addEventListener("DOMMous
拖拽事件
先来看看官方的解释:
拖放(Drag 和 drop)是 HTML5 标准的组成部分。
拖放是一种常见的特性,即抓取对象以后拖到另一个位置。
在 HTML5 中,拖放是标准的一部分,任何元素都能够拖放。
被拖拽的对象: ondragstart,ondrag,ondragend
拖拽释放区: ondragenter,ondragover(要触发drop事件,要在over里阻止浏览器的默认事件),ondragleave,ondrop(在释放时有浏览器的默认事件,比如释放图片,浏览器默认会在新窗口打开图片;要在drop事件里也阻止默认事件,ev.preventDefault();)
拖拽代码实例