1. 遊戲訪問連線
2. 九宮格拼圖原理
- 圖例原理:
- 上圖的九宮格圖例,每個格子都有一個(x,y)的座標,假如格子9是空白格子,怎麼知道6和8是它的直接相鄰格子呢。這時候就體現出格子座標(x,y)的作用了, 使用公式:|(x6 - x9)| + |(y6 - y9)| = 1,將空白格子9的座標與格子6的座標進行對應座標的差值的絕對值的和等於1,就證明它們是直接相鄰格子,可進行移動互換。
- 詳細原理請點選:跳轉
3. 實現過程,程式碼分析
- flex實現九宮格佈局:
<style>
.jigsaw {
margin-top: 15px;
}
.jigsaw .ul{
display: flex;
flex-wrap: wrap; // 換行
}
.ul .child {
width: 33.3%;
color: rgba(255, 255, 255, 0.5);
background-repeat: no-repeat;
}
</style>
<section class='jigsaw'>
<ul class="ul">
<li class="child" data-x='1' data-y='1' style="order:1">1</li>
<li class="child" data-x='2' data-y='1' style="order:2">2</li>
<li class="child" data-x='3' data-y='1' style="order:3">3</li>
<li class="child" data-x='1' data-y='2' style="order:4">4</li>
<li class="child" data-x='2' data-y='2' style="order:5">5</li>
<li class="child" data-x='3' data-y='2' style="order:6">6</li>
<li class="child" data-x='1' data-y='3' style="order:7">7</li>
<li class="child" data-x='2' data-y='3' style="order:8">8</li>
<li class="child" data-x='3' data-y='3' style="order:9" id='empty'>9</li>
</ul>
</section>
複製程式碼
- 現在的佈局是這樣子的:
// 設定格子的高度、背景圖片的尺寸
setChildStyle() {
this.childWidth = window.getComputedStyle(this.oChild[0], false).width; // 獲取格子寬度
console.log(this.childWidth);
for (let i = 0; i < this.oChild.length; i++) {
this.oChild[i].style.height = `${this.childWidth}`;
}
}
複製程式碼
- 現在變成
setChildStyle() {
this.childWidth = window.getComputedStyle(this.oChild[0], false).width;
console.log(this.childWidth);
for (let i = 0; i < this.oChild.length; i++) {
this.oChild[i].style.height = `${this.childWidth}`;
this.oChild[i].style.backgroundSize = `${this.ulWidth} auto`;
this.setBgpositon(this.oChild[i]);
}
}
複製程式碼
- 其實每個格子的背景圖片都是同一張,只不過是通過background-position 對背景圖片進行定位,讓每個格子只顯示圖片背景的九分之一,
// 設定背景圖在格子的位置
setBgpositon(chiObj) {
let x = chiObj.getAttribute('data-x') - 1;
let y = chiObj.getAttribute('data-y') - 1;
chiObj.style.backgroundPosition = `${-x*parseInt(this.childWidth)}px ${-y*parseInt(this.childWidth)}px`;
}
複製程式碼
如下圖視:
- 設定預設背景圖片後:
// 設定格子的背景圖片
setBgImg(imgUrl) {
for (let i = 0; i < this.oChild.length - 1; i++) {
this.oChild[i].style.backgroundImage = `url(${imgUrl})`;
}
}
複製程式碼
- 接下來把格子擼成可移動的,與空白格子直接相鄰的格子都可以與空白格子換位,一開始的order樣式就起作用了。點選格子,首先比較該格子是否與空白格子直接相鄰,如果是就交換格子的data-x、data-y和order值進行換位:
childEvent() {
let that = this;
let oEmptyChild = document.getElementById('empty'); // 獲取空白的格子物件
this.oUl[0].addEventListener('click', function(ev){
let target = ev.target;
let targetX, targetY, targetOrder;
let iEmptyX, iEmptyY, iEmptyOrder;
if (target.className != 'child' ) return false;
iEmptyX = oEmptyChild.getAttribute('data-x');
iEmptyY = oEmptyChild.getAttribute('data-y');
iEmptyOrder = window.getComputedStyle(oEmptyChild, false).order;
targetX = target.getAttribute('data-x');
targetY = target.getAttribute('data-y');
targetOrder = window.getComputedStyle(target, false).order;
if (Math.abs(targetX - iEmptyX) + Math.abs(targetY - iEmptyY) == 1) {
// data-x data-y order 值互換
[iEmptyX, targetX] = [targetX, iEmptyX];
[iEmptyY, targetY] = [targetY, iEmptyY];
[iEmptyOrder, targetOrder] = [targetOrder, iEmptyOrder];
oEmptyChild.setAttribute('data-x', iEmptyX);
oEmptyChild.setAttribute('data-y', iEmptyY);
oEmptyChild.style.order = iEmptyOrder;
target.setAttribute('data-x', targetX);
target.setAttribute('data-y', targetY);
target.style.order = targetOrder;
}
}, false);
}
複製程式碼
- 接下來是把上傳的img圖片設定成格子背景,通過監聽input type='file'的change事件來獲取圖片檔案files:
imgEvent() {
let that = this;
this.oFile.addEventListener('change', function(){
let imgUrl = window.URL.createObjectURL(this.files[0]); // 該方法將files轉換成img可訪問的本地路徑
that.oImg.setAttribute('src', imgUrl);
that.oImg.onload = function() {
that.setBgImg(imgUrl); // 重新設定格子背景
}
}, false);
}
複製程式碼
-
原始碼地址 點選訪問
-
(完)