自己是電子信息方向的,因此總是需要處理大量的電路實驗、電路數據和電路仿真處理,每次處理數據時候還需要同樣的數據很多遍, 又需要關於電路的頻率響應和時域響應情況,所以一直有做一個這樣公式編輯器的打算了。 本來想使用VC的,但是想到javascript的eval()函數,就可以省去數據計算的算法了,而且對於用戶函數擴展都有幫助。
仔細想想後,作品需要有公式編輯、自定義操作符、自定義函數、系統函數調用、變量更新處理、定時器實現遍歷變量處理、圖形繪製和保存公式和函數等模塊。
這就是最終的界面了前面講的功能基本都實現了。
我覺的IT領域代碼純粹是屬於技術了,只要花時間總是能夠做好的,只是這種架構的模式和創意很重要。 而這種感性認識很大一部分來自於視野,看的東西、經歷的東西、悟的東西多了,靈感也會多點。 因此,還是希望我們程序員們不要總是宅在電腦前了。
一:公式編輯
好了,言歸正傳。 js裏面有個eval()函數,可以動態執行代碼。因此可以讓用戶操作腳本的運行。 在這個編輯器中也就是這樣,將用戶編輯的公式,經過變量處理、運算符號判斷等處理,轉換成eval()可以運行的語句。關於將用戶輸入的語句轉換成可執行語句是比較困難、麻煩的,因爲需要大量的判斷,例如是否碰到運算符,數字,變量是否重複,變量命名規制等等。 由於比較複雜,我貼下自己的供參考:
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;
}
}
}
其中包含了許多的函數和變量、對象,大家可能不懂,也沒關係,知道在判斷時候小心嚴謹點就好了。
二:變量處理
大家想,一旦用戶輸入了公式,就希望輕鬆改一下參數就可以瞬間算出全部結果了,所以可以把變量和結果製作成表格,允許用戶修改變量值並且更新結果。
對於高級功能。 大家有沒有遇到過一個運算過程中需要將某個變量或幾個變量遞增或遞減呢? 應該會的,我求解電路方程時經常需要變化。
技術活可以用setInterval()實現的,給個大概:
/*******開始運行高級功能****************/
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 = "開始";
}
}
同樣不是不完整的,需要其他函數的支持。
三:自定義函數或者符號
有些時候,用戶需要經常使用某些算式,那麼就可以讓他們自己定義成函數或者操作符了,例如我們經常使用電路中並聯運算,所以可以定義並聯符號//,多方便。
這個其實還是基於eval()的,例如 str="function And(){"+ order+"} And()";
其中order是用戶編輯的,可以修改一下。 先定義函數,在執行這個函數,eval(str)後就完成了。具體的大家可以再好好想想
四:圖形繪製
圖形是表達式最直觀的表現形式了,例如找最值,拐點,趨勢等。
圖形一般就要求自變量和因變量了,在固定自變量輸入範圍後利用插值法就可以繪製圖形了。
繪製圖形這裏需要用到HTML5中<canvas>對象,而且還需要新的瀏覽器的支持,這個功能與保存功能是矛盾的,因爲只有IE得到用戶許可後才能保存文件,但是連IE8都不支持html5,杯具了……
東西都是做的出來的,只是想法不一樣罷了。而且這個編輯器也還是有些bug的,只要大家有創意,都能夠完成,歡迎大家指正與討論。
懶於奮鬥的軀體是徒有虛名的擺設
懶於思考的大腦是寸草不生的荒漠