html-拼图特效
作者:fengfanv
Tips:
- 欢迎
客官您的光临,文章如果对您有帮助,欢迎点赞或评论,让更多的人看到,万分感谢。
Demo 注意事项
- Demo 是用Vue编写的,使用时需要先引用Vue。
<script src="https://unpkg.com/vue@next"></script>
- Demo 样式是基于 移动端750设计图尺寸 编写的,使用时需要设置
<html style="font-size: calc(100vw / 750 * 100);"></html>
- 引用 Demo 时,需要重新设置一下,图片的大小,否则拼图上的图片会被扭曲显示。
Demo 源码:
- demo.html
<div id="app">
<!--拼图区域-->
<div class="card_frame">
</div>
<!--存放拼图碎片的区域-->
<div class="card_fragment">
<ul>
<li
v-for="(item, index) in list"
:key="index"
:style="{
width: item.width + 'px',
height: item.height + 'px',
left: (current_fragment_id == item.id? current_left : item.current_left) + 'px',
top: (current_fragment_id == item.id ? current_top : item.current_top) + 'px',
'box-shadow': current_fragment_id == item.id && current_fragment_position_status ? '0 0 1rem green' : '0 0 0',
border: current_fragment_id == item.id && current_fragment_position_status ? '0.04rem solid green' : '0.04rem solid black',
transition: current_fragment_id == item.id ? '0s' : '0.2s',
'z-index': current_fragment_id == item.id ? '999' : '0',
background: item.background,
'background-position': '-' + item.one_left + 'px -' + item.one_top + 'px'
}"
@touchstart.stop.prevent="touchstart($event, item, index)"
@touchmove.stop.prevent="touchmove($event, item, index)"
@touchend.stop.prevent="touchend($event, item, index)"
>
<p>{{ index + 1 }}</p>
</li>
</ul>
</div>
</div>
- demo.js
Vue.createApp({
data() {
return {
list: [], //拼图碎片list
current_fragment_id: null, //当前移动中的碎片id
current_fragment_position_status: false, //当前移动中的碎片,位置是否是到达,要放的位置,是的话,变成绿色,不是不变
startPageX: 0,
startPageY: 0,
current_left: 0,
current_top: 0,
allfinish: false, //全部拼完
}
},
mounted() {
setTimeout(() => {
this.init()
}, 1000)
},
methods: {
//拼图初始化方法
init() {
let _this = this;
//1、把碎片内数组内的设计图尺寸转换成 当前设备下的 真实尺寸
//拼图的区域:one_parent
_this.one_parent_left = (window.innerWidth / 750) * 100 * 1.44;//拼图区域,距离页面最左边的位置
_this.one_parent_top = (window.innerWidth / 750) * 100 * 1.78;//拼图区域,距离页面最顶部的位置
//存放碎片的区域:two_parent
let two_parent_left = (window.innerWidth / 750) * 100 * 0.26;//存放碎片区域,距离页面最左边的位置
let two_parent_top = (window.innerWidth / 750) * 100 * (1.78 + 0.04 + 6.62 + 0.04 + 1.2 + 0.04);//存放碎片区域,距离页面最顶部的位置
let two_parent_width = (window.innerWidth / 750) * 100 * 7;//存放碎片区域,宽度
//2、初始化,碎片list 与 拼图的图片
let list = fragment1;
let len = list.length;
let imgurl = './艾索德.png';
//3、处理碎片list
for (let i = 0; i < len; i++) {
//当前碎片的大小,转换成,当前设备上,真实大小
list[i].width = (window.innerWidth / 750) * 100 * list[i].width;
list[i].height = (window.innerWidth / 750) * 100 * list[i].height;
list[i].one_left = (window.innerWidth / 750) * 100 * list[i].one_left;
list[i].one_top = (window.innerWidth / 750) * 100 * list[i].one_top;
//初始化当前碎片的位置
list[i].two_left = two_parent_left + (two_parent_width / 5) * i;
list[i].two_top = two_parent_top;
list[i].current_left = list[i].two_left;
list[i].current_top = list[i].two_top;
list[i].background = "url(" + imgurl + ") no-repeat white";
if (i == 0 || i == len - 1) {
//先放两个碎片,到拼图区域
list[i].current_left = _this.one_parent_left + list[i].one_left;
list[i].current_top = _this.one_parent_top + list[i].one_top;
list[i].finish = true;
} else {
let num = 0;
if (i == 1) {
num = 0;
} else if (i == 2) {
num = 1;
} else if (i == 3) {
num = 2;
}
//这个碎片list一共有5个碎片,上面已经放了2,还剩下三个,这里是设置这三个,在存放碎片区域的位置
list[i].two_left = two_parent_left + list[0].width * num;
list[i].current_left = list[i].two_left;
}
}
this.list = list;
},
//碎片,触摸开始
touchstart(e, item) {
if (item.finish == false) {
this.startPageX = e.changedTouches[0].pageX;
this.startPageY = e.changedTouches[0].pageY;
this.current_left = item.current_left;
this.current_top = item.current_top;
this.current_fragment_id = item.id;
}
},
//碎片,触摸移动
touchmove(e, item, index) {
let _this = this;
if (item.finish == false) {
let list = _this.list;
let pageX = e.changedTouches[0].pageX;
let pageY = e.changedTouches[0].pageY;
if (_this.current_fragment_id != null) {
//移动的距离
let moveX = pageX - _this.startPageX;
let moveY = pageY - _this.startPageY;
_this.current_left = _this.list[index].current_left + moveX;
_this.current_top = _this.list[index].current_top + moveY;
this.current_fragment_position_status = false;
//检测当前移动中的碎片,位置,是否是,碎片要放的位置
let check_left = _this.one_parent_left + list[index].one_left - 20;
let check_right = _this.one_parent_left + list[index].one_left + list[index].width;
let check_top = _this.one_parent_top + list[index].one_top - 20;
let check_bottom = _this.one_parent_top + list[index].one_top + list[index].height;
if (_this.current_left >= check_left && _this.current_left < check_right) {
if (_this.current_top >= check_top && _this.current_top < check_bottom) {
_this.current_fragment_position_status = true;
}
}
}
}
},
//触摸结束
touchend(e, item, index) {
let _this = this;
if (item.finish == false) {
//检测当前移动中的碎片,位置,是否是,要放的位置
if (_this.current_fragment_position_status == true) {
_this.list[index].current_left = _this.one_parent_left + _this.list[index].one_left;
_this.list[index].current_top = _this.one_parent_top + _this.list[index].one_top;
_this.list[index].finish = true;
//检测碎片是否都拼完成了
let len = _this.list.length;
let num = 0;
for (let i = 0; i < len; i++) {
if (_this.list[i].finish) {
num++;
}
}
if (num == len) {
console.log("全部拼完!");
_this.allfinish = true;
}
}
_this.current_fragment_position_status = false;
_this.current_fragment_id = null;
}
},
}
}).mount("#app");
//图的碎片数组
var fragment1 = [
{
id: 0,
width: 2.29,//碎片大小
height: 3.31,
one_left: 0, //完成时的位置
one_top: 0, //完成时的位置
current_left: 0, //当前位置
current_top: 0, //当前位置
two_left: 0, //未完成时的位置
two_top: 0, //未完成时的位置
finish: false,//碎片是否已经拼到相应位置
},
{
id: 1,
width: 2.29,
height: 3.31,
one_left: 0,
one_top: 3.31,
current_left: 0,
current_top: 0,
two_left: 0,
two_top: 0,
finish: false,
},
{
id: 2,
width: 2.29,
height: 2.2,
one_left: 2.29,
one_top: 0,
current_left: 0,
current_top: 0,
two_left: 0,
two_top: 0,
finish: false,
},
{
id: 3,
width: 2.29,
height: 2.2,
one_left: 2.29,
one_top: 2.2,
current_left: 0,
current_top: 0,
two_left: 0,
two_top: 0,
finish: false,
},
{
id: 4,
width: 2.29,
height: 2.2,
one_left: 2.29,
one_top: 4.4,
current_left: 0,
current_top: 0,
two_left: 0,
two_top: 0,
finish: false,
},
];
- demo.css
* {
margin: 0;
padding: 0;
}
/*拼图的区域*/
.card_frame {
width: 4.58rem;
height: 6.62rem;
margin: 0 auto;
margin-top: 1.78rem;
background: white;
border: 0.04rem solid black;
}
/*存放拼图碎片的区域*/
.card_fragment {
width: 7rem;
height: 3rem;
margin: 0 auto;
margin-top: 1.2rem;
background: #fed929;
border: 0.04rem solid black;
}
/*碎片样式*/
.card_fragment li {
display: flex;
align-items: center;
position: absolute;
border: 0.04rem solid black;
background: white;
color: black;
text-align: center;
font-weight: bold;
background-size: 4.58rem 6.62rem !important;
background: white;
}