自己是电子信息方向的,因此总是需要处理大量的电路实验、电路数据和电路仿真处理,每次处理数据时候还需要同样的数据很多遍, 又需要关于电路的频率响应和时域响应情况,所以一直有做一个这样公式编辑器的打算了。 本来想使用VC的,但是想到javascript的eval()函数,就可以省去数据计算的算法了,而且对于用户函数扩展都有帮助。
仔细想想后,作品需要有公式编辑、自定义操作符、自定义函数、系统函数调用、变量更新处理、定时器实现遍历变量处理、图形绘制和保存公式和函数等模块。
这就是最终的界面了前面讲的功能基本都实现了。
我觉的IT领域代码纯粹是属于技术了,只要花时间总是能够做好的,只是这种架构的模式和创意很重要。 而这种感性认识很大一部分来自于视野,看的东西、经历的东西、悟的东西多了,灵感也会多点。 因此,还是希望我们程序员们不要总是宅在电脑前了。
一:公式编辑
好了,言归正传。 js里面有个eval()函数,可以动态执行代码。因此可以让用户操作脚本的运行。 在这个编辑器中也就是这样,将用户编辑的公式,经过变量处理、运算符号判断等处理,转换成eval()可以运行的语句。关于将用户输入的语句转换成可执行语句是比较困难、麻烦的,因为需要大量的判断,例如是否碰到运算符,数字,变量是否重复,变量命名规制等等。 由于比较复杂,我贴下自己的供参考:
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
|
<span style=
"font-size:18px;"
>
var
dealSentence =
function
(str, num)
//num对应与order
{
var
pos, end, i = 0, temp =
""
;
order[num] =
""
;
while
(i < str.length)
//遍历一次
{
if
(judgeChar(str.charAt(i)) == 0)
//如果当前的字符不是数字和字母,就应该是运算符
{
//可以通过其他办法动态添加运算符
order[num] += str.charAt(i); i++;
}
else
//说明是一个变量,需要创建变量
{
pos = i; end = 0;
//记录这个变量的首尾位置
while
(judgeChar(str.charAt(i)) >0)
//直到检验出符号或者退出
{
i++;
if
(i >= str.length)
break
;
}
end = i; temp = str.substring(pos, end);
//获取对应的子字串
var
x = judgeMathFunction(temp);
//判断是否是数学符号
if
(judgeStringNum(temp) ==
false
)
//表示字符串不全是数字,有可能是变量,也有可能是数学函数
{
if
(x < 0)
//如果不是数学函数
{
var
x =
new
PARAM(); x.name = temp; x.num = paramcount; x.value = 0;
//初始化
pos = judgeParamExist(x.name);
if
(pos < 0)
//表示没有与之前的变量重合
{
param[paramcount] = x; order[num] += x.value; paramcount++;
//创建变量并且保存
}
else
order[num] += param[pos].value;
}
else
if
(x < 100)
//表示是自带的数学函数
order[num] +=
"Math."
+ temp;
//转换成对应的数学运算
else
//>=100表示对应的是自定义的函数
order[num] += temp;
//先不进行处理
}
else
//如果字符串只是数字,不创建变量
order[num] += temp;
}
}
}</span>
|
其中包含了许多的函数和变量、对象,大家可能不懂,也没关系,知道在判断时候小心严谨点就好了。
二:变量处理
大家想,一旦用户输入了公式,就希望轻松改一下参数就可以瞬间算出全部结果了,所以可以把变量和结果制作成表格,允许用户修改变量值并且更新结果。
对于高级功能。 大家有没有遇到过一个运算过程中需要将某个变量或几个变量递增或递减呢? 应该会的,我求解电路方程时经常需要变化。
技术活可以用setInterval()实现的,给个大概:
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
|
<span style=
"font-size:18px;"
>
/*******开始运行高级功能****************/
var
time =
null
;
var
start =
function
()
//
{
readValue();
//获取值
dealFlag();
//处理标签
if
(begin ==
true
)
//表示开始定时器
time = setInterval(
"settime()"
, 300);
//没300ms处理一次
else
clearInterval(time);
}
/******定时器************/
var
settime =
function
()
//
{
for
(
var
i = 0; i < paramcount; i++)
// 先更新值
{
if
(method[i] ==
"y"
|| method[i] ==
"Y"
)
param[i].value += parseFloat(small[i]);
if
(method[i] ==
"n"
|| method ==
"N"
)
param[i].value -= parseFloat(small[i]);
}
updateAdancedTable();
}
/**************************处理begin***************/
var
dealFlag =
function
()
//
{
if
(begin ==
false
)
//
{
begin =
true
; document.getElementById(
"BS"
).innerHTML =
"暂停"
;
}
else
//
{
begin =
false
; document.getElementById(
"BS"
).innerHTML =
"开始"
;
}
}</span>
|
同样不是不完整的,需要其他函数的支持。
三:自定义函数或者符号
有些时候,用户需要经常使用某些算式,那么就可以让他们自己定义成函数或者操作符了,例如我们经常使用电路中并联运算,所以可以定义并联符号//,多方便。
这个其实还是基于eval()的,例如 str="function And(){"+ order+"} And()";
其中order是用户编辑的,可以修改一下。 先定义函数,在执行这个函数,eval(str)后就完成了。具体的大家可以再好好想想
四:图形绘制
图形是表达式最直观的表现形式了,例如找最值,拐点,趋势等。
图形一般就要求自变量和因变量了,在固定自变量输入范围后利用插值法就可以绘制图形了。
绘制图形这里需要用到HTML5中<canvas>对象,而且还需要新的浏览器的支持,这个功能与保存功能是矛盾的,因为只有IE得到用户许可后才能保存文件,但是连IE8都不支持html5,杯具了……
东西都是做的出来的,只是想法不一样罢了。而且这个编辑器也还是有些bug的,只要大家有创意,都能够完成,欢迎大家指正与讨论。