javascript - How to plot the graph based on equation using js - Stack Overflow

I need to plot a graph in a canvas. But how can I use an algebra equation as input, and based on the eq

I need to plot a graph in a canvas. But how can I use an algebra equation as input, and based on the equation, draw the curve, using javascript?

For example:

x2+5y=250

The equation plots a graph with both positive and negative values.

<!DOCTYPE html>
<html>
    <head>
        <title>Interactive Line Graph</title>
        <script src=".6.1.min.js"></script>
        <script>
            var graph;
            var xPadding = 30;
            var yPadding = 30;
            
            var data = { values:[
                { X: "1", Y: 15 },
                { X: "2", Y: 35 },
                { X: "3", Y: 60 },
                { X: "4", Y: 14 },
                { X: "5", Y: 20 },
                { X: "6", Y: 95 },
            ]};

            // Returns the max Y value in our data list
            function getMaxY() {
                var max = 0;
                
                for(var i = 0; i < data.values.length; i ++) {
                    if(data.values[i].Y > max) {
                        max = data.values[i].Y;
                    }
                }
                
                max += 10 - max % 10;
                return max;
            }
            
            // Return the x pixel for a graph point
            function getXPixel(val) {
                return ((graph.width() - xPadding) / data.values.length) * val + (xPadding * 1.5);
            }
            
            // Return the y pixel for a graph point
            function getYPixel(val) {
                return graph.height() - (((graph.height() - yPadding) / getMaxY()) * val) - yPadding;
            }

            $(document).ready(function() {
                graph = $('#graph');
                var c = graph[0].getContext('2d');            
                
                c.lineWidth = 2;
                c.strokeStyle = '#333';
                c.font = 'italic 8pt sans-serif';
                c.textAlign = "center";
                
                // Draw the axises
                c.beginPath();
                c.moveTo(xPadding, 0);
                c.lineTo(xPadding, graph.height() - yPadding);
                c.lineTo(graph.width(), graph.height() - yPadding);
                c.stroke();
                
                // Draw the X value texts
                for(var i = 0; i < data.values.length; i ++) {
                    c.fillText(data.values[i].X, getXPixel(i), graph.height() - yPadding + 20);
                }
                
                // Draw the Y value texts
                c.textAlign = "right"
                c.textBaseline = "middle";
                
                for(var i = 0; i < getMaxY(); i += 10) {
                    c.fillText(i, xPadding - 10, getYPixel(i));
                }
                
                c.strokeStyle = '#f00';
                
                // Draw the line graph
                c.beginPath();
                c.moveTo(getXPixel(0), getYPixel(data.values[0].Y));
                for(var i = 1; i < data.values.length; i ++) {
                    c.lineTo(getXPixel(i), getYPixel(data.values[i].Y));
                }
                c.stroke();
                
                // Draw the dots
                c.fillStyle = '#333';
                
                for(var i = 0; i < data.values.length; i ++) {  
                    c.beginPath();
                    c.arc(getXPixel(i), getYPixel(data.values[i].Y), 4, 0, Math.PI * 2, true);
                    c.fill();
                }
            });
        </script>
    </head>
    <body>
        <canvas id="graph" width="200" height="150">   
        </canvas> 
    </body>
</html>

I need to plot a graph in a canvas. But how can I use an algebra equation as input, and based on the equation, draw the curve, using javascript?

For example:

x2+5y=250

The equation plots a graph with both positive and negative values.

<!DOCTYPE html>
<html>
    <head>
        <title>Interactive Line Graph</title>
        <script src="http://ajax.aspnetcdn./ajax/jQuery/jquery-1.6.1.min.js"></script>
        <script>
            var graph;
            var xPadding = 30;
            var yPadding = 30;
            
            var data = { values:[
                { X: "1", Y: 15 },
                { X: "2", Y: 35 },
                { X: "3", Y: 60 },
                { X: "4", Y: 14 },
                { X: "5", Y: 20 },
                { X: "6", Y: 95 },
            ]};

            // Returns the max Y value in our data list
            function getMaxY() {
                var max = 0;
                
                for(var i = 0; i < data.values.length; i ++) {
                    if(data.values[i].Y > max) {
                        max = data.values[i].Y;
                    }
                }
                
                max += 10 - max % 10;
                return max;
            }
            
            // Return the x pixel for a graph point
            function getXPixel(val) {
                return ((graph.width() - xPadding) / data.values.length) * val + (xPadding * 1.5);
            }
            
            // Return the y pixel for a graph point
            function getYPixel(val) {
                return graph.height() - (((graph.height() - yPadding) / getMaxY()) * val) - yPadding;
            }

            $(document).ready(function() {
                graph = $('#graph');
                var c = graph[0].getContext('2d');            
                
                c.lineWidth = 2;
                c.strokeStyle = '#333';
                c.font = 'italic 8pt sans-serif';
                c.textAlign = "center";
                
                // Draw the axises
                c.beginPath();
                c.moveTo(xPadding, 0);
                c.lineTo(xPadding, graph.height() - yPadding);
                c.lineTo(graph.width(), graph.height() - yPadding);
                c.stroke();
                
                // Draw the X value texts
                for(var i = 0; i < data.values.length; i ++) {
                    c.fillText(data.values[i].X, getXPixel(i), graph.height() - yPadding + 20);
                }
                
                // Draw the Y value texts
                c.textAlign = "right"
                c.textBaseline = "middle";
                
                for(var i = 0; i < getMaxY(); i += 10) {
                    c.fillText(i, xPadding - 10, getYPixel(i));
                }
                
                c.strokeStyle = '#f00';
                
                // Draw the line graph
                c.beginPath();
                c.moveTo(getXPixel(0), getYPixel(data.values[0].Y));
                for(var i = 1; i < data.values.length; i ++) {
                    c.lineTo(getXPixel(i), getYPixel(data.values[i].Y));
                }
                c.stroke();
                
                // Draw the dots
                c.fillStyle = '#333';
                
                for(var i = 0; i < data.values.length; i ++) {  
                    c.beginPath();
                    c.arc(getXPixel(i), getYPixel(data.values[i].Y), 4, 0, Math.PI * 2, true);
                    c.fill();
                }
            });
        </script>
    </head>
    <body>
        <canvas id="graph" width="200" height="150">   
        </canvas> 
    </body>
</html>
[i am add one example ploter in math.js ] i want to how to full screen plot the graph and mouse are cilck in graph any point to show the details in x&y value.so how to change please help me.

Share Improve this question edited Dec 3, 2016 at 3:45 Ivan Chaer 7,0901 gold badge40 silver badges49 bronze badges asked Aug 20, 2016 at 10:08 Prasanth KlrPrasanth Klr 1311 gold badge3 silver badges9 bronze badges 5
  • can u precise what u want to do? pls simplify a bit your "question" – kolboc Commented Aug 20, 2016 at 10:11
  • please help me how to programming this method – Prasanth Klr Commented Aug 20, 2016 at 10:25
  • 2 you may find that webpage helpful: javascripter/faq/plotafunctiongraph.htm – kolboc Commented Aug 20, 2016 at 10:29
  • @kolboc how to change the programming in long equation type in input but your refer page small equation only plot so how to change please send the any example code. – Prasanth Klr Commented Aug 20, 2016 at 10:40
  • Any one can help me – Prasanth Klr Commented Aug 20, 2016 at 11:01
Add a ment  | 

2 Answers 2

Reset to default 4

Parsing linear equation.

Or maybe it is the Parsing of the equation that the question is about.

This answer shows how to parse a simple linear equation.

User inputs x2+5y=230 and you need to solve and plot for y for f(x) which would be the function function(x) { return (3 * x -230) / -5; }

Will assume the equation is always in the same form with x and y and some scalars and constants scalar * x + const + scalar * y = const

Define the rules

Rules

  • Only x and y will be considered variables.
  • A term is a scalar and a variable 2x or a constant +1.
  • All additional characters will be ignored including *,/,%
  • Numbers can have decimal places. Valid numbers 1 +1 0.2 -2 10e5
  • Scalars must be adjacent to variables 3y2 bees 6y 3y-2 stays as is.

Parsing

To parse a equation we must break it down into unambiguous easy to manipulate units. In this case a unit I call a term and will have 3 properties.

  • scalar A number
  • variable the name of the variable x,y or null for constants
  • side which side of the equation the term is Left or right

An example equation

2x + 2 + 3y = 4x - 1y

First parsed to create terms

// shorthand not code
{2,x,true; // true is for left
{2,null,true; // null is a constant
{3,y,true;
{4,x,false;
{-1,y,false;

Once all the terms are parsed then the equation is solved by summing all the terms for x, y and constants and moving everything to the left flipping the sign of any values on the right.

sumX = 2 + -4; //as 4x is on the right it bees negative 
sumY = 3 + 1;
const = 2;

Making the equation

 -2x + 4y + 2 = 0

Then move the y out to the right and divide the left by its scalar.

 -2x + 2 = 4y
 (-2x + 2)/-4 = y

The result is a function that we can call from javascript will the value of x and get the value of y.

 function(x){ return (-2 * x + 2) / 4; }

The Parser

The following function parses and returns a function for input equation for x. That function then use to plot the points in the demo below.

function parseEquation(input){
    // Important that white spaces are removed first
    input = input.replace(/\s+/g,""); // remove whitespaces
    input = input.replace(/([\-\+])([xy])/g,"$11$2"); // convert -x -y or +x +y to -1x -1y or +1x +1y
                                                      // just to make the logic below a little simpler
    var newTerm = () => {term = { val : null, scalar : 1, left : left, };} // create a new term
    var pushTerm = () => {terms.push(term); term = null;} // push term and null current
    // regExp [xy=] gets "x","y", or "="" or [\-\+]??[0-9\.]+  gets +- number with decimal
    var reg =/[xy=]|[\-\+]??[0-9\.eE]+/g;   // regExp to split the input string into parts
    var parts = input.match(reg);           // get all the parts of the equation
    var terms = [];     // an array of all terms parsed
    var term = null;    // Numbers as constants and variables with scalars are terms
    var left = true;    // which side of equation a term is
    parts.forEach( p=> { 
        if (p === "x" || p === "y") {
            if (term !== null && term.val !== null) {  // is the variable defined
                 pushTerm(); // yes so push to the stack and null 
            }
            if (term === null) { newTerm(); }  // do we need a new term?
            term.val = p;
        } else if( p === "=") {                // is it the equals sign
            if (!left) { throw new SyntaxError("Unxpected `=` in equation."); }
            if (term === null) { throw new SyntaxError("No left hand side of equation."); }// make sure that there is a left side
            terms.push(term);   // push the last left side term onto the stack
            term = null;
            left = false;       // everything on the right from here on in
        } else {                // all that is left are numbers (we hope)
            if (isNaN(p)){ throw new SyntaxError("Unknown value '"+p+"' in equation");  }//check that there is a number
            if (term !== null && (p[0] === "+" || p[0] === "-")) { // check if number is a new term
                 pushTerm();    // yes so push to the stack and null 
            }
            if (term === null) { newTerm(); } // do we need a new term?
            term.scalar *= Number(p);         // set the scalar to the new value
        }
    });

    if (term !== null) { // there may or may not be a term left to push to the stack
        pushTerm();
    }
    // now simplify the equation getting the scalar for left and right sides . x on left y on right
    var scalarX = 0;
    var scalarY = 0
    var valC = 0; // any constants 
    terms.forEach(t => {
        t.scalar *= !t.left ? -1 : 1; // everything on right is negative
        if (t.val === "y") {
            scalarY += -t.scalar; // reverse sign
        } else if (t.val === "x") {
            scalarX += t.scalar; 
        } else {
            valC += t.scalar;
        }
    })
    // now build the code string for the equation to solve for x and return y
    var code = "return (" + scalarX + " * x  + (" + valC + ")) / "+scalarY +";\n";
    var equation = new Function("x",code); // create the function
    return equation;
}

The following usage examples are all the same equation

var equation = parseEquation("x2+5y+x=230");
var y = equation(10); // get y for x = 10;

equation = parseEquation("x2+x=230-5y");
equation = parseEquation("x2+x-30=200-2y-3y");
equation = parseEquation("200- 2y-3y = x2+x-30");
equation = parseEquation("200-2y- 3y - x2-x+30=0");
equation = parseEquation("100.0 + 100-2y- 3y - x2-x+30=0");
equation = parseEquation("1e2 + 10E1-2y- 3y - x2-x+30=0");

Demo

I have added it to the code in the answer markE has already given. (hope you don't mind markE)

function plot(equation) {
    var graph;
    var xPadding = 30;
    var yPadding = 30;

    var data = {
        values : [{
                X : "1",
                Y : 15
            }, {
                X : "2",
                Y : 35
            }, {
                X : "3",
                Y : 60
            }, {
                X : "4",
                Y : 14
            }, {
                X : "5",
                Y : 20
            }, {
                X : "6",
                Y : -30
            },
        ]
    };

    // Returns the max Y value in our data list
    function getMaxY() {
        var max = 0;

        for (var i = 0; i < data.values.length; i++) {
            if (data.values[i].Y > max) {
                max = data.values[i].Y;
            }
        }

        max += 10 - max % 10;
        return max;
    }
    var scaleA = 1.4;
    // Return the x pixel for a graph point
    function getXPixel(val) {
        return ((graph.width() / scaleA  - xPadding) / data.values.length) * val + (xPadding * 1.5);
    }

    // Return the y pixel for a graph point
    function getYPixel(val) {
        return graph.height() / scaleA  - (((graph.height() / scaleA  - yPadding) / getMaxY()) * val) - yPadding;
    }

    graph = $('#graph');
    var c = graph[0].getContext('2d');
    c.clearRect(0,0,graph[0].width,graph[0].height);
    c.lineWidth = 2;
    c.strokeStyle = '#333';
    c.font = 'italic 8pt sans-serif'; 
    c.textAlign = "center";

    // Draw the axises
    c.beginPath();
    c.moveTo(xPadding, 0);
    c.lineTo(xPadding, graph.height() / scaleA  - yPadding);
    c.lineTo(graph.width(), graph.height() / scaleA  - yPadding);
    c.stroke();

    // Draw the X value texts
    for (var i = 0; i < data.values.length; i++) {
        c.fillText(data.values[i].X, getXPixel(i), graph.height() / scaleA  - yPadding + 20);
    }

    // Draw the Y value texts
    c.textAlign = "right"
        c.textBaseline = "middle";

    for (var i = 0; i < getMaxY(); i += 10) {
        c.fillText(i, xPadding - 10, getYPixel(i));
    }

    c.strokeStyle = '#f00';

    // Draw the line graph
    c.beginPath();
    c.moveTo(getXPixel(0), getYPixel(equation(0)));
    for (var i = 1; i < data.values.length; i++) {
        c.lineTo(getXPixel(i), getYPixel(equation(i)));
    }
    c.stroke();

    // Draw the dots
    c.fillStyle = '#333';

    for (var i = 0; i < data.values.length; i++) {
        c.beginPath();
        c.arc(getXPixel(i), getYPixel(equation(i)), 4, 0, Math.PI * 2, true);
        c.fill();
    }
}
var codeText = "";
function parseEquation(input){
    // Important that white spaces are removed first
    input = input.replace(/\s+/g,""); // remove whitespaces
    input = input.replace(/([\-\+])([xy])/g,"$11$2"); // convert -x -y or +x +y to -1x -1y or +1x +1y
                                                      // just to make the logic below a little simpler
    var newTerm = () => {term = { val : null, scalar : 1, left : left, };} // create a new term
    var pushTerm = () => {terms.push(term); term = null;} // push term and null current
    // regExp [xy=] gets "x","y", or "="" or [\-\+]??[0-9\.]+  gets +- number with decimal
    var reg =/[xy=]|[\-\+]??[0-9\.eE]+/g;   // regExp to split the input string into parts
    var parts = input.match(reg);           // get all the parts of the equation
    var terms = [];     // an array of all terms parsed
    var term = null;    // Numbers as constants and variables with scalars are terms
    var left = true;    // which side of equation a term is
    parts.forEach(p=>{ 
         if (p === "x" || p === "y") {
            if (term !== null && term.val !== null) {  // is the variable defined
                 pushTerm(); // yes so push to the stack and null 
            }
            if (term === null) { newTerm(); }  // do we need a new term?
            term.val = p;
        } else if( p === "="){                // is it the equals sign
            if (!left) { throw new SyntaxError("Unxpected `=` in equation."); }
            if (term === null) { throw new SyntaxError("No left hand side of equation."); }// make sure that there is a left side
            terms.push(term);   // push the last left side term onto the stack
            term = null;
            left = false;       // everything on the right from here on in
        } else {                // all that is left are numbers (we hope)
            if (isNaN(p)){ throw new SyntaxError("Unknown value '"+p+"' in equation");  }//check that there is a number
            if (term !== null && (p[0] === "+" || p[0] === "-")){ // check if number is a new term
                 pushTerm();    // yes so push to the stack and null 
            }
            if(term === null){ newTerm(); } // do we need a new term?
            term.scalar *= Number(p);       // set the scalar to the new value
        }
    });
    
    if(term !== null){// there may or may not be a term left to push to the stack
        pushTerm();
    }
    // now simplify the equation getting the scalar for left and right sides . x on left y on right
    var scalarX = 0;
    var scalarY = 0
    var valC = 0; // any constants 
    terms.forEach(t => {
        t.scalar *= !t.left ? -1 : 1; // everything on right is negative
        if (t.val === "y") {
            scalarY += -t.scalar; // reverse sign
        } else if (t.val === "x") {
            scalarX += t.scalar; 
        } else {
            valC += t.scalar;
        }
    })
    // now build the code string for the equation to solve for x and return y
    var code = "return (" + scalarX + " * x  + (" + valC + ")) / "+scalarY +";\n";
    codeText = code;
    var equation = new Function("x",code); // create the function
    
    return equation;
}


function parseAndPlot(){
  var input = eqInput.value;
  try{
     var equation = parseEquation(input);
     plot(equation);
     error.textContent ="Plot of "+input+ " as 'function(x){ "+codeText+"}'";      
  }catch(e){
     error.textContent = "Error parsing equation. " + e.message;      
  }
  
} 


var button = document.getElementById("plot");
var eqInput = document.getElementById("equation-text");
var error = document.getElementById("status");
button.addEventListener("click",parseAndPlot);
parseAndPlot();
<script src="https://ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="graph" width="200" height="150"></canvas> <br>
Enter a linear equation : <input id="equation-text" value="x2 + 5y = 250" type="text"></input><input id="plot" value="plot" type=button></input><div id="status"></div>

I think I understand what you're asking...

Your existing code automatically puts your y-axis at the bottom of the canvas so negative y-values will be off-canvas.

Quick solution

The quickest solution is to divide graph.height()/2 so that your graph has it's y-axis near center-canvas. This leaves room for negative values.

Better solution

The better solution is to redesign your graphing system to allow for solutions in all axis directions.

Refactored code showing the quick solution:

I leave it to you to extend the y-axis labels in the negative direction (if desired)

var graph;
var xPadding = 30;
var yPadding = 30;

var data = { values:[
  { X: "1", Y: 15 },
  { X: "2", Y: 35 },
  { X: "3", Y: 60 },
  { X: "4", Y: 14 },
  { X: "5", Y: 20 },
  { X: "6", Y: -30 },
]};

  // Returns the max Y value in our data list
  function getMaxY() {
  var max = 0;

  for(var i = 0; i < data.values.length; i ++) {
  if(data.values[i].Y > max) {
            max = data.values[i].Y;
           }
}

max += 10 - max % 10;
return max;
}

// Return the x pixel for a graph point
function getXPixel(val) {
  return ((graph.width()/2 - xPadding) / data.values.length) * val + (xPadding * 1.5);
}

// Return the y pixel for a graph point
function getYPixel(val) {
  return graph.height()/2 - (((graph.height()/2 - yPadding) / getMaxY()) * val) - yPadding;
}

graph = $('#graph');
var c = graph[0].getContext('2d');            

c.lineWidth = 2;
c.strokeStyle = '#333';
c.font = 'italic 8pt sans-serif';
c.textAlign = "center";

// Draw the axises
c.beginPath();
c.moveTo(xPadding, 0);
c.lineTo(xPadding, graph.height()/2 - yPadding);
c.lineTo(graph.width(), graph.height()/2 - yPadding);
c.stroke();

// Draw the X value texts
for(var i = 0; i < data.values.length; i ++) {
  c.fillText(data.values[i].X, getXPixel(i), graph.height()/2 - yPadding + 20);
}

// Draw the Y value texts
c.textAlign = "right"
c.textBaseline = "middle";

for(var i = 0; i < getMaxY(); i += 10) {
  c.fillText(i, xPadding - 10, getYPixel(i));
}

c.strokeStyle = '#f00';

// Draw the line graph
c.beginPath();
c.moveTo(getXPixel(0), getYPixel(data.values[0].Y));
for(var i = 1; i < data.values.length; i ++) {
  c.lineTo(getXPixel(i), getYPixel(data.values[i].Y));
}
c.stroke();

// Draw the dots
c.fillStyle = '#333';

for(var i = 0; i < data.values.length; i ++) {  
  c.beginPath();
  c.arc(getXPixel(i), getYPixel(data.values[i].Y), 4, 0, Math.PI * 2, true);
  c.fill();
}
<script src="https://ajax.googleapis./ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="graph" width="200" height="300"></canvas> 

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744153461a4560745.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信