Details
Characters from Open Peeps.
I'm using bitty for the
event to element wiring. The rest of the code is below.
The [! include ... !] calls are what's loading
the SVG images inline.
The HTML
<div hidden>
[! include "_wrappers/svgs-body.html" !]
[! include "_wrappers/svgs-head.html" !]
[! include "_wrappers/svgs-face.html" !]
</div>
<bitty-2-0 data-connect="ThePeeps" data-send="peeps">
<div data-receive="peeps"></div>
<button data-send="scrambleBody|peep">Scramble Bodies</button>
<button data-send="scrambleHead|peep">Scramble Heads</button>
</bitty-2-0>
The JavaScript
class State2 {
scrambleBody() {
shuffleArray(this.bodies);
}
scrambleHead() {
shuffleArray(this.heads);
}
}
function shuffleArray(array) {
let currentIndex = array.length;
let randomIndex;
while (currentIndex != 0) {
randomIndex = Math.floor(Math.random() * currentIndex);
currentIndex--;
[array[currentIndex], array[randomIndex]] = [
array[randomIndex],
array[currentIndex],
];
}
}
const s2 = new State2();
window.ThePeeps = class {
bittyInit() {
s2.bodies = [...document.querySelectorAll("[data-part=body]")].toSpliced(
12,
);
s2.faces = [...document.querySelectorAll("[data-part=face]")].toSpliced(
12,
);
s2.heads = [...document.querySelectorAll("[data-part=head]")].toSpliced(
12,
);
}
peep(_event, el) {
el.replaceChildren(s2.bodies[el.dataset.num]);
el.appendChild(s2.heads[el.dataset.num]);
el.appendChild(s2.faces[el.dataset.num]);
}
async peeps(_event, el) {
for (let num = 0; num < 12; num += 1) {
let peep = document.createElement("div");
peep.dataset.num = num;
peep.dataset.receive = "peep";
await el.appendChild(peep);
}
this.api.forward(null, "peep");
}
scrambleBody(_event, _el) {
s2.scrambleBody();
}
scrambleHead(_event, _el) {
s2.scrambleHead();
}
}
The CSS
[data-part=body] {
position: absolute;
top: 36px;
left: 10px;
width: 70px;
height: 70px;
}
[data-part=face] {
position: absolute;
top: 13px;
left: 42px;
width: 30px;
height: 30px;
}
[data-receive=peeps] {
display: flex;
flex-wrap: wrap;
}
[data-receive=peep] {
margin: var(--default-margin);
position: relative;
width: 100px;
height: 100px;
}
[data-part=head] {
position: absolute;
top: 0px;
left: 28px;
width: 50px;
height: 50px;
}