首页 前端知识 【绘制“函数图”——html实现】

【绘制“函数图”——html实现】

2024-06-09 09:06:17 前端知识 前端哥 389 137 我要收藏

return new Segment(Math.pow(v1, v2));

}

};

}

//Class for special functions

function MathFunction(input) {

this.f = input;

if (!input) {

console.log(“Math function has no input.”);

}

this.solve = function (segment) {

var v = segment.coefficient;

if (this.f == “sin”) {

return new Segment(Math.sin(v));

} else if (this.f == “cos”) {

return new Segment(Math.cos(v));

} else if (this.f == “tan”) {

return new Segment(Math.tan(v));

} else if (this.f == “asin”) {

return new Segment(Math.asin(v));

} else if (this.f == “acos”) {

return new Segment(Math.acos(v));

} else if (this.f == “atan”) {

return new Segment(Math.atan(v));

} else if (this.f == “abs”) {

return new Segment(Math.abs(v));

}

};

}

//Class for a segment of math (a container)

function Segment(input) {

this.sections = [];

this.type = “section”;

this.operator = 0;

this.coefficient = 0;

this.mathFunction = 0;

this.variable = “”;

var removeBrackets = function (value) {

if (!value) return “”;

//While there are brackets around the string

while (value.substr(0, 1) == “(” && value.substr(value.length - 1, 1) == “)”) {

var openBrackets = 1;

//See if the end bracket closes the opening bracket or not

for (var i = 1; i < value.length && openBrackets > 0; i++) {

if (value.substr(i, 1) == “(”) openBrackets++;

if (value.substr(i, 1) == “)”) openBrackets–;

}

i -= 1;

//If it corresponds to different brackets, do nothing

if (openBrackets !== 0 || i != value.length - 1) {

break;

//Otherwise, remove the brackets, continue loop to see if there are more

} else {

value = value.substring(1, value.length - 1);

}

}

return value;

};

var findLast = function (operator, value) {

//Keep searching for the next last sign if the one found is within brackets

var inBrackets = true;

var index = -1;

if (operator != “^”) {

index = value.lastIndexOf(operator);

} else {

index = value.indexOf(operator); //Look for the first instead of last if it’s an exponent

}

var operators = “±/*^”;

while (inBrackets) {

var openBrackets = 0;

//Find how many brackets are opened or closed at a given point in the string

for (var i = 0; i < value.length; i++) {

if (value.substr(i, 1) == “(”) {

openBrackets++;

} else if (value.substr(i, 1) == “)”) {

openBrackets–;

}

if (i == index) {

//If no brackets are open (and if the operator is actually - and not just a minus sign), break the loop.

if ((openBrackets === 0 && (operator != “-” || (i > 0 && operators.indexOf(value.substr(i - 1, 1)) == -1) || i === 0)) || (openBrackets == 1 && operator == “(”)) {

inBrackets = false;

break;

//Otherwise, find the next operator, and loop through again to see if that one is in brackets

} else {

if (operator != “^”) {

index = value.substring(0, index).lastIndexOf(operator);

} else {

var nextOperator = value.substring(index + 1).indexOf(operator);

if (nextOperator == -1) {

index = -1;

} else {

index = (index + 1 + value.substring(index + 1).indexOf(operator));

}

}

}

}

}

//If no more operators are found, break the loop

if (index == -1) {

inBrackets = false;

}

}

return index;

};

var findLastTrig = function (trig, value) {

var matches = 0;

var index = -1;

var r = 0;

if (trig == “sin”) {

r = /(a)?sin/g;

} else if (trig == “cos”) {

r = /(a)?cos/g;

} else if (trig == “tan”) {

r = /(a)?tan/g;

} else {

return -1;

}

for (matches = r.exec(value); matches; matches = r.exec(value)) if (RegExp.$1 != “a”) index = matches.index;

var inBrackets = true;

while (inBrackets && index != -1) {

var openBrackets = 0;

//Find how many brackets are opened or closed at a given point in the string

for (var i = 0; i < value.length; i++) {

if (value.substr(i, 1) == “(”) {

openBrackets++;

} else if (value.substr(i, 1) == “)”) {

openBrackets–;

}

if (i == index) {

//If no brackets are open (and if the operator is actually - and not just a minus sign), break the loop.

if (openBrackets === 0) {

inBrackets = false;

break;

//Otherwise, find the next operator, and loop through again to see if that one is in brackets

} else {

var sub = value.substring(0, index);

index = -1;

for (matches = r.exec(sub); matches; matches = r.exec(sub)) if (RegExp.$1 != “a”) index = matches.index;

}

}

}

//If no more operators are found, break the loop

if (index == -1) {

inBrackets = false;

}

}

return index;

};

//Specifically for finding brackets that can be used for multiplication

var findMultiplicationBrackets = function (value) {

//Keep searching for the next last sign if the one found is within brackets

var inBracketsOpen = true;

var inBracketsClosed = true;

var indexOpen = -1;

var indexClosed = -1;

var operators = “±/*^sincostanabs”;

indexOpen = value.lastIndexOf(“(”);

indexClosed = value.lastIndexOf(“)”);

while (inBracketsOpen || inBracketsClosed) {

var openBrackets = 0;

//Find how many brackets are opened or closed at a given point in the string

for (var i = 0; i < value.length; i++) {

if (value.substr(i, 1) == “(”) {

openBrackets++;

} else if (value.substr(i, 1) == “)”) {

openBrackets–;

}

if (i == indexOpen && inBracketsOpen) {

if (openBrackets == 1 && i !== 0 && operators.indexOf(value.substr(i - 1, 1)) == -1) {

inBracketsOpen = false;

//Otherwise, find the next operator, and loop through again to see if that one is in brackets

} else {

indexOpen = value.substring(0, indexOpen).lastIndexOf(“(”);

}

}

if (i == indexClosed && inBracketsClosed) {

if (openBrackets === 0 && i < value.length - 1 && operators.indexOf(value.substr(i + 1, 1)) == -1) {

inBracketsClosed = false;

//Otherwise, find the next operator, and loop through again to see if that one is in brackets

} else {

indexClosed = value.substring(0, indexClosed).lastIndexOf(“)”);

}

}

}

//If no more operators are found, break the loop

if (indexOpen == -1) {

inBracketsOpen = false;

}

if (indexClosed == -1) {

inBracketsClosed = false;

}

}

if (indexClosed > indexOpen && indexClosed != -1) {

return indexClosed;

} else {

return indexOpen;

}

};

//Recursively solve children

this.solve = function (x) {

if (!x) x = 0;

if (this.type == “value”) {

return this;

} else if (this.type == “variable”) {

return new Segment(x);

} else if (this.type == “function”) {

return this.mathFunction.solve(this.sections[0].solve(x));

} else {

if (this.sections.length == 1) {

return this.sections[0].solve(x);

} else if (this.sections.length == 2) {

return this.operator.solve(this.sections[0].solve(x), this.sections[1].solve(x), x);

}

}

};

//Outputs the final answer

this.result = function (x) {

return this.solve(x).coefficient;

};

this.display = function (x) {

if (this.type == “value”) return this.coefficient;

if (this.type == “variable”) return “x”;

if (this.type == “function”) return this.mathFunction.f;

var str = “

”;

for (var i = 0; i < this.sections.length; i++) {

str += this.sections[i].display(x);

if (i === 0 && this.operator) {

str += “

” + this.operator.operator + “ ”;

}

}

str += "

= " + this.solve().coefficient + “ ”;

str += “”;

return str;

};

//constructor

if (input !== undefined) {

if (typeof (input) == “string”) {

//Remove excess whitespace

input = input.replace(/\s/g, “”);

//get rid of unnecessary brackets surrounding the section

input = removeBrackets(input);

//Find the last instance of each operator in the string

var addition = findLast(“+”, input);

var subtraction = findLast(“-”, input);

var division = findLast(“/”, input);

var exponent = findLast(“^”, input); //Find the first exponent, since those work in reverse

var bracket1 = findLast(“(”, input);

var sin = findLastTrig(“sin”, input);

var cos = findLastTrig(“cos”, input);

var tan = findLastTrig(“tan”, input);

var asin = findLast(“asin”, input);

var acos = findLast(“acos”, input);

var atan = findLast(“atan”, input);

var abs = findLast(“abs”, input);

var multiplication = findLast(“*”, input);

var multiplication2 = findMultiplicationBrackets(input); //Find brackets that are the same as multiplication

var functionMultiplication = -1;

if (sin > multiplication) functionMultiplication = sin;

if (cos > multiplication) functionMultiplication = cos;

if (tan > multiplication) functionMultiplication = tan;

if (asin > multiplication) functionMultiplication = asin;

if (acos > multiplication) functionMultiplication = acos;

if (atan > multiplication) functionMultiplication = atan;

if (abs > multiplication) functionMultiplication = abs;

//Push back each half of the equation into a section, in reverse order of operations

if (addition != -1 && (subtraction == -1 || addition > subtraction)) {

this.sections.push(new Segment(input.substring(0, addition)));

this.sections.push(new Segment(input.substring(addition + 1)));

this.operator = new Operator(“+”);

} else if (subtraction != -1) {

if (subtraction > 0) {

this.sections.push(new Segment(input.substring(0, subtraction)));

} else {

this.sections.push(new Segment(0));

}

this.sections.push(new Segment(input.substring(subtraction + 1)));

this.operator = new Operator(“-”);

} else if (functionMultiplication > 0 && functionMultiplication > multiplication && functionMultiplication > division) {

this.sections.push(new Segment(input.substring(0, functionMultiplication)));

this.sections.push(new Segment(input.substring(functionMultiplication)));

this.operator = new Operator(“*”);

} else if (multiplication2 != -1 && (division == -1 || multiplication > division) && (multiplication == -1 || multiplication2 > multiplication)) {

this.sections.push(new Segment(input.substring(0, multiplication2)));

this.sections.push(new Segment(input.substring(multiplication2)));

this.operator = new Operator(“*”);

} else if (multiplication != -1 && (division == -1 || multiplication > division)) {

this.sections.push(new Segment(input.substring(0, multiplication)));

this.sections.push(new Segment(input.substring(multiplication + 1)));

this.operator = new Operator(“*”);

} else if (division != -1) {

this.sections.push(new Segment(input.substring(0, division)));

this.sections.push(new Segment(input.substring(division + 1)));

this.operator = new Operator(“/”);

} else if (exponent != -1) {

this.sections.push(new Segment(input.substring(0, exponent)));

this.sections.push(new Segment(input.substring(exponent + 1)));

this.operator = new Operator(“^”);

} else if (sin != -1 && (cos == -1 || sin > cos) && (tan == -1 || sin > tan) && (asin == -1 || sin > asin) && (acos == -1 || sin > acos) && (atan == -1 || sin > atan) && (abs == -1 || sin > abs)) {

this.sections.push(new Segment(input.substring(sin + 3)));

this.mathFunction = new MathFunction(“sin”);

this.type = “function”;

} else if (cos != -1 && (tan == -1 || cos > tan) && (asin == -1 || cos > asin) && (acos == -1 || cos > acos) && (atan == -1 || cos > atan) && (abs == -1 || cos > abs)) {

this.sections.push(new Segment(input.substring(cos + 3)));

this.mathFunction = new MathFunction(“cos”);

this.type = “function”;

} else if (tan != -1 && (asin == -1 || tan > asin) && (acos == -1 || tan > acos) && (atan == -1 || tan > atan) && (abs == -1 || tan > abs)) {

this.sections.push(new Segment(input.substring(tan + 3)));

this.mathFunction = new MathFunction(“tan”);

this.type = “function”;

} else if (asin != -1 && (acos == -1 || asin > acos) && (atan == -1 || asin > atan) && (abs == -1 || asin > abs)) {

this.sections.push(new Segment(input.substring(asin + 4)));

this.mathFunction = new MathFunction(“asin”);

this.type = “function”;

} else if (acos != -1 && (atan == -1 || acos > atan) && (abs == -1 || acos > abs)) {

this.sections.push(new Segment(input.substring(acos + 4)));

this.mathFunction = new MathFunction(“acos”);

this.type = “function”;

} else if (atan != -1 && (abs == -1 || atan > abs)) {

this.sections.push(new Segment(input.substring(atan + 4)));

this.mathFunction = new MathFunction(“atan”);

this.type = “function”;

} else if (abs != -1) {

this.sections.push(new Segment(input.substring(abs + 3)));

this.mathFunction = new MathFunction(“abs”);

this.type = “function”;

} else if (bracket1 != -1) {

var openBrackets = 1;

for (var i = bracket1 + 1; i < input.length && openBrackets > 0; i++) {

if (input.substr(i, 1) == “(”) openBrackets++;

if (input.substr(i, 1) == “)”) openBrackets–;

}

if (openBrackets === 0) {

var bracket2 = i - 1;

if (bracket1 > 0) this.sections.push(new Segment(input.substring(0, bracket1)));

if (bracket2 - bracket1 != 1) this.sections.push(new Segment(input.substring(bracket1 + 1, bracket2)));

if (bracket2 != input.length - 1) this.sections.push(new Segment(input.substring(bracket2 + 1)));

this.operator = new Operator(“*”);

} else {

console.log("Brackets nesting error: " + input);

}

//If there are no operators, just push the input itself

} else {

var xLocation = input.toLowerCase().indexOf(“x”);

if (xLocation != -1) {

if (xLocation > 0) {

this.sections.push(new Segment(input.substring(0, xLocation)));

this.sections.push(new Segment(“x”));

this.operator = new Operator(“*”);

} else {

this.variable = “x”;

this.type = “variable”;

}

} else {

this.coefficient = parseFloat(input);

this.type = “value”;

}

}

} else if (typeof (input) == “number”) {

this.coefficient = input;

this.type = “value”;

}

} else {

console.log(“Segment has no input.”);

}

}

//One point on a graph

function Point(x, y) {

this.x = x || 0;

this.y = y || 0;

}

//MathFunction to create graphs

function Graph(value, width, height, rangeX, rangeY) {

var autoRange = false;

//Default params

if (rangeX === undefined) {

rangeX = 10;

}

if (rangeY === undefined) {

autoRange = true;

}

//Properties

this.expression = new Segment(value);

this.points = [];

this.canvas = document.createElement(“canvas”);

this.canvas.width = width || 800;

this.canvas.height = height || 800;

this.min = undefined;

this.max = undefined;

this.x1 = 0 - Math.abs(rangeX);

this.x2 = 0 + Math.abs(rangeX);

this.y1 = 0 - Math.abs(rangeY);

this.y2 = 0 + Math.abs(rangeY);

var startMouse = new Point(0, 0);

var mousePos = new Point(0, 0);

var timer = 0;

var stage = 0;

var img = 0;

var magnitudeX = 0;

var magnitudeY = 0;

//Gets minimum y value in the set of points

this.getMin = function () {

if (this.min === undefined) {

if (this.points.length > 0) {

var min = this.points[0].y;

for (var i = 1; i < this.points.length; i++) {

if (this.points[i].y < min) min = this.points[i].y;

}

this.min = min;

return min;

} else {

return 0;

}

} else {

return this.min;

}

};

//Gets maximum y value in the set of points

this.getMax = function () {

if (this.max === undefined) {

if (this.points.length > 0) {

var max = this.points[0].y;

for (var i = 1; i < this.points.length; i++) {

if (this.points[i].y > max) max = this.points[i].y;

}

this.max = max;

return max;

} else {

return 0;

}

} else {

return this.max;

}

};

//Updates the points and graph

this.update = function () {

var accuracy = (this.x2 - this.x1) / this.canvas.width;

this.points = [];

for (var i = this.x1; i <= this.x2; i += accuracy) {

this.points.push(new Point(i, this.expression.result(i)));

}

if (autoRange) {

if (this.getMax() - this.getMin() > 100000) {

this.y1 = -100;

this.y2 = 100;

} else {

this.y1 = this.getMin() - 5;

this.y2 = this.getMax() + 5;

}

autoRange = false;

}

magnitudeX = Math.ceil(Math.log(this.x2 - this.x1));

magnitudeY = Math.ceil(Math.log(this.y2 - this.y1));

this.redraw();

};

var drawAxes = function (_x1, _x2, _y1, _y2, redraw) {

stage.strokeStyle = “#7FFF00”;

stage.fillStyle = “#7FFF00”;

var limit = 0;

var i = 0;

//Draw the y axis if it is in the view

if (0 >= _x1 - 30 && 0 <= _x2 + 30) {

stage.lineWidth = 2;

stage.beginPath();

stage.moveTo(this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width, 0);

stage.lineTo(this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width, this.canvas.height);

stage.closePath();

stage.stroke();

stage.textAlign = “right”;

stage.textBaseline = “middle”;

stage.lineWidth = 1;

limit = (Math.abs(_y2) > Math.abs(_y1)) ? Math.abs(_y2) : Math.abs(_y1);

for (i = 0; i <= limit; i += Math.pow(10, Math.floor(Math.log(_y2 - _y1) / Math.LN10)) / 4) {

if (i === 0) continue;

if (i <= _y2 + 50) {

if (redraw || (i >= this.y2 - 50)) {

stage.beginPath();

stage.moveTo(this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width - 5, this.canvas.height - ((i - _y1) / (_y2 - _y1)) * this.canvas.height);

stage.lineTo(this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width + 5, this.canvas.height - ((i - _y1) / (_y2 - _y1)) * this.canvas.height);

stage.closePath();

stage.stroke();

stage.fillText(“” + (Math.round(i * 100) / 100), this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width - 8, this.canvas.height - ((i - _y1) / (_y2 - _y1)) * this.canvas.height);

}

}

if (i >= _y1 - 50) {

if (redraw || (-i <= this.y1 + 50)) {

stage.beginPath();

stage.moveTo(this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width - 5, this.canvas.height - ((-i - _y1) / (_y2 - _y1)) * this.canvas.height);

stage.lineTo(this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width + 5, this.canvas.height - ((-i - _y1) / (_y2 - _y1)) * this.canvas.height);

stage.closePath();

stage.stroke();

stage.fillText(“” + (Math.round(-i * 100) / 100), this.canvas.width / 2 - (((_x2 + _x1) / 2) / (_x2 - _x1)) * this.canvas.width - 8, this.canvas.height - ((-i - _y1) / (_y2 - _y1)) * this.canvas.height);

}

}

}

}

//Draw the x axis if it is in the view

if (0 >= _y1 - 50 && 0 <= _y2 + 50) {

stage.lineWidth = 2;

stage.beginPath();

stage.moveTo(0, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height);

stage.lineTo(this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height);

stage.closePath();

stage.stroke();

stage.textAlign = “center”;

stage.textBaseline = “top”;

stage.lineWidth = 1;

limit = (Math.abs(_x2) > Math.abs(_x1)) ? Math.abs(_x2) : Math.abs(_x1);

for (i = 0; i <= limit; i += Math.pow(10, Math.floor(Math.log(_x2 - _x1) / Math.LN10)) / 4) {

if (i === 0) continue;

if (i <= _x2 + 50) {

if (redraw || (i >= this.x2 - 50)) {

stage.beginPath();

stage.moveTo(((i - _x1) / (_x2 - _x1)) * this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height - 5);

stage.lineTo(((i - _x1) / (_x2 - _x1)) * this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height + 5);

stage.closePath();

stage.stroke();

stage.fillText(“” + (Math.round(i * 100) / 100), ((i - _x1) / (_x2 - _x1)) * this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height + 8);

}

}

if (i >= _x1 - 50) {

if (redraw || (-i <= this.x1 + 50)) {

stage.beginPath();

stage.moveTo(((-i - _x1) / (_x2 - _x1)) * this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height - 5);

stage.lineTo(((-i - _x1) / (_x2 - _x1)) * this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height + 5);

stage.closePath();

stage.stroke();

stage.fillText(“” + (Math.round(-i * 100) / 100), ((-i - _x1) / (_x2 - _x1)) * this.canvas.width, this.canvas.height / 2 + (((_y2 + _y1) / 2) / (_y2 - _y1)) * this.canvas.height + 8);

}

}

}

}

}.bind(this);

//Updates the canvas

this.redraw = function () {

if (this.points.length > 1) {

stage.clearRect(0, 0, this.canvas.width, this.canvas.height);

stage.lineCap = “round”;

var offsetY = -this.y1;

drawAxes(this.x1, this.x2, this.y1, this.y2, true);

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可领取了。

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!**

[外链图片转存中…(img-yttjTobn-1712562980751)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

核心竞争力,怎么才能提高呢?

成年人想要改变生活,逆转状态?那就开始学习吧~

万事开头难,但是程序员这一条路坚持几年后发展空间还是非常大的,一切重在坚持。

为了帮助大家更好更高效的准备面试,特别整理了《前端工程师面试手册》电子稿文件。

前端面试题汇总

JavaScript

性能

linux

前端资料汇总

完整版PDF资料免费分享,只需你点赞支持,动动手指点击此处就可领取了。

前端工程师岗位缺口一直很大,符合岗位要求的人越来越少,所以学习前端的小伙伴要注意了,一定要把技能学到扎实,做有含金量的项目,这样在找工作的时候无论遇到什么情况,问题都不会大。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/11625.html
标签
评论
发布的文章
大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!