需要用到几天前写的Mathast,或者修改一下用eval也可以。
必要说明:

1
2
3
4
id 为canvas的id
exp 为函数 (如sin X 大写X为自变量)
color 为颜色(若不存在会自动生成)
max_x / max_y 为图像显示域,若分别输入10和20,则显示的范围为X∈[-10, 10] Y∈[-20, 20]

用法:

1
draw('c', 'sin X', '#272727', 4*Math.PI, 3);

注意:Y=2X+5等函数应该写成2*X+5,应遵守Mathast的语法原则。还有部分函数由于取值问题使曲线没有连接到位,请脑部 :)

正态分布表达式: pow E (-squ(X)/2*squ10) / sqr(2*PI) * 10

下图为tanXX*sinX+cosX (不同域下) 的图像

函数图像

在线实例:foxnes.github.com/mathexp.html

上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
function draw(id, exp, color, max_x){
if (typeof color == 'undefined' || color == '') {
var color = (function(m, s, c) {return (c ? arguments.callee(m, s, c - 1) : '#') + s[m.floor(m.random() * 16)]})(Math, '0123456789abcdef', 5);
}
if (typeof max_x == 'undefined' || max_x == 0 || max_x == '') {
var max_x = 10;
}
function transcoo(x, y) {
return {
x: ((w / 2) + (x * division_x)),
y: ((h / 2) - (y * division_y))
};
}
var c = document.getElementById(id),
ctx = c.getContext('2d');
if (exp == false) {
ctx.clearRect(0,0,c.width,c.height);
return true;
}
var w = c.width,
h = c.height,
division_x = w / max_x,
division_y = h / max_x,
sort = [],
sort_ = [],
tmp,
tmp_,
trend = ['asc', 0],
index = 0,
addx = max_x / 150,
sign_ = false,
calc = {
Add: function (arg1, arg2) {
arg1 = arg1.toString();
arg2 = arg2.toString();
var arg1Arr = arg1.split("."), arg2Arr = arg2.split("."), d1 = arg1Arr.length == 2 ? arg1Arr[1] : "", d2 = arg2Arr.length == 2 ? arg2Arr[1] : "";
var maxLen = Math.max(d1.length, d2.length);
var m = Math.pow(10, maxLen);
var result = Number(((arg1 * m + arg2 * m) / m).toFixed(maxLen));
var d = arguments[2];
return typeof d === "number" ? Number((result).toFixed(d)) : result;
},
Sub: function (arg1, arg2) {
return calc.Add(arg1, -Number(arg2), arguments[2]);
},
Mul: function (arg1, arg2) {
var r1 = arg1.toString(), r2 = arg2.toString(), m, resultVal, d = arguments[2];
m = (r1.split(".")[1] ? r1.split(".")[1].length : 0) + (r2.split(".")[1] ? r2.split(".")[1].length : 0);
resultVal = Number(r1.replace(".", "")) * Number(r2.replace(".", "")) / Math.pow(10, m);
return typeof d !== "number" ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)));
},
Div: function (arg1, arg2) {
var r1 = arg1.toString(), r2 = arg2.toString(), m, resultVal, d = arguments[2];
m = (r2.split(".")[1] ? r2.split(".")[1].length : 0) - (r1.split(".")[1] ? r1.split(".")[1].length : 0);
resultVal = Number(r1.replace(".", "")) / Number(r2.replace(".", "")) * Math.pow(10, m);
return typeof d !== "number" ? Number(resultVal) : Number(resultVal.toFixed(parseInt(d)));
}
};
ctx.beginPath();
ctx.strokeStyle = "#0f0f0f";
ctx.lineWidth = 1;
ctx.moveTo(w / 2, 0);
ctx.lineTo(w / 2, h);
ctx.moveTo(0, h / 2);
ctx.lineTo(w, h / 2);
ctx.stroke();
ctx.closePath();
ctx.beginPath();
ctx.strokeStyle = color;
ctx.lineWidth = 2;
var i = calc.Div(-max_x, 2);
while ( i <= calc.Div(max_x, 2) ) {
tmp = Mathast.run(exp.replace(/x/ig, '(' + i + ')')).result.value;
if (typeof tmp == 'number' && !isNaN(tmp)) {
sort.push({
y: Number(tmp),
x: Number(i)
});
if (index > 0)
tmp_ = calc.Sub(sort[(index - 1)].y, sort[index].y);
else
tmp_ = false;
if (tmp_ <= 0 && trend[0] == 'desc' && tmp_ !== false) {
trend = ['asc', tmp_];
tmp_ = true;
}else if (tmp_ >= 0 && trend[0] == 'asc' && tmp_ !== false){
trend = ['desc', tmp_];
tmp_ = true;
}else{
tmp_ = false;
}
if (tmp_ !== true) {
if (index - 2 >= 0){
tmp = calc.Div(calc.Sub(sort[(index - 2)].y, sort[(index - 1)].y), 2);
tmp_ = calc.Sub(sort[(index - 1)].y, sort[index].y);
}else{
tmp = 0;
tmp_ = 0;
}
if (Math.abs(tmp_) > Math.abs(tmp)){
tmp_ = true;
}else{
tmp_ = false;
}
}
if (tmp_ !== false) {
for (var j = sort[(index - 1)].x; j <= sort[index].x; j = calc.Add(j, calc.Div(addx, 50))) {
tmp = Mathast.run(exp.replace(/X/ig, '(' + j + ')')).result.value;
if (typeof tmp == 'number' && !isNaN(tmp)){
sort.push({
y: Number(tmp),
x: Number(j)
});
}else{
i = calc.Add(i, calc.Div(addx, 50));
continue;
}
}
}
index = sort.length;
}else{
i = calc.Add(i, calc.Div(addx, 50));
continue;
}
i = calc.Add(i, addx);
}
sort.sort(function(a, b){
return a.x - b.x;
});
for (var i = 0; i < sort.length; i++) {
tmp = sort[i];
tmp = transcoo(tmp.x, tmp.y);
if (i > 0 && (Math.abs(tmp.y) < (c.height))){
ctx.lineTo(tmp.x, tmp.y);
}else{
ctx.moveTo(tmp.x, tmp.y);
}
tmp_++;
}
ctx.stroke();
console.log(sort.length)
return {r: true, d: sort.length};
}