场景是这样,移动端页面,有两个3X3的拼图A和B,共18块碎片打乱填充,任意拖动复原拼图。
我的想法是,通过touch相关事件拖动,然后交换拖动元素的src和目标元素的src。但是尝试后发现由于拖动的事件从start到end都只绑定了拖动的元素,目标元素的数据拿不到,那该怎么获取呢?或者提供一下别的思路呢?
上代码:
<template>
<div class="jigsaw" @touchmove.prevent>
<canvas
id="canvas"
v-show="false"
class="jigsaw-canvas"
width="150"
height="150"
>Browser cannot support canvas.</canvas>
<ul class="jigsaw-sudoku" id="sudoku">
<li v-for="(item, index) in 9" :key="`sudoku_${index}`">
<img :id="`_${index}`" src alt />
</li>
</ul>
<ul class="jigsaw-selector" id="selector">
<li v-for="(item, index) in 9" :key="`selector_${index}`">
<img src alt draggable />
</li>
</ul>
</div>
</template>
<script>
export default {
name: '',
props: {
},
data() {
return {
imgSrc: require('@/assets/demo.jpg'),
startX: 0,
startY: 0,
ctx: undefined,
selectorList: [],
selectorArr: [],
};
},
computed: {
},
created() {
},
mounted() {
this.onInit();
},
watch: {
},
methods: {
/* ----------------------行为触发函数------------------------ */
actionToDrag() {
const sudoku = document.getElementById('sudoku')
const selector = document.getElementById('selector')
sudoku.addEventListener('dragover', function (e) {
e.preventDefault();
}, false);
selector.addEventListener('dragover', function (e) {
e.preventDefault();
}, false);
selector.addEventListener('dragstart', function (e) {
const target = e.target;
if (target.tagName.toLowerCase() == 'img') {
e.dataTransfer.setData('id', target.id);
}
}, false);
sudoku.addEventListener('drop', function (e) {
const target = e.target;
if (target.tagName.toLowerCase() == 'img') {
const originObj = document.getElementById(e.dataTransfer.getData('id'));
const endObj = target;
if (target.id === `_${e.dataTransfer.getData('id')}`) {
[endObj.src, originObj.src] = [originObj.src, endObj.src];
[endObj.id, originObj.id] = [originObj.id, endObj.id];
originObj.parentNode.remove()
// let newImgArr = document.querySelectorAll('#sudoku img');
// let idArr = [];
// for (i = 0; i < 9; i++) {
// idArr.push(newImgArr[i].id);
// }
// if (idArr.toString() == [0, 1, 2, 3, 4, 5, 6, 7, 8].toString()) {
// alert('success')
// }
}
}
}, false);
},
/* ----------------------内部处理函数------------------------ */
onRandomImage() {
this.selectorArr = this.selectorArr.sort(function () {
return Math.random() - Math.random();
})
},
onRenderImage(image) {
let index = 0;
for (let i = 0; i < 3; i++) {
for (let j = 0; j < 3; j++) {
this.ctx.drawImage(image, 300 * j, 300 * i, 300, 300, 0, 0, 150, 150);
this.selectorArr[index].src = document.getElementById('canvas').toDataURL('image/jpeg');
this.selectorArr[index].id = index;
index++;
}
}
},
onLoadImage(imgSrc) {
const image = new Image();
const _this = this
image.src = imgSrc
image.onload = function () {
_this.onRandomImage()
_this.onRenderImage(image)
_this.actionToDrag()
}
},
onInit() {
this.ctx = document.getElementById('canvas').getContext('2d');
this.selectorList = document.querySelectorAll('#selector img');
this.selectorArr = Array.from(this.selectorList);
this.onLoadImage(this.imgSrc)
},
/* ----------------------请求调用函数------------------------ */
ajaxToDo() { }
},
components: {
},
};
</script>
<style lang="less" scoped>
.jigsaw {
&-sudoku {
width: 246px;
margin: 80px auto;
overflow: hidden;
> li {
width: 80px;
height: 80px;
float: left;
margin: 1px;
> img {
width: 80px;
height: 80px;
}
}
}
&-selector {
display: flex;
overflow-x: auto;
> li {
width: 80px;
height: 80px;
margin: 1px;
img {
width: 80px;
height: 80px;
}
}
}
}
</style>
使用HTML的Drag & Drop API。把3X3的区域设置为可拖拽区域,然后每块拼图设置为可拖拽元素,当元素drop释放后,拿到源信息和目标区域的信息,进行对比和后续的逻辑编写。