前几天,做了一个移动端的拖拽拼图小游戏,需求是在轮播中展示预览图,然后从预览图中拖到相应的位置,全部拖到对应的位置就完成了,就是下面这页面,感觉还挺有意思的,记一下思路,欢迎指出更好的方法。
思路
首先呢,当然是先把大概方向确认下来啦。首先,12块拼图,那里面肯定是需要有12个坑位放置图片的,再看看预览图,嗯,也是12个,那就好办了,直接在预览图中放置要展示的图片,这样拖到指定位置的时候就直接获取当前拖动的图片的地址填充到指定位置就可以了,接下来就容易啦,先把html``css写好了。
//展示拼图的部分
<div class="puzzles-show-box" id="puzzles_show_box">
<div class="item item-1" id="puzzles_b_1"></div>
<div class="item item-1" id="puzzles_b_2"></div>
<div class="item item-1" id="puzzles_b_3"></div>
<div class="item item-2" id="puzzles_b_4"></div>
<div class="item item-2" id="puzzles_b_5"></div>
<div class="item item-2" id="puzzles_b_6"></div>
<div class="item item-3" id="puzzles_b_7"></div>
<div class="item item-3" id="puzzles_b_8"></div>
<div class="item item-3" id="puzzles_b_9"></div>
<div class="item item-4" id="puzzles_b_10"></div>
<div class="item item-4" id="puzzles_b_11"></div>
<div class="item item-4" id="puzzles_b_12"></div>
</div>
这里因为这记行的高度都是不一样的,所以分别用不用的class来设置高度,用不同的id来区分每一格。
//预览图部分
<div class="scroll-outside-box" id="scroll_outside_box">
<div class="scroll-wrap">
<div class="scroll-box" id="puzzles_scroll_box">
<div class="item" data-index="2"><img id="puzzles_s_2" src="image/puzzles-img-1/img-2.png"></div>
<div class="item" id="scroll_item_width" data-index="1"><img id="puzzles_s_1" src="image/puzzles-img-1/img-1.png"></div>
<div class="item" data-index="10"><img id="puzzles_s_10" src="image/puzzles-img-1/img-10.png"></div>
<div class="item" data-index="6"><img id="puzzles_s_6" src="image/puzzles-img-1/img-6.png"></div>
<div class="item" data-index="5"><img id="puzzles_s_5" src="image/puzzles-img-1/img-5.png"></div>
<div class="item" data-index="4"><img id="puzzles_s_4" src="image/puzzles-img-1/img-4.png"></div>
<div class="item" data-index="9"><img id="puzzles_s_9" src="image/puzzles-img-1/img-9.png"></div>
<div class="item" data-index="7"><img id="puzzles_s_7" src="image/puzzles-img-1/img-7.png"></div>
<div class="item" data-index="8"><img id="puzzles_s_8" src="image/puzzles-img-1/img-8.png"></div>
<div class="item" data-index="11"><img id="puzzles_s_11" src="image/puzzles-img-1/img-11.png"></div>
<div class="item" data-index="3"><img id="puzzles_s_3" src="image/puzzles-img-1/img-3.png"></div>
<div class="item" data-index="12"><img id="puzzles_s_12" src="image/puzzles-img-1/img-12.png"></div>
</div>
</div>
<div class="scroll-arrow scroll-arrow-1" id="scroll_arrow_left"><img src="image/arrow-left.jpg"></div>
<div class="scroll-arrow scroll-arrow-2" id="scroll_arrow_right"><img src="image/arrow-right.jpg"></div>
</div>
这里没有做js随机的,手动随机(。ì _ í。) 害,先写一下思路吧,等后面再优化吧。
好了,到这里就迈出了一大步了,css那些就不贴啦,大家自己随便想想啦,不想也可以,随便你。接下来,轮到js登场。
let _show_width = $('#puzzles_b_1').outerWidth(true);//展示格的宽度
let _scroll_width = $('#scroll_item_width').outerWidth(true);//预览格的宽度
let _outside_box_width = $('#scroll_outside_box').outerWidth(true);//预览框外层宽度
let _scroll_box_width = $('#puzzles_scroll_box').outerWidth(true);//预览框内层宽度
let _show_box_top = $('#puzzles_show_box').offset().top//展示框距离页面顶部的距离
let _scroll_box_top = $('#scroll_outside_box').offset().top//预览框距离页面顶部的距离
$('#puzzles_scroll_box .item').each(function(i) {
let index = $(this).data('index')//对应展示框的id数
let scroll_img = document.getElementById(`puzzles_s_${index}`)
let show_img = document.getElementById(`puzzles_b_${index}`)
let scroll_img_left = $(this)[0].offsetLeft
scroll_img.addEventListener('touchstart', function (e){
let ev = e || window.event;
let touch = ev.targetTouches[0];
oL = touch.clientX - scroll_img.offsetLeft;
oT = touch.clientY - scroll_img.offsetTop;
document.addEventListener("touchmove", defaultEvent, false);
})
scroll_img.addEventListener('touchmove', function (e) {
let ev = e || window.event;
ev.preventDefault()
let touch = ev.targetTouches[0];
let oLeft = touch.clientX - oL;
let oTop = touch.clientY - oT;
scroll_img.style.left = oLeft + 'px';
scroll_img.style.top = oTop + 'px';
})
scroll_img.addEventListener('touchend', function (e) {
let ev = e || window.event;
let _top = scroll_img.offsetTop
let _left = scroll_img.offsetLeft
let _show_left = show_img.offsetLeft
let _show_top = show_img.offsetTop
let _show_height = show_img.offsetHeight
let _diff_height = _scroll_box_top - _show_top
let src = ''
let _scroll_box_left = $('#puzzles_scroll_box').position().left
let _move_left = _left + scroll_img_left + _scroll_box_left
let img_move_left = _show_left - _show_width * .5
let img_move_right = _show_left + _show_width + _show_width * .5
if(_move_left >= img_move_left && _move_left <= img_move_right && Math.abs(_top) <= _diff_height + _show_width * .5 && Math.abs(_top) >= _diff_height - _show_height - _show_width * .5) {
src = scroll_img.getAttribute('src')
$(`#puzzles_b_${index}`).append(`<img src="${src}">`)
scroll_img.style.opacity = 0
if($('#puzzles_show_box img').length == 12) {
$('#puzzles_success_box').removeClass('hide').addClass('show')
$('#puzzles_note_show').show()
$('#puzzles_scroll_hide').hide()
setTimeout(function() {
$('#puzzles_success_box, #puzzles_show_box').removeClass('show').addClass('hide')
$('#puzzles_success_img').removeClass('hide').addClass('show')
}, 1000)
}
} else {
scroll_img.style.left = 0;
scroll_img.style.top = 0;
}
})
})
function defaultEvent(e) {
e.preventDefault();
}
当touchstart的时候,计算当前的位置的top和left
touchmove的时候,用当前的移动的top和left减去初始的值,得到移动的差值就是图片相对移动的top和left
touchend的时候,主要是要计算是不是在指定的格子内,_move_left字段就是用来计算图片拖到到什么位置,这里用touchmove的时候移动预览图的移动left+预览图的初始位置left+滚动框当前的left就是相对的展示框的left了,这时候要计算指定格子的最左和最右填入(由自己决定,我是用了展示格子宽度的一半来计算了),也就是最左就是格子left - 格子宽度0.5,最右是格子left+格子宽度+格子宽度0.5,所以只要最左<= _move_left <= 最右,那就是在格子的左右范围了。接下来再计算格子上下的填入位置,一样的道理只要最下<= Math.abs(_top) <= 最上,那就是在格子的上下范围内了,首先计算最上的值,这时候只要把预览层的offsetTop - 格子的offsetTop(也就是_diff_height)就得到预览图到展示格子之间的距离了,接下来就是计算最上最下最大值了,最上应该是_diff_height + 格子高度0.5,最下是_diff_height -格子高度 - 格子高度0.5,当时拖动的坐标处于这范围内就是能填充的范围了。走到这一步已经完成了大半了,剩下一些就是优化优化了,拿到当前拖动的image地址,填充到对应的id内,把拖动的image置于透明,这样就不会遮挡到展示格子了,当格子内图片长度==12的时候,说明填充完成了,就酱紫吧