Kleiner JavaScript Kurs
Funktionsplotter
Für einen Funktionsplotter benötigen wir auf der html - Seite (im body)
- 1 Canvas Zeichenfläche (id="myCanvas")
- 1 Input - Box für die zu plottende Funktion (id="fx")
- 2 Input Boxen für x-Min und x-Max (id="xmin" und id="xmax")
- 2 Input Boxen für y-Min und y-Max (id="ymin" und id="ymax")
- 1 Button zum starten des Plottens
<body>
<h1>Funktionsplotter</h1>
<div>y=f(x): <input type="text" id="fx" value="x*x"><br>
<button onclick="plotter();">plotten</button></div>
<canvas id="myCanvas" width="500" height="350" style="border:2px solid #000000;"></canvas>
<div>
ymax: <input type="text" id="ymax" value="100"><br>
xmin: <input type="text" id="xmin" value="-10">xmax: <input type="text" id="xmax" value="10"><br>
ymin: <input type="text" id="ymin" value="-10"><br>
</div>
</body>
Bevor wir die erste Funktion schreiben definieren wir alle wichtigen Variablen global:
var xmin, xmax;
var ymin, ymax;
var funktionFx;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var breite = canvas.width;
var hoehe = canvas.height;
Unser Hauptprogramm, dass mit dem Button gestartet wird heisst "plotter" und liest zunächst die Werte aller Input - Boxen ein:
function plotter(){
xmin=parseFloat(document.getElementById("xmin").value);
xmax=parseFloat(document.getElementById("xmax").value);
ymin=parseFloat(document.getElementById("ymin").value);
ymax=parseFloat(document.getElementById("ymax").value);
funktionFx=document.getElementById("fx").value;
}
Als erstes wird die Zeichenfläche gelöscht (mit einem Rechteck überschrieben). Wir verwenden dafür eine eigene Funktion, dann kann man das Löschen später bei Bedarf ausschalten um mehrere Funktionen in 1 Koordinatensystem zu plotten.
function canvasLoeschen(){
ctx.fillStyle = "yellow";
//ctx.clearRect(0,0,breite,hoehe);
ctx.fillRect(0,0,breite,hoehe);
}
Jetzt zeichnen wir das Koordinatensystem, also die x - und y - Achse. Am schwierigsten ist dabei die Umrechnung von x/y Werten in Canvas Koordinaten. Z.B. muss bei x-Min = -10 und x-Max = 10 die y-Achse im Canvas genau in der Mitte (bei einer Canvas - Breite von 500 Pixeln bei x = 250) gezeichnet werden.
function xyAchsen(){
ctx.beginPath();
//y-Achse;
var yAchseX=(breite/(xmax-xmin))*(-xmin);
ctx.moveTo(yAchseX, 0);
ctx.lineTo(yAchseX, hoehe);
ctx.stroke();
//x-Achse;
var xAchseY=(hoehe/(ymax-ymin))*(ymax);
ctx.moveTo(0, xAchseY);
ctx.lineTo(breite, xAchseY);
ctx.stroke();
}
Als Nächstes zeichnen wir die Funktion. Dafür durchlaufen wir mit einer for - Schleife die x - Werte von x-Min bis x-Max und berechnen für jeden x-Wert den entsprechenden y-Wert. Da die Funktion y=f(x) als Text vorliegt (aus dem Input-Feld "fx") verwenden wir die JavaScript-Funktion eval(), die einen Text als JavaScript Befehl ausführt.
y = eval(funktionFx);
Achtung:Die Funktion eval wird auf vielen Internet Servern gesperrt, da ihre Ausführung Hackern die Möglichkeit der Manipulation bietet. Auch die Funktion
var f=new Function("x","return "+ funktionFx);
y=f(x);
ist nicht sicher und wird bei vielen Servern geblockt. Deshalb eignet sich die Plotter Version mit eval() nur für den lokalen Einsatz. Eine Variante für den Einsatz auf einem Internet Server zeige ich weiter unten.
Wir können neben den Grundrechenarten +, -, *, /, % auch die Funktionen aus der Math-Bibliothek beim Plotten verwenden. Plotte doch mal
Math.sin(x) oder Math.sqrt(x) oder Math.pow(x, 4) oder auch Math.cos(x*x)
function funktionPlotten(){
xSchritt=breite/(xmax-xmin);
ySchritt=hoehe/(ymax-ymin);
schrittweite=(xmax-xmin)/100;
ctx.beginPath();
for(var x=xmin;x<=xmax;x+=schrittweite){
xc=(xSchritt*(-xmin)+xSchritt*x);
y=eval(funktionFx);
//var f=new Function("x","return "+ funktionFx);
//y=f(x);
yc=(hoehe+ySchritt*(ymin)-ySchritt*y);
if(x==xmin){ctx.moveTo(xc,yc);}
else{ctx.lineTo(xc,yc);}
}
ctx.stroke();
}
So könnte der Funktionsplotter (mit eval) aussehen: Funktions - Plotter
Damit der Plotter auch im Internet funktioniert, können wir z.B. die Funktion evaluate() der Bibliothek math.js einsetzen. Dazu müssen wir die Bibliothek zunächst im head einbinden:
<head>
<meta charset="utf-8">
<title>Funktionsplotter mit math.js</title>
<script src="js/math.js" type="text/javascript"></script>
</head>
Danach ersetzen wir die eval() Funktion durch die math.js Funktion evaluate():
//y=eval(funktionFx);
var scope={x};
y=math.evaluate(funktionFx, scope);
Angenehmer Nebeneffekt: jetzt funktioniert bei der Funktionseingabe auch: 5^2, sin(x), sqrt(x), tan(x), log(x), sin(x+pi), ... (s. mathjs.org); auch Konstante wie pi, e, usw können verwendet werden.
So könnte der Funktionsplotter mit math.js aussehen: Funktions - Plotter
Hier die HTML-Seite mit dem kompletten Programm
<!DOCTYPE html>
<html lang="de">
<head>
<meta charset="utf-8">
<title>Funktionsplotter</title>
<script src="js/math.js" type="text/javascript"></script>
</head>
<body>
<h1>Funktionsplotter</h1>
<div>y=f(x): <input type="text" id="fx" value="x*x"><br>
<button onclick="plotter();">plotten</button></div>
<canvas id="myCanvas" width="500" height="350" style="border:2px solid #000000;"></canvas>
<div>
ymax: <input type="text" id="ymax" value="100"><br>
xmin: <input type="text" id="xmin" value="-10">xmax: <input type="text" id="xmax" value="10"><br>
ymin: <input type="text" id="ymin" value="-10"><br>
</div>
</body>
<script>
var xmin, xmax;
var ymin, ymax;
var funktionFx;
var canvas = document.getElementById("myCanvas");
var ctx = canvas.getContext("2d");
var breite = canvas.width;
var hoehe = canvas.height;
function plotter(){
xmin=parseFloat(document.getElementById("xmin").value);
xmax=parseFloat(document.getElementById("xmax").value);
ymin=parseFloat(document.getElementById("ymin").value);
ymax=parseFloat(document.getElementById("ymax").value);
funktionFx=document.getElementById("fx").value;
canvasLoeschen();
xyAchsen();
funktionPlotten();
}
function canvasLoeschen(){
ctx.fillStyle = "yellow";
//ctx.clearRect(0,0,breite,hoehe);
ctx.fillRect(0,0,breite,hoehe);
}
function xyAchsen(){
ctx.beginPath();
//y-Achse;
var yAchseX=(breite/(xmax-xmin))*(-xmin);
ctx.moveTo(yAchseX, 0);
ctx.lineTo(yAchseX, hoehe);
ctx.stroke();
//x-Achse;
var xAchseY=(hoehe/(ymax-ymin))*(ymax);
ctx.moveTo(0, xAchseY);
ctx.lineTo(breite, xAchseY);
ctx.stroke();
}
function funktionPlotten(){
xSchritt=breite/(xmax-xmin);
ySchritt=hoehe/(ymax-ymin);
schrittweite=(xmax-xmin)/100;
ctx.beginPath();
for(var x=xmin;x<=xmax;x+=schrittweite){
xc=(xSchritt*(-xmin)+xSchritt*x);
//y=eval(funktionFx);
var scope={x};
y=math.evaluate(funktionFx, scope);
yc=(hoehe+ySchritt*(ymin)-ySchritt*y);
if(x==xmin){ctx.moveTo(xc,yc);}
else{ctx.lineTo(xc,yc);}
}
ctx.stroke();
}
</script>
</html>