.information
span It takes
span.step 0
span steps.
.wrapper
// generate boxes
.operator
button.sort(onclick="bubbleSort()") SORT
button.reset(onclick="reset()") RESET
View Compiled
body
margin: 0
padding: 0
display: flex
justify-content: center
align-items: center
flex-direction: column
height: 100vh
font-family: 'Barlow', sans-serif
background-color: #333
.information
color: #fff
font-size: 1.5rem
margin-bottom: 1.25rem
> *
margin: 0 0.125rem
.wrapper
display: flex
position: relative
width: 800px
height: 80px
.box
display: flex
justify-content: center
align-items: center
position: absolute
width: 80px
height: 80px
border: 4px solid #000
background-color: #fff
font-size: 3rem
font-weight: 500
left: calc(var(--i) * 80px)
transition: all 1s
overflow: hidden
&:before
content: ''
width: 100%
height: 100%
position: absolute
top: -5%
left: -90%
background-color: rgba(silver, 0.3)
transform: skew(10deg)
.operator
margin: 2rem
button
padding: 0.25rem
width: 100px
font-size: 1.5rem
background-color: #fff
cursor: pointer
border: 3px solid #000
font-family: 'Barlow', sans-serif
font-weight: 500
position: relative
overflow: hidden
&:before
content: ''
width: 100%
height: 100%
position: absolute
top: 0
left: 0
transition: 0.4s
background-color: rgba(gold, 0.5)
transform: scale(0)
&:hover
box-shadow: 0 0 10px 0 rgba(gold, 0.4)
&:before
transform: scale(1)
background-color: rgba(gold, 0.06)
View Compiled
const example = [4, 7, 0, 5, 3, 0, 9, 2, 8, 6];
let arr = [];
let sortStep = 0;
let swapStep = 0;
// 建立 box
function createEl() {
let wrapper = document.querySelector(".wrapper");
let index = 0;
arr = JSON.parse(JSON.stringify(example));
for (let a of arr) {
let box = document.createElement("div");
box.classList.add("box", `box_${a}`);
box.innerText = a;
// 運用 setProperty 塞入 css variable
box.style.setProperty("--i", index);
wrapper.appendChild(box);
index++;
}
}
// 氣泡排序
function bubbleSort() {
sortStep = 0;
for (let i = 0; i < arr.length - 2; i++) {
for (let j = arr.length - 1; j >= i + 1; j--) {
if (arr[j] < arr[j - 1]) {
let moveForward = arr[j];
let moveBackward = arr[j - 1];
arr[j] = arr[j - 1];
arr[j - 1] = moveForward;
// 交換位置
setTimeout(
() => swapPosition(moveForward, moveBackward),
(sortStep + 1) * 1200
);
sortStep++;
}
}
}
}
// 抓出兩個要交換的 box 的 transform 位置
// forward 往前 -80px, backward 往後 +80px
function swapPosition(forward, backward) {
const seperateNum = (str) => Number(str.match(/-*\d+/));
let forwardEl = document.querySelector(`.box_${forward}`);
let backwardEl = document.querySelector(`.box_${backward}`);
forwardEl.style.transform = `translateX(${
seperateNum(forwardEl.style.transform) - 80
}px)`;
backwardEl.style.transform = `translateX(${
seperateNum(backwardEl.style.transform) + 80
}px)`;
swapStep++;
rewriteStep();
}
// 清空所有 box 的 transform, 重置數列
function reset() {
// 阻止排序中重置
if (sortStep !== swapStep) return;
let allBoxes = Array.from(document.querySelectorAll(".box"));
allBoxes.forEach((a) => (a.style.transform = ""));
arr = JSON.parse(JSON.stringify(example));
swapStep = 0;
rewriteStep();
}
function rewriteStep() {
let stepEl = document.querySelector(".step");
stepEl.innerText = swapStep;
}
createEl();
// WIP: 重複數字的問題,應該要判斷正確的 index 再 swap
// WIP: 也許可以用 animation delay 取代 setTimeout 動畫
// WIP: function 共用優化
This Pen doesn't use any external CSS resources.
This Pen doesn't use any external JavaScript resources.