適用于javascript開發(fā)者的Processing.js入門教程
這個入門指導(dǎo)是為javascript開發(fā)者寫的。讀這個文檔之前,你最好掌握javascript和web開發(fā)編程,并還會非?;镜?Processing 知識。
目錄:
為沒有耐心看長篇大論的人準(zhǔn)備:
如果你很著急入門,那么你就需要知道以下幾點(diǎn):
1、Processing.js 把 Processing 代碼轉(zhuǎn)變成能夠在瀏覽器端運(yùn)行的javascript代碼,實(shí)質(zhì)是通過<canvas>標(biāo)簽來實(shí)現(xiàn)繪圖的;
2、為了使用它,你的首先下載 Processing.js;
3、創(chuàng)建你的 后綴名為".pde"的 Processing 文件,它和通常你創(chuàng)建的普通文本文件一樣,例如: hello-web.pde
4、創(chuàng)建一個 html 頁面,然后在頁面里外引用 Processing.js文件,再添加一個<canvas>標(biāo)簽,該<canvas>標(biāo)簽上指明有你的 sketch file(顧名思義,草圖文件,就是Processing 文件),sketch file 可以有多個文件,多個文件用空格隔開。例如:
<script src="processing-1.3.6.min.js"></script> <canvas data-processing-sources="hello-web.pde"></canvas>
加載你的 web 頁面,processing.js 將解析、翻譯 sketch file,然后你的sketch file就會運(yùn)行在瀏覽器里。
Processing.js的來源?
Processing為何物?
Processing 語言原先被MIT創(chuàng)建,被作為多媒體實(shí)驗(yàn)室 和美學(xué)&計(jì)算機(jī)組的一部分。借助Processing能打通軟件開發(fā)者,藝術(shù)家,數(shù)據(jù)可視化工程師們之間的隔閡,并且能夠讓編程人員和非編程人員非常容易地勝任視覺化工作。Processing 是用java創(chuàng)建的,你可以把它認(rèn)為是一種被簡化了的java,并且?guī)П缓喕说挠脕砝L畫和繪圖的API。
Processing 能在web端做點(diǎn)什么?
Processing 擁有大型并且和活躍的社區(qū)群體,他們擅長創(chuàng)建2D和3D圖象,可視化數(shù)據(jù)套件,音頻,視頻等等。因?yàn)镠TML5,web端擁有了 canvas,audio,video,這些原先只能通過flash 和java插件擁有的功能。與此同時,高級的javascript引擎使得javascript 可以完全勝任以前做起來很慢的事情。
通過把Processing語言移植到web端,Processing 和 web社區(qū)都會收益。對于Processing來說,這意味這源碼不僅可以在桌面上工作,而且可以在跑在瀏覽器上。對于web社區(qū)來說,一個新而成熟并且接近全功能的圖象編程語言從而誕生了。 <canvas>元素對于直接用javascript提供的接口來開發(fā)的編程人員來說,這些原生接口太低級了,所以更高級的庫就是必要的。Processing.js就能夠被當(dāng)作是這樣的簡化操作2D和3Dcanvas的庫。
學(xué)會processing,需要多少工作要做
Processing語言小而完整,所以非常容易學(xué)。本文檔不僅僅嘗試去教你Processing,還會鼓勵你去尋找 Processing的規(guī)范教程,書和例子。任何Processing代碼或者概念都應(yīng)該映射到Processing.js里(下邊列出的除外)。你可以跳過Processing贊成的java語法的javascript,使用純javascript來與Processing的畫圖API一起使用。
使用Processing的方式
Processing.js創(chuàng)建的初衷是能夠讓Processing開發(fā)者和Processing代碼(通常是指 sketches)不用修改就可以在web端運(yùn)行。因此,被推薦的方式就是用Processing.js來寫processing 代碼,然后通過Processing.js轉(zhuǎn)換成javascript后運(yùn)行它。
隨著時間的推移,一些web開發(fā)者也開始使用processing.js,他們就要求設(shè)計(jì)的API從Processing 語脫離出來使用。因此,我們提供一種可以用純javascript語言來開發(fā)的方式,并且可以使用Processing的方法和對象。注意:Processing.js是放在首位的,并且是Processing向web開放的最重要的一部分,具有有利于兼容Processing的設(shè)計(jì)決定權(quán)。它不是被設(shè)計(jì)成一個通用的HTML 畫圖庫。已經(jīng)說過,它是可以當(dāng)作canvas高級畫圖API來用。
接下來我們討論下在web頁面里使用的各種Processing.js方法。
寫純 Processing 代碼
這種寫法是使用Processing.js的首選方法,并且已經(jīng)在 Processing.js for Processing Devs quick start guide 做了長篇的介紹。概括總結(jié)如下:
1、下載 processing.js
2、創(chuàng)建一個單獨(dú)的 Processing 文件,或多個文件,名字可以隨便叫,只要后綴名是".pde"就行。
3、創(chuàng)建一個web頁面,頁面包括 Processing.js 和 <canvas>標(biāo)簽,<canvas> 的信息含有 sketch file(s)的路徑和用空格隔開的Procesing 文件名列表,并且這些列表名是放在canvas的屬性data-processing-sources上。例如:
<!DOCTYPE html> <html> <head> <title>Hello Web - Processing.js Test</title> <script src="processing-1.3.6.min.js"></script> </head> <body> <h1>Processing.js Test</h1> <p>This is my first Processing.js web-based sketch:</p> <canvas data-processing-sources="hello-web.pde"></canvas> </body> </html>
當(dāng)頁面加載完(on page load),processing.js將會自動瀏覽web頁面的document,去查找<canvas>的屬性data-processing-sources,然后用XMLHTTPRequest去下載 這些文件,將它們?nèi)M(jìn)從porcessing到j(luò)avascript的翻譯器,翻譯后的javascript將會通過eval 函數(shù)來執(zhí)行。
預(yù)編譯 processing 代碼 為 javascript
Processing.js 自動下載并將所有Processing 代碼轉(zhuǎn)成 javascript。它做這些是使用Processing.compile()方法來完成的,并且 那些相關(guān)的processing構(gòu)建工具 或者實(shí)用工具也可以做同樣的事情。
為了獲得 從Processing 代碼編譯后的代碼(例如,JavaScript適用于processing.js運(yùn)行),請按如下操作:
// hard-coded Processing code, text from an HTML widget, downloaded text, etc. var processingCode = "..."; var jsCode = Processing.compile(processingCode).sourceCode;
例如,轉(zhuǎn)化如下的Processing 代碼 會生成 在它之下的 編譯的來的javascript代碼:
// Processing code void setup() { size(200, 200); background(100); stroke(255); ellipse(50, 50, 25, 25); println("hello web!"); } // "Comiled" JavaScript code // this code was autogenerated from PJS (function(processing, $constants) { function setup() { processing.size(200, 200); processing.background(100); processing.stroke(255); processing.ellipse(50, 50, 25, 25); processing.println("hello web!"); } processing.setup = setup; })
只寫 javascritp的 processing.js code
前面的方法把 processing 代嗎生成了 javascript 代碼,但是你也可以單獨(dú)寫javascript。processing.js的解析器將Processing代碼轉(zhuǎn)化成javascript方法,然后運(yùn)行它。因此,完全有可能跳過Processing代碼,只寫javascript 方法,將方法傳給一個Processing實(shí)例。這有個例子如下:
function sketchProc(processing) { // Override draw function, by default it will be called 60 times per second processing.draw = function() { // determine center and max clock arm length var centerX = processing.width / 2, centerY = processing.height / 2; var maxArmLength = Math.min(centerX, centerY); function drawArm(position, lengthScale, weight) { processing.strokeWeight(weight); processing.line(centerX, centerY, centerX + Math.sin(position * 2 * Math.PI) * lengthScale * maxArmLength, centerY - Math.cos(position * 2 * Math.PI) * lengthScale * maxArmLength); } // erase background processing.background(224); var now = new Date(); // Moving hours arm by small increments var hoursPosition = (now.getHours() % 12 + now.getMinutes() / 60) / 12; drawArm(hoursPosition, 0.5, 5); // Moving minutes arm by small increments var minutesPosition = (now.getMinutes() + now.getSeconds() / 60) / 60; drawArm(minutesPosition, 0.80, 3); // Moving hour arm by second increments var secondsPosition = now.getSeconds() / 60; drawArm(secondsPosition, 0.90, 1); }; } var canvas = document.getElementById("canvas1"); // attaching the sketchProc function to the canvas var processingInstance = new Processing(canvas, sketchProc);
這兒是創(chuàng)建了一個 sketch 方法,這個方法就和解析器生成的代碼一樣。這個方法需要一個參數(shù),它是一個指向某個由Processing構(gòu)造器生成的processing對象(例如,Processing運(yùn)行時對象)的引用,任何 Procesing方法或者對象都一個作為它的屬性來訪問。
一旦這個方法完成,并且通過,隨著就有一個引用指向canvas,一個引用指向 Processing構(gòu)造器(記得用"new")。
寫一個 Processing 和 javascript結(jié)合的文件
人們經(jīng)常問的第一個問題就是processing.js是否可以讀取來自正在運(yùn)行Processing sketch的文件的值?;蛘叻催^來的觀點(diǎn)。答案是肯定的。
Processing.js 轉(zhuǎn)化 Processing 代碼 成一個含有函數(shù)閉包javascript代碼。所有你創(chuàng)建的變量和方法沒有被綁定到全局變量上(即:window)。然而,你仍然可以訪問他們。
1)、從Processing里訪問 javascript對象
從Processing代碼轉(zhuǎn)化成javascript并且和其他函數(shù)一樣運(yùn)行起來,所有Processing代碼都可以訪問全局對象。這意味著你可以在全局腳本模塊里創(chuàng)建一個變量或者方法,它們就可以自動被Processing來訪問??紤]這樣一個例子:
首先是 Processing 文件,mixed.pde:
String processingString = "Hello from Processing!"; void setup() { printMessage(jsString + " " + processingString); }
接下來是web頁面:
<!DOCTYPE html> <html> <head> <title>Hello Web - Accessing JavaScript from Processing</title> <script src="processing-1.3.6.min.js"></script> </head> <body> <div id="msg"> </div> <canvas data-processing-sources="mixing.pde"></canvas> <script type="application/javascript"> var jsString = "Hello from JavaScript!"; var printMessage = function (msg) { document.getElementById('msg').innerHTML = "Message: " + msg; }; </script> </body> </html>
這里 Processing.js允許使用的變量和方法聲明在 Processing代碼的外邊。
2)、javascript 和 Processing代碼的混合
前面的例子使得javascript和processing代碼各自放在單獨(dú)的文件里,當(dāng)它們之間的界限不是分的很近時。
因?yàn)镻rocessing.js在轉(zhuǎn)化代碼時,也可能直接將他們直接混在一起。Processing.js解析器保留包含在Processing代碼里的 javascript不變,這樣就允許開發(fā)者能寫processing和javascript的混合代碼(注意:這也就是為什么 processing.js里沒有使用純processing解析器的原因)。這是一個之前也是用這個方法寫的例子:
var jsString = "Hello from JavaScript!"; var printMessage = function(msg) { document.getElementById('msg').innerHTML = "Message: " + msg; }; String processingString = "Hello from Processing!"; void setup() { printMessage(jsString + " " + processingString); }
有些javascript語法很難用這種方式混在一起寫(例如:正則語法)。如果是那樣的情況的話,你可以簡單地將純javasript代碼移到一個<script>代碼塊里,然后像上邊“Accessing JavaScript Objects from Processing”描述的那樣來訪問它。
3)、從javascript里訪問 processing
得出個結(jié)論是從Processing 代碼里訪問javascript比反過來要容易的多,因?yàn)楸籔rocessing解析器創(chuàng)建javascript沒有直接暴露在全局對象里,因此你只能通過Processing.instances 的屬性來訪問。
Processing 的構(gòu)造器一直都在監(jiān)視實(shí)例的創(chuàng)建,并且使得他們可以使用getInstanceById()方法。默認(rèn),當(dāng)<canvas>有屬性 data-processing-source時,它的id將會作為Processing 實(shí)例的唯一識別負(fù)。如果沒有id屬性,你可以用Proessing.instance[0]來訪問。
當(dāng)你有一個能夠訪問Processing實(shí)例的引用時,你就可以調(diào)用它像這樣:
<!DOCTYPE html> <html> <head> <title>Hello Web - Controlling Processing from JavaScript</title> <script src="processing-1.3.6.min.js"></script> </head> <body> <canvas id="sketch" data-processing-sources="controlling.pde"></canvas> <button onclick="startSketch();"> Start</button> <button onclick="stopSketch();"> Stop</button> <script type="application/javascript"> var processingInstance; function startSketch() { switchSketchState(true); } function stopSketch() { switchSketchState(false); } function switchSketchState(on) { if (!processingInstance) { processingInstance = Processing.getInstanceById('sketch'); } if (on) { processingInstance.loop(); // call Processing loop() function } else { processingInstance.noLoop(); // stop animation, call noLoop() } } </script> </body> </html>
在DOM結(jié)構(gòu)中有2個按鈕,他們被用來讓用戶選擇開始或暫停正在運(yùn)行的Processing sketch.
他們直接在javascript中控制Processing實(shí)例(在頁面里你可能有多個,或者藏在div中),通過調(diào)用Processing的方法:loop()和noLoop()。這些Processing 的方法可以在其他的文件中找到。
作為一個使用Processing.js的開發(fā)者必須知道的事情:
當(dāng) Processing.js試圖去完全兼容 Processing時,就有些不同的事情或者需要解決辦法。我們也增加了一些web規(guī)范的功能來使Processing更容易被使用。 這里有一些技巧和提示在你開始使用Processing.js做復(fù)雜的sketch時可能有幫助。
Processing.js提供通過“externals”屬性來訪問各種 DOM/javascript對象
每個Processing 實(shí)例(即:Processing.instances)包含有一個"external"屬性,它是一個對象,包含各種指向非常有用的非Processing 的DOM/javascritp 對象,例如:
canvas--sketch被綁定上的畫板 context--畫板的執(zhí)行上下文 onblur and onfocus--事件處理器
如果一個除法表達(dá)式期望產(chǎn)生一個整型值,那么這可能需要顯式轉(zhuǎn)換
當(dāng)將Processing代碼轉(zhuǎn)化成javascript,涉及整型 vs 浮點(diǎn)型的除法的時候,有一個有bug的class會出現(xiàn)這個問題。
在Processing代碼中出現(xiàn)某個東西直接除以整數(shù)的代碼塊,當(dāng)被轉(zhuǎn)化成Processing時,可能有時出現(xiàn)問題,因?yàn)?,整型編程雙精度型,被引入了一個小數(shù)部分。修補(bǔ)這個bug的方法是 顯式轉(zhuǎn)換任何除法,正如展示的做法:
// before int g = mouseX / i; // after int g = (int)(mouseX / i);
Processing.js有個欺騙在模擬 Processing的異步輸入輸出
Processing 使用一個同步輸入輸出的模型,這就意味著 像loadImage()方法這樣,需要相對長時間去執(zhí)行,然而當(dāng)他們執(zhí)行期間,又沒有任何事發(fā)生,程序等到它loadImage()執(zhí)行完才去執(zhí)行下一行語句。這就意味這可以依靠像loadImage()這樣的方法返回的值用在接下來的代碼中。
但是web瀏覽器卻不是這樣的,它使用的是異步輸入輸出模型,這意味著加載外部資源的方法不能使得程序等到他們加載完再執(zhí)行。為了實(shí)現(xiàn)Processing的load方法,你不得不使用一個特殊的Processing的指令。
Processing.js指令提示瀏覽器,指令是寫在注釋里而不是Processing自身代碼。這是一個典型的 Processing sketch,它需要同步加載一個圖片然后畫出它:
PImage img; void setup() { img = loadImage("picture.jpg"); image(img, 0, 0); }
這些代碼在含有Processing.js的瀏覽器里將不會執(zhí)行,因?yàn)閳D片文件 picture.jpg被加載完之前就被調(diào)用了。修補(bǔ)這個bug的辦法是讓在sketch 開始執(zhí)行前就把圖片加載好,并且緩存起來,就是所說的預(yù)加載技術(shù)。這是修改后的代碼:
/* @pjs preload="picture.jpg"; */ PImage img; void setup() { img = loadImage("picture.jpg"); image(img, 0, 0); }
注意:放在代碼頂部的額外的注釋行。"@jps"指令是給Processjing.js用的,不是給開發(fā)者用的??梢园阉J(rèn)為成額外的代碼行,它們將在程序執(zhí)行前就被執(zhí)行了。
如果你有多個圖片被加載,可以使用如下列表:
/* @pjs preload="picture.jpg,picture2.jpg,picture3.png"; */
Processing.js需要更多的注意在變量的命名上比Processing
javascript其中一個最強(qiáng)大的特性就是它的動態(tài),弱類型的性質(zhì)。因?yàn)閖ava是強(qiáng)類型的語言,所以Processing也是,他們能重復(fù)命名而不用還怕產(chǎn)生歧義(例如:方法的重載),Processing.js就不行。不能進(jìn)入javascript的內(nèi)部工作,所以對Processing.js的開發(fā)者來說,最好的建議就是不要用 function/class/etc/,也不要用來自Processing的名字來命名變量。例如,一個叫 line的變量可能看起來合理,但是它會導(dǎo)致問題,因?yàn)樗蚉rocessing與Procesing.js內(nèi)置的函數(shù)名line()一樣。
當(dāng)要覆蓋重載的父類方法時,Processing需要你的幫助
如果你的代碼使用子類覆蓋一個或多個父類里重載的方法,你需要“假”覆蓋,因?yàn)椋總€方法簽名,你通常就沒改動過:
class X { void doSomething() { ... } void doSomething(float x, float y) { ... } } class Y extends X { void doSomething() { // different code from compared to the super class } // even though we don't override this method, // its signature must be added to prevent Pjs // from getting the method chain wrong: void doSomething(float x, float y) { super.doSomething(x,y); } }
盡管在Processing里 你不需要實(shí)現(xiàn)擁有(float,float)簽名的空方法doSomething,但是這樣做幾乎是必須的,這是為了確保Processing.js在調(diào)用方法時不被搞暈。
直接將Processing 代碼放在web頁面里也是可以的
在canvas上,用一個 data-processing-source屬性包含Processing.js加載的外部文件的做法是首選,但是推薦的方式在web頁面里外引用腳本。但是寫成行內(nèi)引用也是可以的。
把上邊例子的代碼作為行內(nèi)引用的方式,有必要的改動一點(diǎn):
<script src="processing-1.3.6.min.js"></script> <script type="application/processing" data-processing-target="pjs"> void setup() { size(200, 200); background(100); stroke(255); ellipse(50, 50, 25, 25); println('hello web!'); } </script> <canvas id="pjs"> </canvas>
這些代碼是更復(fù)雜了,因?yàn)樗鼪]有指出那個canvas配那個腳本文件(即:你可以在一個頁面引用多個Processing sketch,同樣也可以有多個canvas)。也沒有說明腳本的"type"屬性,這個屬性是用來區(qū)別javascript和Processing代碼的(瀏覽器將忽略 Processing 腳本)。最后,注意:"id"和"target"屬性的用法,它倆是用來連接Processing腳本和相關(guān)的canvas的。
以上就是本文的全部內(nèi)容,希望大家對Processing.js有所認(rèn)識。
相關(guān)文章
Swiper.js實(shí)現(xiàn)移動端元素左右滑動
這篇文章主要為大家詳細(xì)介紹了Swiper.js實(shí)現(xiàn)移動端元素左右滑動 ,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下2019-09-09JavaScript中處理數(shù)組,對象和正則的實(shí)用函數(shù)
本文主要分享一下最近項(xiàng)目中遇到的一些javascript的業(yè)務(wù)邏輯函數(shù),這些函數(shù)可以提成一個公用的工具函數(shù)以便于在以后的項(xiàng)目中進(jìn)行使用,希望對大家有所幫助2023-11-11用JavaScript對JSON進(jìn)行模式匹配(Part 1-設(shè)計(jì))
在《從 if else 到 switch case 再到抽象》這篇文章里面說到,解決 if else 和 switch case 分支過多的一個方法,就是做一個專用的 dispatcher ,讓它來負(fù)責(zé)進(jìn)行篩選與轉(zhuǎn)發(fā)。2010-07-07JavaScript的DOM與BOM的區(qū)別與用法詳解
這篇文章主要為大家詳細(xì)介紹了JavaScript的DOM與BOM的區(qū)別與用法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助2022-03-03