<iframe src="https://jsxgraph.org/share/iframe/cannon-ball-simulation" style="border: 1px solid black; overflow: hidden; width: 550px; aspect-ratio: 55 / 65;" name="JSXGraph example: Cannon ball simulation" allowfullscreen ></iframe>
<div id="board-0-wrapper" class="jxgbox-wrapper " style="width: 100%; "> <div id="board-0" class="jxgbox" style="aspect-ratio: 2 / 1; width: 100%;" data-ar="2 / 1"></div> </div> <script type = "text/javascript"> /* This example is licensed under a Creative Commons Attribution 4.0 International License. https://creativecommons.org/licenses/by/4.0/ Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits. */ const BOARDID = 'board-0'; var board = JXG.JSXGraph.initBoard(BOARDID, { boundingbox: [0, 10, 20, 0], showCopyright: false, showNavigation: false }), bottom = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/1/13/Cannon_bottom.png', [0, 0.3], [2, 1] ], { layer: 1, fixed: true }), muzzle = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/e/e4/Cannon_muzzle.png', [0, 1.05], [3, 0.75] ], { layer: 0, fixed: true }), shootButton, resetButton, rot, rp, cp, cc, cannonball, cbanim, solution, velocity, animTime = function() { return 3000; }, fAngle = function() { return Math.atan2(cp.Y() - rp.Y(), cp.X() - rp.X()); }, fSolution = function(x) { var b = fAngle(), g = 9.81 / 2; return Math.tan(b) * (x - cannonball.X()) - g * (Math.pow((x - cannonball.X()) / (velocity.Value() * Math.cos(b)), 2)) + cannonball.Y(); }, fAnim = function(t) { var i = Math.floor(solution.points.length * t / animTime()) /*3 + 17*t/animTime()*/ , s = NaN; if (JXG.exists(solution.points[i]) && solution.points[i].usrCoords[2] > 0) { s = solution.points[i].usrCoords.slice(1); } return s; }, shoot = function() { cannonball.setAttribute({ visible: false }); cbanim.setAttribute({ visible: true }); cbanim.moveTo([cannonball.X(), cannonball.Y()]); cbanim.moveAlong(fAnim, animTime(), { callback: function() { // this is executed when the animation is finished } }); }, resetFunc = function() { board.stopAllAnimation(); cbanim.setAttribute({ visible: false }); cannonball.setAttribute({ visible: true }); }; board.options.animationDelay = 50; velocity = board.create('slider', [ [1, 9.5], [6, 9.5], [0, 5, 15] ], { name: 'Velocity' }); cp = board.create('point', [1.4, 1.4], { fixed: true, visible: false }); cc = board.create('circle', [cp, 1.25], { visible: false }); rp = board.create('glider', [0, 1.4, cc], { withLabel: false, showInfobox: false, color: 'black' }); rot = board.create('transform', [fAngle, cp], { type: 'rotate' }); rot.bindTo(muzzle); cannonball = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true }); cbanim = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true, visible: false }); rot.bindTo(cannonball); solution = board.create('plot', [fSolution, function() { return cannonball.X(); }, 20], { visible: true, doAdvancedPlot: false }); board.create('text', [1, 7, () => 'angle = ' + (180 * fAngle() / Math.PI).toFixed(1) + '°'], {fontSize: 20}); shootButton = board.create('button', [10, 9.5, 'Shoot', shoot]); resetButton = board.create('button', [12, 9.5, 'Reset', resetFunc]); </script>
/* This example is licensed under a Creative Commons Attribution 4.0 International License. https://creativecommons.org/licenses/by/4.0/ Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits. */ const BOARDID = 'your_div_id'; // Insert your id here! var board = JXG.JSXGraph.initBoard(BOARDID, { boundingbox: [0, 10, 20, 0], showCopyright: false, showNavigation: false }), bottom = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/1/13/Cannon_bottom.png', [0, 0.3], [2, 1] ], { layer: 1, fixed: true }), muzzle = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/e/e4/Cannon_muzzle.png', [0, 1.05], [3, 0.75] ], { layer: 0, fixed: true }), shootButton, resetButton, rot, rp, cp, cc, cannonball, cbanim, solution, velocity, animTime = function() { return 3000; }, fAngle = function() { return Math.atan2(cp.Y() - rp.Y(), cp.X() - rp.X()); }, fSolution = function(x) { var b = fAngle(), g = 9.81 / 2; return Math.tan(b) * (x - cannonball.X()) - g * (Math.pow((x - cannonball.X()) / (velocity.Value() * Math.cos(b)), 2)) + cannonball.Y(); }, fAnim = function(t) { var i = Math.floor(solution.points.length * t / animTime()) /*3 + 17*t/animTime()*/ , s = NaN; if (JXG.exists(solution.points[i]) && solution.points[i].usrCoords[2] > 0) { s = solution.points[i].usrCoords.slice(1); } return s; }, shoot = function() { cannonball.setAttribute({ visible: false }); cbanim.setAttribute({ visible: true }); cbanim.moveTo([cannonball.X(), cannonball.Y()]); cbanim.moveAlong(fAnim, animTime(), { callback: function() { // this is executed when the animation is finished } }); }, resetFunc = function() { board.stopAllAnimation(); cbanim.setAttribute({ visible: false }); cannonball.setAttribute({ visible: true }); }; board.options.animationDelay = 50; velocity = board.create('slider', [ [1, 9.5], [6, 9.5], [0, 5, 15] ], { name: 'Velocity' }); cp = board.create('point', [1.4, 1.4], { fixed: true, visible: false }); cc = board.create('circle', [cp, 1.25], { visible: false }); rp = board.create('glider', [0, 1.4, cc], { withLabel: false, showInfobox: false, color: 'black' }); rot = board.create('transform', [fAngle, cp], { type: 'rotate' }); rot.bindTo(muzzle); cannonball = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true }); cbanim = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true, visible: false }); rot.bindTo(cannonball); solution = board.create('plot', [fSolution, function() { return cannonball.X(); }, 20], { visible: true, doAdvancedPlot: false }); board.create('text', [1, 7, () => 'angle = ' + (180 * fAngle() / Math.PI).toFixed(1) + '°'], {fontSize: 20}); shootButton = board.create('button', [10, 9.5, 'Shoot', shoot]); resetButton = board.create('button', [12, 9.5, 'Reset', resetFunc]);
<jsxgraph width="100%" aspect-ratio="2 / 1" title="Cannon ball simulation" description="This construction was copied from JSXGraph examples database: BTW HERE SHOULD BE A GENERATED LINKuseGlobalJS="false"> /* This example is licensed under a Creative Commons Attribution 4.0 International License. https://creativecommons.org/licenses/by/4.0/ Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits. */ var board = JXG.JSXGraph.initBoard(BOARDID, { boundingbox: [0, 10, 20, 0], showCopyright: false, showNavigation: false }), bottom = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/1/13/Cannon_bottom.png', [0, 0.3], [2, 1] ], { layer: 1, fixed: true }), muzzle = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/e/e4/Cannon_muzzle.png', [0, 1.05], [3, 0.75] ], { layer: 0, fixed: true }), shootButton, resetButton, rot, rp, cp, cc, cannonball, cbanim, solution, velocity, animTime = function() { return 3000; }, fAngle = function() { return Math.atan2(cp.Y() - rp.Y(), cp.X() - rp.X()); }, fSolution = function(x) { var b = fAngle(), g = 9.81 / 2; return Math.tan(b) * (x - cannonball.X()) - g * (Math.pow((x - cannonball.X()) / (velocity.Value() * Math.cos(b)), 2)) + cannonball.Y(); }, fAnim = function(t) { var i = Math.floor(solution.points.length * t / animTime()) /*3 + 17*t/animTime()*/ , s = NaN; if (JXG.exists(solution.points[i]) && solution.points[i].usrCoords[2] > 0) { s = solution.points[i].usrCoords.slice(1); } return s; }, shoot = function() { cannonball.setAttribute({ visible: false }); cbanim.setAttribute({ visible: true }); cbanim.moveTo([cannonball.X(), cannonball.Y()]); cbanim.moveAlong(fAnim, animTime(), { callback: function() { // this is executed when the animation is finished } }); }, resetFunc = function() { board.stopAllAnimation(); cbanim.setAttribute({ visible: false }); cannonball.setAttribute({ visible: true }); }; board.options.animationDelay = 50; velocity = board.create('slider', [ [1, 9.5], [6, 9.5], [0, 5, 15] ], { name: 'Velocity' }); cp = board.create('point', [1.4, 1.4], { fixed: true, visible: false }); cc = board.create('circle', [cp, 1.25], { visible: false }); rp = board.create('glider', [0, 1.4, cc], { withLabel: false, showInfobox: false, color: 'black' }); rot = board.create('transform', [fAngle, cp], { type: 'rotate' }); rot.bindTo(muzzle); cannonball = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true }); cbanim = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true, visible: false }); rot.bindTo(cannonball); solution = board.create('plot', [fSolution, function() { return cannonball.X(); }, 20], { visible: true, doAdvancedPlot: false }); board.create('text', [1, 7, () => 'angle = ' + (180 * fAngle() / Math.PI).toFixed(1) + '°'], {fontSize: 20}); shootButton = board.create('button', [10, 9.5, 'Shoot', shoot]); resetButton = board.create('button', [12, 9.5, 'Reset', resetFunc]); </jsxgraph>
// Define the id of your board in BOARDID var board = JXG.JSXGraph.initBoard(BOARDID, { boundingbox: [0, 10, 20, 0], showCopyright: false, showNavigation: false }), bottom = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/1/13/Cannon_bottom.png', [0, 0.3], [2, 1] ], { layer: 1, fixed: true }), muzzle = board.create('image', ['https://jsxgraph.uni-bayreuth.de/wiki/images/e/e4/Cannon_muzzle.png', [0, 1.05], [3, 0.75] ], { layer: 0, fixed: true }), shootButton, resetButton, rot, rp, cp, cc, cannonball, cbanim, solution, velocity, animTime = function() { return 3000; }, fAngle = function() { return Math.atan2(cp.Y() - rp.Y(), cp.X() - rp.X()); }, fSolution = function(x) { var b = fAngle(), g = 9.81 / 2; return Math.tan(b) * (x - cannonball.X()) - g * (Math.pow((x - cannonball.X()) / (velocity.Value() * Math.cos(b)), 2)) + cannonball.Y(); }, fAnim = function(t) { var i = Math.floor(solution.points.length * t / animTime()) /*3 + 17*t/animTime()*/ , s = NaN; if (JXG.exists(solution.points[i]) && solution.points[i].usrCoords[2] > 0) { s = solution.points[i].usrCoords.slice(1); } return s; }, shoot = function() { cannonball.setAttribute({ visible: false }); cbanim.setAttribute({ visible: true }); cbanim.moveTo([cannonball.X(), cannonball.Y()]); cbanim.moveAlong(fAnim, animTime(), { callback: function() { // this is executed when the animation is finished } }); }, resetFunc = function() { board.stopAllAnimation(); cbanim.setAttribute({ visible: false }); cannonball.setAttribute({ visible: true }); }; board.options.animationDelay = 50; velocity = board.create('slider', [ [1, 9.5], [6, 9.5], [0, 5, 15] ], { name: 'Velocity' }); cp = board.create('point', [1.4, 1.4], { fixed: true, visible: false }); cc = board.create('circle', [cp, 1.25], { visible: false }); rp = board.create('glider', [0, 1.4, cc], { withLabel: false, showInfobox: false, color: 'black' }); rot = board.create('transform', [fAngle, cp], { type: 'rotate' }); rot.bindTo(muzzle); cannonball = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true }); cbanim = board.create('point', [3, 1.4], { size: 8, strokeColor: 'black', fillColor: 'gray', withLabel: false, fixed: true, visible: false }); rot.bindTo(cannonball); solution = board.create('plot', [fSolution, function() { return cannonball.X(); }, 20], { visible: true, doAdvancedPlot: false }); board.create('text', [1, 7, () => 'angle = ' + (180 * fAngle() / Math.PI).toFixed(1) + '°'], {fontSize: 20}); shootButton = board.create('button', [10, 9.5, 'Shoot', shoot]); resetButton = board.create('button', [12, 9.5, 'Reset', resetFunc]);
This example is licensed under a Creative Commons Attribution 4.0 International License. Please note you have to mention The Center of Mobile Learning with Digital Technology in the credits.