99 lines
3.5 KiB
JavaScript
99 lines
3.5 KiB
JavaScript
import { Controller } from "https://unpkg.com/@hotwired/stimulus/dist/stimulus.js";
|
|
import { gameState } from "./gamestate.js";
|
|
|
|
const ANIMATION_DURATION = 1500.0;
|
|
const CIRCLE_RADIUS = 50;
|
|
|
|
export default class extends Controller {
|
|
static targets = ['path', 'pathBack', 'count', 'postScore', 'rank'];
|
|
|
|
connect() {
|
|
this._startT = 0;
|
|
|
|
window.setTimeout(() => {
|
|
requestAnimationFrame(this._startAnimating.bind(this));
|
|
}, 500);
|
|
}
|
|
|
|
_startAnimating(t) {
|
|
this._finalScore = gameState.getSummary().totalRight;
|
|
|
|
this._startT = t;
|
|
this._finalArcPostition = 360 * this._finalScore / gameState.getMaxQuestions();
|
|
|
|
this._currentlyDisplayedScore = 0;
|
|
this.countTarget.innerText = "0%";
|
|
requestAnimationFrame(this._animateFrame.bind(this));
|
|
}
|
|
|
|
_animateFrame(t) {
|
|
let tt = t - this._startT;
|
|
let tScaled = tt / ANIMATION_DURATION;
|
|
|
|
if (tt >= ANIMATION_DURATION) {
|
|
if (this._finalArcPostition == 360) {
|
|
this.pathTarget.setAttribute("d", this._describeCircle(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS - 5));
|
|
} else {
|
|
this.pathTarget.setAttribute("d", this._describeArc(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS - 5, 0, this._finalArcPostition));
|
|
}
|
|
|
|
let scoreToDisplay = (this._finalScore * 100 / gameState.getMaxQuestions()) | 0;
|
|
this.countTarget.innerText = `${scoreToDisplay}%`;
|
|
window.setTimeout(() => this._showPostStore(), 1);
|
|
return;
|
|
}
|
|
|
|
let arcT = Math.sin(tt / ANIMATION_DURATION * Math.PI / 2.0);
|
|
|
|
this.pathTarget.setAttribute("d", this._describeArc(CIRCLE_RADIUS, CIRCLE_RADIUS, CIRCLE_RADIUS - 5, 0, this._finalArcPostition * arcT));
|
|
|
|
let scoreToDisplay = (arcT * this._finalScore * 100 / gameState.getMaxQuestions()) | 0;
|
|
if (scoreToDisplay != this._currentlyDisplayedScore) {
|
|
this._currentlyDisplayedScore = scoreToDisplay;
|
|
this.countTarget.innerText = `${scoreToDisplay}%`;
|
|
}
|
|
|
|
requestAnimationFrame(this._animateFrame.bind(this));
|
|
}
|
|
|
|
_polarToCartesian(centerX, centerY, radius, angleInDegrees) {
|
|
var angleInRadians = (angleInDegrees - 180) * Math.PI / 180;
|
|
|
|
return {
|
|
x: centerX + (radius * Math.cos(angleInRadians)),
|
|
y: centerY + (radius * Math.sin(angleInRadians))
|
|
};
|
|
}
|
|
|
|
_describeCircle(x, y, radius) {
|
|
var start = this._polarToCartesian(x, y, radius, 0);
|
|
var mid = this._polarToCartesian(x, y, radius, 180);
|
|
var end = this._polarToCartesian(x, y, radius, 360);
|
|
|
|
var d = [
|
|
"M", start.x, start.y,
|
|
"A", radius, radius, 0, 0, 0, mid.x, mid.y,
|
|
"A", radius, radius, 0, 1, 0, end.x, end.y,
|
|
].join(" ");
|
|
return d;
|
|
}
|
|
|
|
_describeArc(x, y, radius, startAngle, endAngle){
|
|
var start = this._polarToCartesian(x, y, radius, endAngle);
|
|
var end = this._polarToCartesian(x, y, radius, startAngle);
|
|
var largeArcFlag = endAngle - startAngle <= 180 ? "0" : "1";
|
|
|
|
var d = [
|
|
"M", start.x, start.y,
|
|
"A", radius, radius, 0, largeArcFlag, 0, end.x, end.y
|
|
].join(" ");
|
|
return d;
|
|
}
|
|
|
|
_showPostStore() {
|
|
let rank = gameState.getSummary().rank;
|
|
this.rankTarget.innerText = rank;
|
|
|
|
this.postScoreTarget.classList.remove("hidden");
|
|
}
|
|
} |