如何将String转换为数学函数一次?

时间:2016-12-22 13:06:18

标签: javascript html canvas

我想构建类似于desmos的东西,你可以在画布中绘制图形然后移动它。

到目前为止我已经成功了,但唯一剩下的就是用户输入。

使用<input type="text">标签我希望用户编写例如:

"5x + 2"

结果应为:

var f = 5*x + 2;

我搜索了很多方法来执行此操作,我发现的唯一内容是JavaScript中的一些Maths库和eval()函数。最后一个非常有用,因为我可以用图中的x值替换x,它可以用来构建函数的图形。问题是当我想移动图表时它会滞后很多,所以这不是最好的主意。

我确信它会滞后,因为eval()函数必须每次为画布的每个x值转换字符串大约40-50次。

我想要实现的是将字符串转换为Math函数一次,然后使用它。

有可能吗?任何人都可以请帮助

编辑1 : 这是我的功能:

function f (pixelX) {
    var x = getCoordX (pixelX);

    var f = 2 * x + 2;

    return getPixelY(f);
}

2 个答案:

答案 0 :(得分:4)

回答你的问题(即使这不能解决你的问题)。

你可以这样做。

var myString = "5 * x + 2";
var f = Function("x", "return " + myString);

这会从function创建string。第一个参数是第一个参数的名称x,第二个参数是函数的主体(return语句);

然后你可以这样称呼: f(3),结果为17

请注意,您必须在等式中编写乘法,例如5 * x,而不是5x

这样您只需将字符串评估为函数一次,然后您可以使用不同的参数多次调用它。

问题不在于eval需要很长时间才能计算,但是重新绘制画布非常昂贵。尝试限制绘制数量或仅在requestAnimationFrame回调中调用绘制函数,这样浏览器只有在准备好时才会重绘画布。

答案 1 :(得分:3)

您可以使用eval,但每个浏览器的JavaScript引擎可能会有不同的行为。

这是一个简单的查找和替换:

&#13;
&#13;
function solveForX(equation, xValue) {
  var expanded = equation.replace(/(\d+(?:\.\d+|))x/g, '$1 * x');
  return eval(expanded.replace(/x/g, xValue));
}

console.log(solveForX("5x + 2", 3));       // 17
console.log(solveForX("-4.2x + 3x", 5));   // -6
&#13;
.as-console-wrapper { top: 0; max-height: 100% !important; }
&#13;
&#13;
&#13;

高级 - 多变量表达式

&#13;
&#13;
const expFormat = '(\\d+(?:\\.\\d+|)){{@}}';
var expressionCache = {};
function lookupExpansion(v) {
  if (!expressionCache[v]) {
    expressionCache[v] = new RegExp(expFormat.replace(/\{\{\@\}\}/, v), 'g');
  }
  return expressionCache[v];
}

function toFunction(equation, variables) {
  variables.forEach(variable => {
    equation = equation.replace(lookupExpansion(variable), '$1 * ' + variable);
  });
  equation = equation.replace(/\b([a-z])([a-z])\b/g, '$1 * $2');
  console.log('[DEBUG]: Expanded => ' + equation);
  return Function.apply(null, variables.concat('return ' + equation));
}

// ======================== Simple ============================== //
var simpleMultiVariableFn = toFunction("x + 4x + 2y", ['x', 'y']);
console.log(simpleMultiVariableFn(3, 5)); // 25

// ======================== Advanced ============================ //
var slopeInterceptFunction = (slope, yIntercept) => {
  return x => toFunction("mx + b", ['m', 'x', 'b']).call(null, slope, x, yIntercept);
};
var interceptFn = slopeInterceptFunction(1, 2); // Reusable!
console.log(interceptFn(3)); // 5
console.log(interceptFn(4)); // 6
&#13;
.as-console-wrapper { top: 0; max-height: 100% !important; }
&#13;
&#13;
&#13;

使用花车和负数。