Published
Edited
May 9, 2021
1 fork
Importers
7 stars
Insert cell
Insert cell
game = {
let game_ui_height = size+answers_rows*(padding+answer_height)+padding
let shadow = 4
var ui = svg`
<svg width="${width}" height="${game_ui_height+score_height}">
<style>
text {
font-family: sans-serif;
text-anchor: middle;
pointer-events: none;
fill: #333;
}
.card {
fill: white;
stroke-width: 3px;
stroke: #CCC;
}
.answer_btn:not(.clicked) {
cursor: pointer;
}
.shadow {
fill: #CCC;
}
.question {
font-size: ${ size*0.9 }px;
}
.answer {
font-weight: bold;
font-size: ${ answer_height*0.4 }px;
}
text.correct, text.wrong {
fill: white;
}
path.correct {
fill: #00973c;
stroke: #00973c;
}
path.wrong {
fill: #e2403f;
stroke: #e2403f;
}
.score {
font-size: ${ score_height*0.8 }px;
font-weight: bold;
}
tspan.correct {
fill: #00973c;
}
tspan.wrong {
fill: #e2403f;
}
tspan.total {
font-size: ${ score_height*0.5 }px;
}
</style>
<text
x="${ size/2 }"
y="${ size/2 }"
dy="0.35em"
class="question">
${ card[question] }
</text>
${
d3.range(answers_cols).map(j =>
d3.range(answers_rows).map(i => {
let w = (size-padding)/answers_cols
let h = answer_height
let answer_wrapper = answers[j*answers_rows+i]
let answer_class = answer_wrapper.clicked ? (answer_wrapper.card[answer] == card[answer] ? 'correct' : 'wrong') : ''
return `
<path
transform="translate(${ (w+padding)*j } ${ size + padding + (h+padding)*i })"
class="card shadow"
d="${ rounded_rect(w,h,16) }"/>
<path
transform="translate(${ (w+padding)*j } ${ size + padding + (h+padding)*i })"
class="card answer_btn ${ answer_class } ${ answer_wrapper.clicked ? 'clicked' : '' }"
d="${ rounded_rect(w,h-(answer_wrapper.clicked ? 0 : shadow),16) }"/>
<text
x="${ (w+padding)*(j+0.5) - padding/4 }"
y="${ size + padding/2 + (h+padding)*(i+0.5) }"
dy="0.35em"
class="answer ${ answer_class }">
${ answer_wrapper.card[answer] }
</text>
`})
)
}

<text x="${ size/2 }" y="${ game_ui_height + score_height/2 }" dy="0.35em" class="score">
<tspan class="correct">${ score }✓</tspan>
<tspan class="wrong">${ errors }❌</tspan>
<tspan class="total">${ deck.length }/${ data.length } cards left</tspan>
</text>
</svg>
`
// bind events
d3.select(ui).selectAll('.answer_btn')
.on('click', (_, i) => {
if(ui_locked) {
return;
}
(mutable answers)[i].clicked = true;
mutable answers = mutable answers; // retrigger cell
// update score, then proceed if answer was right
if(answers[i].card[answer] == card[answer]) {
mutable score += 1;
// lock ui to avoid repeated pressing of buttons
mutable ui_locked = true;
setTimeout(() => {
mutable turn += 1;
mutable ui_locked = false;
}, 800);
}
else {
mutable errors += 1;
}
})
return ui
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more