rename & handle several canvas
This commit is contained in:
parent
221bc4a1c4
commit
97359d172b
7 changed files with 192 additions and 145 deletions
51
datas.js
51
datas.js
|
|
@ -1,28 +1,29 @@
|
|||
<script>
|
||||
const nombresChinois = [
|
||||
{ valeur: 1, hanzi: "一", pinyin: "yī" },
|
||||
{ valeur: 2, hanzi: "二", pinyin: "èr" },
|
||||
{ valeur: 3, hanzi: "三", pinyin: "sān" },
|
||||
{ valeur: 4, hanzi: "四", pinyin: "sì" },
|
||||
{ valeur: 5, hanzi: "五", pinyin: "wǔ" },
|
||||
{ valeur: 6, hanzi: "六", pinyin: "liù" },
|
||||
{ valeur: 7, hanzi: "七", pinyin: "qī" },
|
||||
{ valeur: 8, hanzi: "八", pinyin: "bā" },
|
||||
{ valeur: 9, hanzi: "九", pinyin: "jiǔ" },
|
||||
{ valeur: 10, hanzi: "十", pinyin: "shí" }
|
||||
];
|
||||
const nombresChinois = [
|
||||
{ valeur: 1, hanzi: "一", pinyin: "yī" },
|
||||
{ valeur: 2, hanzi: "二", pinyin: "èr" },
|
||||
{ valeur: 3, hanzi: "三", pinyin: "sān" },
|
||||
{ valeur: 4, hanzi: "四", pinyin: "sì" },
|
||||
{ valeur: 5, hanzi: "五", pinyin: "wǔ" },
|
||||
{ valeur: 6, hanzi: "六", pinyin: "liù" },
|
||||
{ valeur: 7, hanzi: "七", pinyin: "qī" },
|
||||
{ valeur: 8, hanzi: "八", pinyin: "bā" },
|
||||
{ valeur: 9, hanzi: "九", pinyin: "jiǔ" },
|
||||
{ valeur: 10, hanzi: "十", pinyin: "shí" },
|
||||
{ valeur: 11, hanzi: "十一", pinyin: "shíyī" }
|
||||
];
|
||||
|
||||
const pronomsChinois = [
|
||||
{ hanzi: "我", pinyin: "wǒ", valeur: "je / moi" },
|
||||
{ hanzi: "你", pinyin: "nǐ", valeur: "tu / toi" },
|
||||
{ hanzi: "您", pinyin: "nín", valeur: "vous (politesse)" },
|
||||
{ hanzi: "他", pinyin: "tā", valeur: "il / lui" },
|
||||
{ hanzi: "她", pinyin: "tā", valeur: "elle" },
|
||||
{ hanzi: "它", pinyin: "tā", valeur: "il/elle (objet, animal)" },
|
||||
{ hanzi: "我们", pinyin: "wǒmen", valeur: "nous" },
|
||||
{ hanzi: "你们", pinyin: "nǐmen", valeur: "vous (pluriel)" },
|
||||
{ hanzi: "他们", pinyin: "tāmen", valeur: "ils (masculin ou mixte)" },
|
||||
{ hanzi: "她们", pinyin: "tāmen", valeur: "elles (féminin)" },
|
||||
{ hanzi: "它们", pinyin: "tāmen", valeur: "ils/elles (objets, animaux)" }
|
||||
];
|
||||
const pronomsChinois = [
|
||||
{ hanzi: "我", pinyin: "wǒ", francais: "je / moi" },
|
||||
{ hanzi: "你", pinyin: "nǐ", francais: "tu / toi" },
|
||||
{ hanzi: "您", pinyin: "nín", francais: "vous (politesse)" },
|
||||
{ hanzi: "他", pinyin: "tā", francais: "il / lui" },
|
||||
{ hanzi: "她", pinyin: "tā", francais: "elle" },
|
||||
{ hanzi: "它", pinyin: "tā", francais: "il/elle (objet, animal)" },
|
||||
{ hanzi: "我们", pinyin: "wǒmen", francais: "nous" },
|
||||
{ hanzi: "你们", pinyin: "nǐmen", francais: "vous (pluriel)" },
|
||||
{ hanzi: "他们", pinyin: "tāmen", francais: "ils (masculin ou mixte)" },
|
||||
{ hanzi: "她们", pinyin: "tāmen", francais: "elles (féminin)" },
|
||||
{ hanzi: "它们", pinyin: "tāmen", francais: "ils/elles (objets, animaux)" }
|
||||
];
|
||||
</script>
|
||||
19
hanzi_1.html
Normal file
19
hanzi_1.html
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<div id="challenge"></div>
|
||||
<div id="canvas" class="hanzi-canvas-container"></div>
|
||||
<button id="valid">Vérifier</button>
|
||||
<p id="feedback"></p>
|
||||
<script>
|
||||
const module1 = createMyReusableModule();
|
||||
|
||||
module1.init({
|
||||
challengeID: "challenge",
|
||||
canvasID: "canvas",
|
||||
feedbackID: "feedback",
|
||||
button_OK_ID: "valid",
|
||||
view_settings: {
|
||||
showCharacter: true,
|
||||
showOutline: true,
|
||||
},
|
||||
datas: nombresChinois
|
||||
});
|
||||
</script>
|
||||
19
hanzi_1.js
19
hanzi_1.js
|
|
@ -1,19 +0,0 @@
|
|||
<div id="challenge"></div>
|
||||
<div id="canvas" style="width:200px; height:200px; margin-bottom:10px; border: 2px; border-style: solid;"></div>
|
||||
<button id="valid">Vérifier</button>
|
||||
<p id="feedback"></p>
|
||||
<script>
|
||||
const module1 = createMyReusableModule();
|
||||
|
||||
module1.init({
|
||||
challengeID: "challenge",
|
||||
canvasID: "canvas",
|
||||
feedbackID: "feedback",
|
||||
button_OK_ID: "valid",
|
||||
view_settings: {
|
||||
showCharacter: true,
|
||||
showOutline: true,
|
||||
},
|
||||
datas: nombresChinois
|
||||
});
|
||||
</script>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<div id="challenge1"></div>
|
||||
<div id="canvas1" style="width:200px; height:200px; margin-bottom:10px; border: 2px; border-style: solid;"></div>
|
||||
<div id="canvas1" class="hanzi-canvas-container"></div>
|
||||
<button id="valid1">Vérifier</button>
|
||||
<p id="feedback1"></p>
|
||||
<script>
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
<div id="challenge3"></div>
|
||||
<div id="canvas3" style="width:200px; height:200px; margin-bottom:10px; border: 2px; border-style: solid;"></div>
|
||||
<div id="canvas3" class="hanzi-canvas-container"></div>
|
||||
<button id="valid3">Vérifier</button>
|
||||
<p id="feedback3"></p>
|
||||
<script>
|
||||
const module1 = createMyReusableModule();
|
||||
const module3 = createMyReusableModule();
|
||||
|
||||
module1.init({
|
||||
module3.init({
|
||||
challengeID: "challenge3",
|
||||
canvasID: "canvas3",
|
||||
feedbackID: "feedback3",
|
||||
223
module_hanzi.js
223
module_hanzi.js
|
|
@ -1,129 +1,158 @@
|
|||
<script src="https://cdn.jsdelivr.net/npm/hanzi-writer@3.5/dist/hanzi-writer.min.js"></script>
|
||||
<script>
|
||||
function createMyReusableModule() {
|
||||
function createMyReusableModule() {
|
||||
|
||||
function init(options = {}) {
|
||||
|
||||
// Chaque instance possède son propre état
|
||||
let iNb = 0;
|
||||
let ok = false;
|
||||
let hw = null;
|
||||
let datas_length = 0;
|
||||
let datas = options.datas;
|
||||
let datas_length = datas.length;
|
||||
|
||||
function init(options = {}) {
|
||||
displayChallenge(
|
||||
options.challengeID,
|
||||
options.datas[iNb].valeur,
|
||||
options.datas[iNb].pinyin
|
||||
);
|
||||
displayChallenge(
|
||||
options.challengeID,
|
||||
datas[iNb].valeur,
|
||||
datas[iNb].pinyin
|
||||
);
|
||||
|
||||
datas_length = options.datas.length;
|
||||
// --- INITIALISATION MULTI‑CANVAS ---
|
||||
let { writers, okArray } = initMultiCanvas(
|
||||
options.canvasID,
|
||||
datas[iNb].hanzi,
|
||||
options.view_settings
|
||||
);
|
||||
|
||||
// Initialisation du writer
|
||||
hw = initHW(
|
||||
options.canvasID,
|
||||
options.datas[iNb].hanzi,
|
||||
options.view_settings.showCharacter,
|
||||
options.view_settings.showOutline
|
||||
);
|
||||
startMultiQuiz(writers, okArray);
|
||||
|
||||
const callback_ok = () => { ok = true; };
|
||||
const callback_nok = () => { ok = false; };
|
||||
const bouton = document.querySelector("#" + options.button_OK_ID);
|
||||
|
||||
// Lancer le premier quiz
|
||||
startQuiz1(hw, callback_ok, callback_nok);
|
||||
const handleClick = () => {
|
||||
|
||||
const bouton = document.querySelector("#" + options.button_OK_ID);
|
||||
let isOK = checkAll(okArray, options.feedbackID);
|
||||
|
||||
const handleClick = () => {
|
||||
let isOK = check(ok, options.feedbackID, options.challengeID);
|
||||
switch (isOK) {
|
||||
case 0:
|
||||
// incorrect → rien
|
||||
break;
|
||||
|
||||
switch (isOK) {
|
||||
case 0:
|
||||
// fail
|
||||
break;
|
||||
case 1:
|
||||
// correct → mot suivant
|
||||
iNb++;
|
||||
|
||||
case 1:
|
||||
// success
|
||||
iNb++;
|
||||
if (iNb >= datas_length) {
|
||||
document.getElementById(options.feedbackID).textContent = "Fini !";
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (iNb >= datas_length) {
|
||||
document.getElementById(options.feedbackID).textContent = "Fini !";
|
||||
return -1;
|
||||
}
|
||||
displayChallenge(
|
||||
options.challengeID,
|
||||
datas[iNb].valeur,
|
||||
datas[iNb].pinyin
|
||||
);
|
||||
|
||||
callback_nok();
|
||||
displayChallenge(
|
||||
options.challengeID,
|
||||
options.datas[iNb].valeur,
|
||||
options.datas[iNb].pinyin
|
||||
);
|
||||
// Réinitialiser les canvas pour le nouveau mot
|
||||
let res = initMultiCanvas(
|
||||
options.canvasID,
|
||||
datas[iNb].hanzi,
|
||||
options.view_settings
|
||||
);
|
||||
|
||||
nextQuiz(
|
||||
hw,
|
||||
options.datas[iNb].hanzi,
|
||||
callback_ok,
|
||||
callback_nok
|
||||
);
|
||||
writers = res.writers;
|
||||
okArray = res.okArray;
|
||||
|
||||
break;
|
||||
startMultiQuiz(writers, okArray);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
};
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
bouton.addEventListener("click", handleClick);
|
||||
}
|
||||
bouton.addEventListener("click", handleClick);
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// AFFICHAGE DU CHALLENGE
|
||||
// ---------------------------------------------------------
|
||||
function displayChallenge(divName, chineseChar, pinyin) {
|
||||
document.getElementById(divName).textContent =
|
||||
"Écrire : " + chineseChar + " / " + pinyin;
|
||||
}
|
||||
|
||||
function displayChallenge(divName, chineseChar, pinyin) {
|
||||
document.getElementById(divName).textContent =
|
||||
"Écrire : " + chineseChar + " / " + pinyin;
|
||||
}
|
||||
// ---------------------------------------------------------
|
||||
// CRÉATION MULTI‑CANVAS
|
||||
// ---------------------------------------------------------
|
||||
function initMultiCanvas(containerID, hanzi, view_settings) {
|
||||
|
||||
function initHW(canvasID, currentChar, bShowCharacter, bShowOutline) {
|
||||
return HanziWriter.create(canvasID, currentChar, {
|
||||
const chars = [...hanzi]; // "十一" → ["十","一"]
|
||||
|
||||
const container = document.getElementById(containerID);
|
||||
container.innerHTML = ""; // reset
|
||||
|
||||
let writers = [];
|
||||
let okArray = new Array(chars.length).fill(false);
|
||||
|
||||
chars.forEach((char, index) => {
|
||||
|
||||
const c = document.createElement("div");
|
||||
c.id = `${containerID}_${index}`;
|
||||
c.style.display = "inline-block";
|
||||
c.style.marginRight = "10px";
|
||||
container.appendChild(c);
|
||||
|
||||
const hw = HanziWriter.create(c.id, char, {
|
||||
width: 150,
|
||||
height: 150,
|
||||
showCharacter: bShowCharacter,
|
||||
showOutline: bShowOutline,
|
||||
showCharacter: view_settings.showCharacter,
|
||||
showOutline: view_settings.showOutline,
|
||||
showHintAfterMisses: 1,
|
||||
highlightOnComplete: false,
|
||||
padding: 5
|
||||
});
|
||||
}
|
||||
|
||||
function startQuiz1(hw, fbok, fbpok) {
|
||||
fbpok(); // reset
|
||||
writers.push(hw);
|
||||
});
|
||||
|
||||
hw.quiz({
|
||||
onMistake: () => fbpok(),
|
||||
onCorrectStroke: () => { },
|
||||
onComplete: () => fbok()
|
||||
});
|
||||
}
|
||||
|
||||
// Return >0 if ok; 0: fail; -1 if finish
|
||||
function check(ok, feedbackId) {
|
||||
if (ok) {
|
||||
document.getElementById(feedbackId).textContent = "✔️ Bravo !";
|
||||
document.getElementById(feedbackId).style.color = "green";
|
||||
return 1;
|
||||
} else {
|
||||
document.getElementById(feedbackId).textContent = "❌ Incorrect, continue !";
|
||||
document.getElementById(feedbackId).style.color = "red";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function nextQuiz(hw, hanzi, fbok, fbpok) {
|
||||
hw.setCharacter(hanzi);
|
||||
startQuiz1(hw, fbok, fbpok);
|
||||
}
|
||||
|
||||
// On expose uniquement init()
|
||||
return {
|
||||
init
|
||||
};
|
||||
return { writers, okArray };
|
||||
}
|
||||
|
||||
</script>
|
||||
// ---------------------------------------------------------
|
||||
// LANCER UN QUIZ PAR CANVAS
|
||||
// ---------------------------------------------------------
|
||||
function startMultiQuiz(writers, okArray) {
|
||||
|
||||
writers.forEach((hw, idx) => {
|
||||
|
||||
okArray[idx] = false; // reset
|
||||
|
||||
hw.quiz({
|
||||
onMistake: () => { okArray[idx] = false; },
|
||||
onCorrectStroke: () => {},
|
||||
onComplete: () => { okArray[idx] = true; }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// CHECK GLOBAL
|
||||
// ---------------------------------------------------------
|
||||
function checkAll(okArray, feedbackId) {
|
||||
|
||||
const allOK = okArray.every(v => v === true);
|
||||
|
||||
if (allOK) {
|
||||
document.getElementById(feedbackId).textContent = "✔️ Bravo !";
|
||||
document.getElementById(feedbackId).style.color = "green";
|
||||
return 1;
|
||||
} else {
|
||||
document.getElementById(feedbackId).textContent = "❌ Incorrect, continue !";
|
||||
document.getElementById(feedbackId).style.color = "red";
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------
|
||||
// EXPORT
|
||||
// ---------------------------------------------------------
|
||||
return {
|
||||
init
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
|
|
|||
17
styles.html
Normal file
17
styles.html
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<style>
|
||||
.hanzi-canvas-container {
|
||||
display: flex !important;
|
||||
flex-direction: row !important;
|
||||
gap: 12px;
|
||||
align-items: flex-start;
|
||||
flex-wrap: nowrap !important;
|
||||
margin-bottom: 10px;
|
||||
border: 2px solid #000;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.hanzi-canvas-container > div {
|
||||
display: inline-flex !important;
|
||||
flex: 0 0 auto !important;
|
||||
}
|
||||
</style>
|
||||
Loading…
Reference in a new issue