big ui refractor
This commit is contained in:
@@ -38,6 +38,7 @@ export class KanjiController {
|
||||
this.isAnimating = false;
|
||||
|
||||
this.ctx = { bg: null, hint: null, draw: null };
|
||||
this.hintAnimationFrame = null;
|
||||
}
|
||||
|
||||
static createPathElement(d) {
|
||||
@@ -120,7 +121,16 @@ export class KanjiController {
|
||||
}
|
||||
}
|
||||
|
||||
setAutoHint(val) {
|
||||
this.autoHint = val;
|
||||
if (!val) {
|
||||
this.clearCanvas(this.ctx.hint);
|
||||
}
|
||||
}
|
||||
|
||||
async loadChar(char, autoHint = false) {
|
||||
this.autoHint = autoHint;
|
||||
this.paths = [];
|
||||
this.reset();
|
||||
const hex = char.charCodeAt(0).toString(16).padStart(5, '0');
|
||||
|
||||
@@ -139,6 +149,11 @@ export class KanjiController {
|
||||
}
|
||||
|
||||
reset() {
|
||||
if (this.hintAnimationFrame) {
|
||||
cancelAnimationFrame(this.hintAnimationFrame);
|
||||
this.hintAnimationFrame = null;
|
||||
}
|
||||
|
||||
this.currentStrokeIdx = 0;
|
||||
this.mistakes = 0;
|
||||
this.isAnimating = false;
|
||||
@@ -148,6 +163,10 @@ export class KanjiController {
|
||||
this.clearCanvas(this.ctx.hint);
|
||||
this.drawGrid();
|
||||
this.resetDrawStyle();
|
||||
|
||||
if (this.autoHint && this.paths.length > 0) {
|
||||
this.showHint();
|
||||
}
|
||||
}
|
||||
|
||||
startStroke(point) {
|
||||
@@ -191,6 +210,11 @@ export class KanjiController {
|
||||
}
|
||||
|
||||
showHint() {
|
||||
if (this.hintAnimationFrame) {
|
||||
cancelAnimationFrame(this.hintAnimationFrame);
|
||||
this.hintAnimationFrame = null;
|
||||
}
|
||||
|
||||
this.clearCanvas(this.ctx.hint);
|
||||
if (this.currentStrokeIdx >= this.paths.length) return;
|
||||
|
||||
@@ -199,20 +223,49 @@ export class KanjiController {
|
||||
const len = pathEl.getTotalLength();
|
||||
|
||||
const ctx = this.ctx.hint;
|
||||
ctx.beginPath();
|
||||
ctx.strokeStyle = KANJI_CONSTANTS.COLORS.HINT;
|
||||
ctx.setLineDash(KANJI_CONSTANTS.DASH_ARRAY_HINT);
|
||||
|
||||
const step = 5;
|
||||
const count = Math.floor(len / step) + 1;
|
||||
const startTime = performance.now();
|
||||
const DURATION = 600;
|
||||
|
||||
Array.from({ length: count }).forEach((_, i) => {
|
||||
const dist = Math.min(i * step, len);
|
||||
const pt = pathEl.getPointAtLength(dist);
|
||||
if (i === 0) ctx.moveTo(pt.x * this.scale, pt.y * this.scale);
|
||||
else ctx.lineTo(pt.x * this.scale, pt.y * this.scale);
|
||||
});
|
||||
ctx.stroke();
|
||||
const animate = (now) => {
|
||||
const elapsed = now - startTime;
|
||||
const progress = Math.min(elapsed / DURATION, 1);
|
||||
|
||||
this.clearCanvas(ctx);
|
||||
ctx.beginPath();
|
||||
|
||||
const drawLen = len * progress;
|
||||
const step = 5;
|
||||
|
||||
let first = true;
|
||||
for (let dist = 0; dist <= drawLen; dist += step) {
|
||||
const pt = pathEl.getPointAtLength(dist);
|
||||
if (first) {
|
||||
ctx.moveTo(pt.x * this.scale, pt.y * this.scale);
|
||||
first = false;
|
||||
} else {
|
||||
ctx.lineTo(pt.x * this.scale, pt.y * this.scale);
|
||||
}
|
||||
}
|
||||
|
||||
if (drawLen > 0) {
|
||||
const pt = pathEl.getPointAtLength(drawLen);
|
||||
if (first) ctx.moveTo(pt.x * this.scale, pt.y * this.scale);
|
||||
else ctx.lineTo(pt.x * this.scale, pt.y * this.scale);
|
||||
}
|
||||
|
||||
ctx.stroke();
|
||||
|
||||
if (progress < 1) {
|
||||
this.hintAnimationFrame = requestAnimationFrame(animate);
|
||||
} else {
|
||||
this.hintAnimationFrame = null;
|
||||
}
|
||||
};
|
||||
|
||||
this.hintAnimationFrame = requestAnimationFrame(animate);
|
||||
}
|
||||
|
||||
redrawAllPerfectStrokes(includeCurrent = false) {
|
||||
@@ -257,13 +310,22 @@ export class KanjiController {
|
||||
}));
|
||||
|
||||
if (this.checkMatch(userNormalized, targetD)) {
|
||||
if (this.hintAnimationFrame) {
|
||||
cancelAnimationFrame(this.hintAnimationFrame);
|
||||
this.hintAnimationFrame = null;
|
||||
}
|
||||
|
||||
this.animateMorph(this.userPath, targetD, () => {
|
||||
this.currentStrokeIdx += 1;
|
||||
this.mistakes = 0;
|
||||
this.redrawAllPerfectStrokes();
|
||||
|
||||
this.clearCanvas(this.ctx.hint);
|
||||
|
||||
if (this.currentStrokeIdx >= this.paths.length) {
|
||||
this.onComplete();
|
||||
} else if (this.autoHint) {
|
||||
this.showHint();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user