Details
Trading out eyewear from a shelf is instant in the virtual world.
Using the next iteration of bitty to pull in the SVGs and templates and wiring up the signals to make things easier.
The HTML
<bitty-2-0 data-connect="Trader" data-send="body|shelf">
<div class="wrapper">
<div class="body" data-receive="body"></div>
<div data-receive="shelf"></div>
</div>
</bitty-2-0>
The JavaScript
const items = [
"eyepatch", "glasses", "glasses-2", "glasses-3", "glasses-4", "glasses-5", "sunglasses", "sunglasses-2",
];
const t = {
face: `
<div class="face-item" data-receive="updateFaceItem" data-item="ITEM"></div>`,
shelf: `
<button
class="shelf-item"
data-send="updateShelfItem"
data-receive="updateShelfItem"
data-item="ITEM"></button>`,
}
window.Trader = class {
async body(_event, el){
let svg = await this.api.fetchSVG("/svgs/body/thunder-t-shirt.svg");
el.appendChild(svg);
svg = await this.api.fetchSVG("/svgs/head/shaved-1.svg");
el.appendChild(svg);
svg = await this.api.fetchSVG("/svgs/face/smile.svg");
el.appendChild(svg);
for (let key of items) {
let subs = [["ITEM", key]];
let svg = await this.api.fetchSVG(`/svgs/accessories/${key}.svg`);
let item = await this.api.useEl(t.face, subs);
item.classList.add("hidden");
item.appendChild(svg);
el.appendChild(item);
}
}
async shelf(_event, el) {
for (let key of items) {
let subs = [["ITEM", key]];
let svg = await this.api.fetchSVG(`/svgs/accessories/${key}.svg`);
let item = await this.api.useEl(t.shelf, subs);
item.appendChild(svg);
el.appendChild(item);
}
}
updateFaceItem(event, el) {
if (this.api.match(event, el, "item")) {
el.classList.remove("hidden");
} else {
el.classList.add("hidden");
}
}
updateShelfItem(event, el) {
if (this.api.match(event, el, "item")) {
el.classList.add("current");
} else {
el.classList.remove("current");
}
this.api.forward(event, "updateFaceItem");
}
};
The CSS
.wrapper {
background-color: var(--reverse-faded2);
border-radius: var(--default-radius);
position: relative;
display: grid;
grid-template-columns: 2fr 1fr;
}
.body {
position: relative;
height: 400px;
}
.body-mono-thunder-t-shirt {
position: absolute;
top: 130px;
left: 30px;
width: 200px;
height: auto;
}
.face-item {
position: absolute;
top: 22px;
left: 108px;
width: 84px;
height: auto;
}
.face-item.hidden svg {
opacity: 0;
}
.face-smile {
position: absolute;
top: 64px;
left: 128px;
width: 70px;
height: auto;
}
.head-mono-shaved-1 {
position: absolute;
top: 27px;
left: 95px;
width: 108px;
height: auto;
}
.shelf-item {
display: flex;
justify-content: center;
}
.shelf-item svg {
width: 40%;
height: auto;
}
.shelf-item.current svg {
opacity: 0;
}