A reta tangente a uma função, num ponto, pode ser calculada, de forma aproximada, a partir da reta que passa em (x,f(x)) e (x2,f(x2)), onde x2=x+dx, sendo dx um valor muito pequeno.
No exemplo abaixo, o utilizador pode inserir a expressão da função (com sintaxe de Javascript), assim como os valores de x e dx.
O declive da reta tangente é calculado como m=(f(x2)-f(x))/(x2-x), e a ordenada da origem é obtida pela expressão b=f(x)-m*x.
O gráfico é configurável: é possível alterar a escala de x (xEscala), a escala de y (yEscala), a frequência de traços em cada eixo (xMarcas e yMarcas), assim como a posição da origem do referencial (xr e yr).
Visualização:
Código html
<!DOCTYPE html> <html> <head> <title>Gráfico - reta tangente</title> <meta charset="iso-8859-1"> <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"> </script> <script type="text/javascript" src="codigo.js"></script> <script type="text/javascript" src="Grafico.js"></script> <link type="text/css" href="estilos.css" rel="stylesheet" /> </head> <body onload="init();"> <h3>Gráfico - reta tangente</h3> <canvas width="400" height="300" id="cvs"></canvas> <form> <div> xEscala <meter id="xEsc" min="1" max="100" value=""></meter> <input type="text" id="vxEsc" size="3" value="" onblur="cInput('xEsc');" /> </div> <div> yEscala <meter id="yEsc" min="1" max="100" value=""></meter> <input type="text" id="vyEsc" size="3" value="" onblur="cInput('yEsc');" /> </div> <div> xMarcas <meter id="xMrc" min="1" max="50" value=""></meter> <input type="text" id="vxMrc" size="3" value="" onblur="cInput('xMrc');" /> </div> <div> yMarcas <meter id="yMrc" min="1" max="50" value=""></meter> <input type="text" id="vyMrc" size="3" value="" onblur="cInput('yMrc');" /> </div> <div> xr <meter id="xRef" min="0" max="400" value=""></meter> <input type="text" id="vxRef" size="3" value="" onblur="cInput('xRef');" /> </div> <div> yr <meter id="yRef" min="0" max="300" value=""></meter> <input type="text" id="vyRef" size="3" value="" onblur="cInput('yRef');" /> </div> <div> Função: <input type="text" id="func" size="30" value="4*Math.log(x)" /> </div> <div> x: <input type="text" id="xtan" size="10" value="5" /> </div> <div> dx: <input type="text" id="xdelta" size="10" value="0.2" /> </div> <input type="button" value="Redesenha" onclick="redesenha();" /> </form> </body> </html>
Ficheiro codigo.js
var g; function init() { g = new Grafico(); g.inicia(); document.getElementById("xEsc").value = g.xEscala; document.getElementById("vxEsc").value = g.xEscala; document.getElementById("yEsc").value = g.yEscala; document.getElementById("vyEsc").value = g.yEscala; document.getElementById("xMrc").value = g.xMarcas; document.getElementById("vxMrc").value = g.xMarcas; document.getElementById("yMrc").value = g.yMarcas; document.getElementById("vyMrc").value = g.yMarcas; document.getElementById("xRef").value = g.xr; document.getElementById("vxRef").value = g.xr; document.getElementById("yRef").value = g.yr; document.getElementById("vyRef").value = g.yr; $("#xEsc").click(cMeter); $("#yEsc").click(cMeter); $("#xMrc").click(cMeter); $("#yMrc").click(cMeter); $("#xRef").click(cMeter); $("#yRef").click(cMeter); } function redesenha() { g.xEscala = eval(document.getElementById("vxEsc").value); g.yEscala = eval(document.getElementById("vyEsc").value); g.xMarcas = eval(document.getElementById("vxMrc").value); g.yMarcas = eval(document.getElementById("vyMrc").value); g.xr = eval(document.getElementById("vxRef").value); g.yr = eval(document.getElementById("vyRef").value); g.inicia(); } function cMeter(e) { var id = $(this).attr("id"); var met = document.getElementById(id); var max = met.getAttribute("max"); var min = met.getAttribute("min"); var offx = e.clientX - met.getBoundingClientRect().left; opac = offx / $('#'+id).width(); var pct = Math.round((max-min) * opac); $('#'+id).val(pct); $('#v'+id).val(pct); } function cInput(id) { var valor = $('#v'+id).val(); $('#'+id).val(valor); }
Ficheiro Grafico.js
/* Classe Grafico */ function Grafico() { // Coordenadas da origem do referencial visível this.xr = 50; this.yr = 260; // Escalas dos eixos this.xEscala = 15; this.yEscala = 15; // Espaçamento entre marcas this.xMarcas = 5; this.yMarcas = 2; var canvas = document.getElementById("cvs"); var larg = canvas.getAttribute("width"); var alt = canvas.getAttribute("height"); var ctx = canvas.getContext("2d"); // Criar imagens de 1x1 pixels var ptPreto = ctx.createImageData(1,1); ptPreto.data[0] = 0; // Componente vermelha ptPreto.data[1] = 0; // Componente verde ptPreto.data[2] = 0; // Componente azul ptPreto.data[3] = 255; // Componente alfa var ptVermelho = ctx.createImageData(1,1); ptVermelho.data[0] = 255;// Componente vermelha ptVermelho.data[1] = 0; // Componente verde ptVermelho.data[2] = 0; // Componente azul ptVermelho.data[3] = 255; // Componente alfa var ptVerde = ctx.createImageData(1,1); ptVerde.data[0] = 0; // Componente vermelha ptVerde.data[1] = 128; // Componente verde ptVerde.data[2] = 0; // Componente azul ptVerde.data[3] = 255; // Componente alfa var ptAzul = ctx.createImageData(1,1); ptAzul.data[0] = 0; // Componente vermelha ptAzul.data[1] = 0; // Componente verde ptAzul.data[2] = 255; // Componente azul ptAzul.data[3] = 255; // Componente alfa this.inicia = inicia; function inicia() { ctx.fillStyle = "white"; ctx.beginPath(); ctx.rect(0,0,larg,alt); ctx.fill(); ctx.fillStyle = "white"; ctx.beginPath(); ctx.rect(0,0,larg,alt); ctx.fill(); ctx.strokeStyle = "black"; ctx.beginPath(); ctx.rect(0,0,larg,alt); ctx.stroke(); // Colocar os dois eixos xx, yy poeLinha(0,this.yr,larg,this.yr,"black"); poeLinha(this.xr,0,this.xr,alt,"black"); // Preparação para escrever o texto na horizontal ctx.fillStyle = "black"; ctx.font = "12px 'Courier'"; ctx.textAlign = "center"; ctx.textBaseline = "top"; // Colocar a escala nos eixos // Eixo x positivo for(var n=0; n*this.xEscala+this.xr<larg; n+=this.xMarcas) { poeLinha(n*this.xEscala+this.xr,this.yr-5,n*this.xEscala+this.xr,this.yr+5,"black"); ctx.fillText(n, n*this.xEscala+this.xr, this.yr+10); } // Eixo x negativo for(var n=0; n*this.xEscala+this.xr>0; n-=this.xMarcas) { poeLinha(n*this.xEscala+this.xr,this.yr-5,n*this.xEscala+this.xr,this.yr+5,"black"); ctx.fillText(n, n*this.xEscala+this.xr, this.yr+10); } // Preparação para escrever o texto na horizontal ctx.textAlign = "right"; ctx.textBaseline = "middle"; // Eixo y negativo for(var n=0; n*this.yEscala+this.yr<alt; n+=this.yMarcas) { poeLinha(this.xr-5,n*this.yEscala+this.yr,this.xr+5,n*this.yEscala+this.yr,"black"); ctx.fillText(-n, this.xr-10, n*this.yEscala+this.yr); } // Eixo y positivo for(var n=0; n*this.yEscala+this.yr>0; n-=this.yMarcas) { poeLinha(this.xr-5,n*this.yEscala+this.yr,this.xr+5,n*this.yEscala+this.yr,"black"); ctx.fillText(-n, this.xr-10, n*this.yEscala+this.yr); } // Desenhar a função var y; for(var i=0; i<larg; i++) { x = i/this.xEscala; y = f(x); if(!isFinite(y)) continue; this.poePonto(ptPreto, x, y); } // Calcular o declive var xt = eval( document.getElementById("xtan").value ); var dx = eval( document.getElementById("xdelta").value ); if(xt==undefined || dx==undefined) return; yt = f(xt); yt2 = f(xt+dx); var m = (yt2-yt)/dx; // Calcular ordenada na origem var b = yt - m * xt; // Desenhar tangente for(var i=0; i<larg; i++) { x = i/this.xEscala; y = m * x + b; if(!isFinite(y)) continue; this.poePonto(ptPreto, x, y); } } function f(x) { var ff = document.getElementById("func").value; if(ff=="") return 0; var y = eval(ff); return y; } this.poePonto = poePonto; function poePonto(pt, x, y) { var xe = x * this.xEscala + this.xr; var ye = -y * this.yEscala + this.yr; ctx.putImageData(pt, xe, ye); } this.poeLinha = poeLinha; function poeLinha(x1,y1,x2,y2,cor) { ctx.strokeStyle = cor; ctx.beginPath(); ctx.moveTo(x1,y1); ctx.lineTo(x2,y2); ctx.stroke(); } }
Ficheiro estilos.css
meter { width: 200px; }