自己是電子信息方向的,因此總是需要處理大量的電路實驗、電路數(shù)據(jù)和電路仿真處理,每次處理數(shù)據(jù)時候還需要同樣的數(shù)據(jù)很多遍, 又需要關(guān)于電路的頻率響應(yīng)和時域響應(yīng)情況,所以一直有做一個這樣公式編輯器的打算了。 本來想使用VC的,但是想到javascript的eval()函數(shù),就可以省去數(shù)據(jù)計算的算法了,而且對于用戶函數(shù)擴展都有幫助。
仔細想想后,作品需要有公式編輯、自定義操作符、自定義函數(shù)、系統(tǒng)函數(shù)調(diào)用、變量更新處理、定時器實現(xiàn)遍歷變量處理、圖形繪制和保存公式和函數(shù)等模塊。

這就是最終的界面了前面講的功能基本都實現(xiàn)了。
我覺的IT領(lǐng)域代碼純粹是屬于技術(shù)了,只要花時間總是能夠做好的,只是這種架構(gòu)的模式和創(chuàng)意很重要。 而這種感性認識很大一部分來自于視野,看的東西、經(jīng)歷的東西、悟的東西多了,靈感也會多點。 因此,還是希望我們程序員們不要總是宅在電腦前了。
一:公式編輯
好了,言歸正傳。 js里面有個eval()函數(shù),可以動態(tài)執(zhí)行代碼。因此可以讓用戶操作腳本的運行。 在這個編輯器中也就是這樣,將用戶編輯的公式,經(jīng)過變量處理、運算符號判斷等處理,轉(zhuǎn)換成eval()可以運行的語句。關(guān)于將用戶輸入的語句轉(zhuǎn)換成可執(zhí)行語句是比較困難、麻煩的,因為需要大量的判斷,例如是否碰到運算符,數(shù)字,變量是否重復(fù),變量命名規(guī)制等等。 由于比較復(fù)雜,我貼下自己的供參考:
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對應(yīng)與order { var pos, end, i = 0, temp = ""; order[num] = ""; while (i < str.length)//遍歷一次 { if (judgeChar(str.charAt(i)) == 0) //如果當(dāng)前的字符不是數(shù)字和字母,就應(yīng)該是運算符 { //可以通過其他辦法動態(tài)添加運算符 order[num] += str.charAt(i); i++; } else //說明是一個變量,需要創(chuàng)建變量 { pos = i; end = 0; //記錄這個變量的首尾位置 while (judgeChar(str.charAt(i)) >0) //直到檢驗出符號或者退出 { i++; if (i >= str.length) break; } end = i; temp = str.substring(pos, end); //獲取對應(yīng)的子字串 var x = judgeMathFunction(temp); //判斷是否是數(shù)學(xué)符號 if (judgeStringNum(temp) == false) //表示字符串不全是數(shù)字,有可能是變量,也有可能是數(shù)學(xué)函數(shù) { if (x < 0) //如果不是數(shù)學(xué)函數(shù) { 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++; //創(chuàng)建變量并且保存 } else order[num] += param[pos].value; } else if (x < 100) //表示是自帶的數(shù)學(xué)函數(shù) order[num] += "Math." + temp; //轉(zhuǎn)換成對應(yīng)的數(shù)學(xué)運算 else //>=100表示對應(yīng)的是自定義的函數(shù) order[num] += temp; //先不進行處理 } else //如果字符串只是數(shù)字,不創(chuàng)建變量 order[num] += temp; } } }</span> |
其中包含了許多的函數(shù)和變量、對象,大家可能不懂,也沒關(guān)系,知道在判斷時候小心嚴(yán)謹點就好了。
二:變量處理
大家想,一旦用戶輸入了公式,就希望輕松改一下參數(shù)就可以瞬間算出全部結(jié)果了,所以可以把變量和結(jié)果制作成表格,允許用戶修改變量值并且更新結(jié)果。
對于高級功能。 大家有沒有遇到過一個運算過程中需要將某個變量或幾個變量遞增或遞減呢? 應(yīng)該會的,我求解電路方程時經(jīng)常需要變化。
技術(shù)活可以用setInterval()實現(xiàn)的,給個大概:
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(); //處理標(biāo)簽 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> |
同樣不是不完整的,需要其他函數(shù)的支持。
三:自定義函數(shù)或者符號
有些時候,用戶需要經(jīng)常使用某些算式,那么就可以讓他們自己定義成函數(shù)或者操作符了,例如我們經(jīng)常使用電路中并聯(lián)運算,所以可以定義并聯(lián)符號//,多方便。
這個其實還是基于eval()的,例如 str="function And(){"+ order+"} And()";
其中order是用戶編輯的,可以修改一下。 先定義函數(shù),在執(zhí)行這個函數(shù),eval(str)后就完成了。具體的大家可以再好好想想
四:圖形繪制
圖形是表達式最直觀的表現(xiàn)形式了,例如找最值,拐點,趨勢等。
圖形一般就要求自變量和因變量了,在固定自變量輸入范圍后利用插值法就可以繪制圖形了。
繪制圖形這里需要用到HTML5中<canvas>對象,而且還需要新的瀏覽器的支持,這個功能與保存功能是矛盾的,因為只有IE得到用戶許可后才能保存文件,但是連IE8都不支持html5,杯具了……
東西都是做的出來的,只是想法不一樣罷了。而且這個編輯器也還是有些bug的,只要大家有創(chuàng)意,都能夠完成,歡迎大家指正與討論。
新聞熱點
疑難解答