JSXGraph logo
JSXGraph
JSXGraph share

Share

Cannon ball simulation
QR code
<iframe 
    src="http://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>
This code has to
<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>

Cannon ball simulation

// 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]);

license

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.