In the following code, particularly around lines 62-68. I am trying to have the equations appear on the JavaScript canvas with proper math typography using MathJax on the screen.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Math Game</title>
<style>
body {
font-family: Arial, sans-serif;
text-align: center;
}
canvas {
background-color: #f0f0f0;
display: block;
margin: 0 auto;
}
.shake {
animation: shake 0.5s;
}
@keyframes shake {
0% { transform: translate(1px, 1px) rotate(5deg); }
10% { transform: translate(-1px, -2px) rotate(-5deg); }
20% { transform: translate(-3px, 0px) rotate(5deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(5deg); }
50% { transform: translate(-1px, 2px) rotate(-5deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-5deg); }
80% { transform: translate(-1px, -1px) rotate(5deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-5deg); }
}
#userForm {
display: none;
}
</style>
</head>
<body>
<h1>Math Game</h1>
<p>Solve the questions before they reach the bottom!</p>
<canvas id="gameCanvas" width="600" height="600"></canvas>
<p>Score: <span id="score">0</span></p>
<p>Grade: <span id="grade">0.0</span></p>
<div id="userForm">
<label for="fullname">Full Name:</label>
<input type="text" id="fullname"><br>
<label for="email">Email:</label>
<input type="email" id="email"><br>
<button onclick="startGame()">Start Game</button>
</div>
<input type="hidden" id="finalScore" value="">
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.7/MathJax.js?config=TeX-MML-AM_CHTML" async></script>
<script>
const canvas = document.getElementById("gameCanvas");
const ctx = canvas.getContext("2d");
const scoreDisplay = document.getElementById("score");
const gradeDisplay = document.getElementById("grade");
const userForm = document.getElementById("userForm");
const questions = [
{ question: "\(3(x+2)\)", answer: '3x+6' },
{ question: "$frac{x}{2}+frac{x}{2}$", answer: 'x' },
{ question: "6times 2", answer: '12' },
{ question: '6times 2', answer: '12' },
{ question: "9 + 10", answer: '19' }
];
let score = 0;
let currentQuestionIndex = 0;
let currentQuestion = null;
let y = 0;
let speed = 1;
let gamePaused = true;
function drawQuestion() {
if (gamePaused) return;
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.font = "20px Arial";
ctx.fillStyle = "black";
ctx.fillText(currentQuestion.question, canvas.width / 2 - 50, y);
y += speed;
if (y > canvas.height) {
score -= 5;
updateScore();
shakeCanvas();
nextQuestion();
}
}
function nextQuestion() {
currentQuestionIndex = (currentQuestionIndex + 1) % questions.length;
currentQuestion = questions[currentQuestionIndex];
y = 0;
}
function updateScore() {
scoreDisplay.textContent = score;
let grade = 0.0;
if (score >= 200) {
grade = 4.0;
alert("Your score is 4.0. Submitting your score.");
document.getElementById("finalScore").value = grade;
submitScore();
return;
} else if (score >= 150) {
grade = 3.0;
} else if (score >= 100) {
grade = 2.0;
} else if (score >= 50) {
grade = 1.0;
}
gradeDisplay.textContent = grade;
document.getElementById("finalScore").value = grade;
if ([50, 100, 150, 200].includes(score)) {
gamePaused = true;
let continueGame = confirm(`Your score is ${grade}. Do you want to continue to the next level?`);
if (!continueGame) {
submitScore();
} else {
gamePaused = false;
currentQuestion = questions[currentQuestionIndex];
setInterval(drawQuestion, 30);
}
}
}
function checkAnswer(input) {
const userAnswer = input.value.replace(/s/g, '').toLowerCase();
const correctAnswer = currentQuestion.answer.replace(/s/g, '').toLowerCase();
const isCorrect = evaluateExpression(userAnswer) === evaluateExpression(correctAnswer);
if (isCorrect) {
score += 10;
} else {
score -= 5;
shakeCanvas();
}
updateScore();
input.value = "";
nextQuestion();
}
function evaluateExpression(expression) {
const sanitizedExpression = expression.replace(/x/g, '*');
try {
return eval(sanitizedExpression);
} catch (error) {
console.error(`Error evaluating expression: ${expression}`, error);
return NaN;
}
}
function submitScore() {
const fullname = document.getElementById("fullname").value;
const email = document.getElementById("email").value;
const finalScore = document.getElementById("finalScore").value;
google.script.run.AddRecord(fullname, email, finalScore);
alert("Thank you " + fullname + " for submitting your assignment.");
window.location.reload();
}
function startGame() {
const fullname = document.getElementById("fullname").value;
const email = document.getElementById("email").value;
if (fullname && email) {
userForm.style.display = "none";
gamePaused = false;
currentQuestion = questions[currentQuestionIndex];
setInterval(drawQuestion, 30);
} else {
alert("Please enter your full name and email.");
}
}
function shakeCanvas() {
canvas.classList.add('shake');
setTimeout(() => {
canvas.classList.remove('shake');
}, 500);
}
document.addEventListener("DOMContentLoaded", () => {
userForm.style.display = "block";
const input = document.createElement("input");
input.type = "text";
input.placeholder = "Your answer";
document.body.appendChild(input);
input.addEventListener("keyup", function(event) {
if (event.keyCode === 13) {
checkAnswer(input);
}
});
});
</script>
</body>
</html>
I have had success with the following but some of the formatting is different. How do I get this to work with the code above? I feel like it’s something really minor that I am missing that is not allowing it to convert properly to MathJax.
<html lang="en">
<style>
.shake {
background: lightblue;
position: relative;
animation: earthQuake 2s ;
}
@keyframes earthQuake {
0% { transform: translate(1px, 1px) rotate(5deg); }
10% { transform: translate(-1px, -2px) rotate(-5deg); }
20% { transform: translate(-3px, 0px) rotate(5deg); }
30% { transform: translate(3px, 2px) rotate(0deg); }
40% { transform: translate(1px, -1px) rotate(5deg); }
50% { transform: translate(-1px, 2px) rotate(-5deg); }
60% { transform: translate(-3px, 1px) rotate(0deg); }
70% { transform: translate(3px, 1px) rotate(-5deg); }
80% { transform: translate(-1px, -1px) rotate(5deg); }
90% { transform: translate(1px, 2px) rotate(0deg); }
100% { transform: translate(1px, -2px) rotate(-5deg); }
}
</style>
<!---------Example of shaking <div class="shake">Idk</div> -------------->
<head>
<meta name="google-signin-client_id" content="YOUR_CLIENT_ID.apps.googleusercontent.com">
</head>
<body>
<div id="my-signin2"></div>
<script>
function onSuccess(googleUser) {
console.log('Logged in as: ' + googleUser.getBasicProfile().getName());
}
function onFailure(error) {
console.log(error);
}
function renderButton() {
gapi.signin2.render('my-signin2', {
'scope': 'profile email',
'width': 240,
'height': 50,
'longtitle': true,
'theme': 'dark',
'onsuccess': onSuccess,
'onfailure': onFailure
});
}
</script>
<script src="https://apis.google.com/js/platform.js?onload=renderButton" async defer></script>
</body>
<!-----------Horizontal Scrollbar at Top----------------->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
.center {
margin-left: auto;
margin-right: auto;
}
.scrollmenu {
background-color: #000;
overflow: auto;
white-space: nowrap;
}
.scrollmenu a {
display: inline-block;
color: white;
text-align: center;
padding: 14px;
text-decoration: none;
}
.scrollmenu a:hover {
background-color: #777;
}
</style>
</head>
<body>
<div class="scrollmenu">
<a href="#homepage">Online Math Assessment</a>
</div>
<h2>Math Assessment</h2>
</body>
<!------------------------Side Scrollbar----------------->
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
body {
font-family: "Lato", sans-serif;
}
.sidebar {
height: 100%;
width: 0;
position: fixed;
z-index: 1;
top: 0;
left: 0;
background-color: #111;
overflow-x: hidden;
transition: 0.5s;
padding-top: 60px;
}
.sidebar a {
padding: 10px 10px 10px 30px;
text-decoration: none;
font-size: 20px;
color: #818181;
display: block;
transition: 0.1s;
}
.sidebar a:hover {
color: #f1f1f1;
}
.sidebar .closebtn {
position: absolute;
top: 0;
right: 25px;
font-size: 36px;
margin-left: 50px;
}
.openbtn {
font-size: 20px;
cursor: pointer;
background-color: #111;
color: white;
padding: 10px 15px;
border: none;
}
.openbtn:hover {
background-color: #444;
}
#main {
transition: margin-left .5s;
padding: 16px;
}
/* On smaller screens, where height is less than 450px, change the style of the sidenav (less padding and a smaller font size) */
@media screen and (max-height: 450px) {
.sidebar {padding-top: 15px;}
.sidebar a {font-size: 18px;}
}
</style>
<script type="text/javascript" src="//code.createjs.com/createjs-2013.09.25.combined.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-AMS-MML_HTMLorMML"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<!----jspreviewformathjax cdn---->
<script type="text/javascript" async src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-mml-chtml.js"></script>
<!---the following two scripts are delimeters from http://docs.mathjax.org/en/latest/web/start.html -------->
<script>
MathJax = {
tex: {inlineMath: [['$', '$'], ['\(', '\)']],
packages: {'[+]': ['input']}},
packages: {'[+]': ['cancel']},
chtml: {scale: 1.1},
svg: {scale: 1.1},
startup: {
ready() {
const Configuration = MathJax._.input.tex.Configuration.Configuration;
const CommandMap = MathJax._.input.tex.SymbolMap.CommandMap;
const TEXCLASS = MathJax._.core.MmlTree.MmlNode.TEXCLASS;
new CommandMap('input', {input: 'Input'}, {
Input(parser, name) {
const xml = parser.create('node', 'XML');
const id = parser.GetBrackets(name, '');
const w = parser.GetBrackets(name, '5em');
const value = parser.GetArgument(name);
xml.setXML(MathJax.startup.adaptor.node('input', {
id: id, value: value, style: {width: w}, xmlns: 'http://www.w3.org/1999/xhtml'
}), MathJax.startup.adaptor);
xml.getSerializedXML = function () {
return this.adaptor.outerHTML(this.xml) + '</input>';
}
parser.Push(
parser.create('node', 'TeXAtom', [
parser.create('node', 'semantics', [
parser.create('node', 'annotation-xml', [
xml
], {encoding: 'application/xhtml+xml'})
])
], {texClass: TEXCLASS.ORD})
);
}
});
Configuration.create('input', {handler: {macro: ['input']}});
MathJax.startup.defaultReady();
}
}
};
</script>
<script id="MathJax-script" defer src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"></script>
<script id="MathJax-script" async
src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js">
</script>
$textbf{User Information}$ </br>
</br>
</br>
<label>Full Name:</label><input type="text" id="fullname">
<label>Email:</label><input type="email" id="email">
</br>
</br>
<input type="hidden" id="blankemail" value="">
<input type="hidden" id="score" value="">
</br>
</br>
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
text-align: center;
}
th, td {
padding: 15px;
text-align: center;
}
</style>
<!----------------------------- Combined ------------------->
<audio id="myAudio">
<source src="https://docs.google.com/uc?export=open&id=11FJxgkEdjWz23luAe2IhwNLB8WkBGff9" type="audio/mp3">
preload="auto"
src="file.mp3#t=00:00:00.2"
oncanplaythrough="this.play();">
</audio>
<style>
#gameCanvas {
background-color: lightyellow;
}
</style>
<div class="canvasHolder1">
<div id="eqn1"> begin{align*}f(x)&=frac{3x^2+4x^2}{9}\
&=frac{input[q1j][1em]{}x^2}{9}
end{align*}</div>
<div id="eqn2"> (3^input[q2j][1em]{}=9implies x=2)
</div>
<button id="myBtn" onclick="correct()">Button</button>
<script>
//score does not have id score here
var score=1;
function addInput(qnj) {
var x = document.createElement("INPUT");
//Not sure why not working here.
var qn=qnj.slice(0,-1);
x.setAttribute("id", qn);
x.setAttribute("type", "hidden");
x.setAttribute("value", document.getElementById(qnj).value);
document.body.appendChild(x);
}
function correct(){javascript:alert('Correct. '+'Your Score is ' + score);
score+=1;
//addinput gives q1
addInput("q1j");
addInput("q2j");
document.getElementById('eqn1').remove();
document.getElementById('eqn2').remove();
}
for(i=1; i++; i<=k){
const quest=[];
quest[i]= document.getElementById(`q${i}j`);
quest[i].addEventListener("keyup", function(event) {
if (event.keyCode == 13 && document.getElementById(`q${i}j`).value==6) {
document.getElementById("myBtn").click();
event.preventDefault();
}
});
}
</script>
<canvas id="gameCanvas" width="600" height="600">Not supported</canvas>
<script type="text/javascript">
var water = document.getElementById("myAudio");
var value = document.getElementById("qj1");
var stage = new createjs.Stage("gameCanvas");
var domElement = new createjs.DOMElement(document.getElementById("eqn1"));
var obj=[]
var k=2;
// k = Number of Questions
for (let i = 1; i <= k; i++) {
obj[i] = new createjs.DOMElement(document.getElementById(`eqn${i}`));
}
var gravity = 1;
//setTimeout(doSomething, 3000);
//function doSomething() {
//do whatever you want here
//}
can = document.getElementById("gameCanvas");
for (let i = 1; i <= k; i++) {
obj[i].x = Math.random()* can.width;
obj[i].y = 0.5;}
var speedY=5;
var speedX=5;
var floor=5;
function startGame() {
stage.addChild(obj[1]);
setTimeout(delay, 2000);
function delay(){
stage.addChild(obj[2]);
}
this.frameNo = 0;
createjs.Ticker.addEventListener("tick", handleTick);
function handleTick(event) {
dropRight();
hitRightWall();
hitLeftWall();
ground();
stage.update();
}
}
function dropRight(){
for (let i = 1; i <= k; i++) {
if (obj[i].x<can.width && speedX==5 && obj[i].y<can.height && speedY==5){
obj[i].x += 1;
obj[i].y +=3;
}
}
}
function hitRightWall(){
for (let i = 1; i <= k; i++) {
if ((obj[i].x>=can.width || speedX==-5)&& obj[i].y<can.height && speedY==5){
obj[i].x -= 2;
obj[i].y +=3;
speedX=-5;}
}
}
function hitLeftWall(){
for (let i = 1; i <= k; i++) {
if (obj[i].x==0 && speedX==-5 && obj[i].y<can.height && speedY==5){
speedX=5;}
}
}
function ground(){
for (let i = 1; i <= k; i++) {
if (obj[i].y>=can.height || speedY==0){
//Adding water drop sound the or operator continues to repeat sound which is the reason for the extra if here
if(obj[i].y>=can.height){
water.play();
document.getElementById("gameCanvas").className = "shake"; }
speedY=0;
obj[i].y -=3;
obj[i].x +=1;
document.getElementById(`eqn${i}`).remove();
}
}
}
</script>
<body onload="startGame();">
<div >
<canvas>This browser or document mode doesn't support canvas object.</canvas>
</div>
</body>
<!--------------------------------Start of APP-------------------->
<head>
<base target="_top">
<script>
function AddRow(){
var fullname = document.getElementById("fullname").value;
var email = document.getElementById("email").value;
var blankemail = document.getElementById("blankemail").value;
var score = document.getElementById("score").value;
var array = [];
// i<= Number of Questions
for (let i = 1; i <= 2; i++) {
array[i-1]=document.getElementById(`q${i}`).value;
}
google.script.run.AddRecord(fullname, email, blankemail, score,...array);
alert("Thank you "+fullname+" for submitting your assignment.");
}
</script>
</head>
<body>
<input type="button" value="Submit" onclick="AddRow()">
</body>
</br>
</br>
</br>
</br>
</html>