Three.js图像拼图技术
图像拼图-CSDN直播图像拼图https://live.csdn.net/v/460095https://live.csdn.net/v/460095
一.HTML部分
#board
二.CSS部分
#board {
width:100vw;
height:100vh;
position:relative;
filter:contrast(3);
transition:filter 5s;
}
#board.finish {
filter:contrast(1);
}
.puzzle {
background: url(https://images.unsplash.com/photo-1516585427167-9f4af9627e6c?ixlib=rb-0.3.5&ixid=eyJhcHBfaWQiOjEyMDd9&s=800dd307bb9474d017eeaf3c14c5d157&auto=format&fit=crop&w=4000&q=80);
position:absolute;
transition:all 0s; /*mod by js soon*/
}
img {
display:none;
}
body {
min-height:100vh;
display:flex;
flex-flow:column nowrap;
justify-content:center;
align-items:center;
}
三.JS部分
const sz = 5;
const dur = 0.3;
//
// main
//
const rndPos = shuffle(Array.from(Array(sz*sz), (x,i)=>i));
for (let i = 0; i < sz * sz; i++) {
const el = makeEl(i);
el.dataset.correctPos = i;
el.dataset.currentPos = rndPos[i];
moveToCurrentPos(el);
board.appendChild(el);
}
const N = sz * sz;
const remain = Array.from(Array(N), (x,i)=>i.toString());
const rndRemainEl = ()=> board.children[remain[Math.random() * remain.length | 0]];
const advance = () => {
const at = remain.indexOf(el.dataset.correctPos);
remain.splice(at, 1);
return (remain.length) ? rndRemainEl() : null;
}
let i = 0;
let el = board.children[0];
setTimeout(function f() {
while (el.dataset.currentPos == el.dataset.correctPos)
if (!(el = advance())) return cbFinish();
correct(el);
if (!(el = advance())) return cbFinish();
setTimeout(f, dur*1e3);
}, 10);
function cbFinish() {
board.classList.add("finish");
}
//
// fns
//
// shuffle
function shuffle(arr) {
let n = arr.length;
while(n) {
let i = Math.random() * n | 0;
n--;
let tmp = arr[n];
arr[n] = arr[i];
arr[i] = tmp;
}
return arr;
}
function makeEl(idx) {
const el = document.createElement("div");
el.classList.add("puzzle");
el.style.backgroundPosition = `-${(idx%sz)*100}% -${(idx/sz|0)*100}%`;
el.style.width = `${100/sz}%`;
el.style.height = `${100/sz}%`;
el.style.transitionDuration = `${dur}s`;
el.style.backgroundSize = `${sz*100}% ${sz*100}%`;
return el;
}
function moveToCurrentPos(el) {
const idx = el.dataset.currentPos;
el.style.left = `${idx%sz/sz*100}%`;
el.style.top = `${(idx/sz|0)/sz*100}%`;
}
function correct(el) {
const dstEl = board.querySelector(`[data-current-pos="${el.dataset.correctPos}"]`);
dstEl.dataset.currentPos = el.dataset.currentPos; // update dstEl currentPos
moveToCurrentPos(dstEl); // dstEl goto new pos
el.dataset.currentPos = el.dataset.correctPos; // update el currentPos
moveToCurrentPos(el);
return dstEl;
}