robot
最新文章(10)
Mqskit 和其它相關工具
CPython 的 GC 二、三事
寫 Mecurial Extension 是件快樂的事!
Mozilla 台灣辨公室徵人啟事
關於 Apple 的兩項專利
core dump 之前的 frame
怎麼發出 beep 聲?
先承認你要找的是奴才吧!
程式碼要清的多乾淨?
FreeBSD 的 Thread-Local Storage 實作
首頁
新編
最新留言
Entries RSS
重要關鍵字(10)
coding (122)
Python (93)
FreeBSD (71)
WEB (61)
URL (48)
hardware (46)
javascript (36)
Linux (34)
blog (30)
C++ (16)
所有關鍵字
新增 URL
SVG 的 boundary box
by thinker
2 Columns
關鍵字:
WEB
coding
最近又回到 MadSwatter 上的開發,以配合 MadButterfly 的進行。在 MadButterfly 趨於成熟後,突然發覺工具沒跟上。於是,本週我又回到 MadSwatter 的開發,提供動畫編輯的功能。 之前, MadSwatter 只能做 sprite 的移動。為了要做放大、縮小、旋轉等功能,則需計算出 boundary box 的範圍,讓使用者能拉動 boundary box,進行上述動作。原本,我是將 MadButterfly 上的演算法搬過來,在 Javascript 上重新 impelment。後來發覺,原來 linkname:[SVG uDOM] http://www.w3.org/TR/2008/REC-SVGTiny12-20081222/svgudom.html 的規格裡已經定義了 boundary box 的計算函數,而 $Firefox$ 也實作了一部分。我們要用到的是 * getScreenBBox() 可惜的是, $Firefox$ 3.0.5 只 implement * getBBox() getBBox() 傳回的 boundary box 是位於 $graphic$ 所在的空間裡,需轉換至 viewport 的座標空間。可錯, $Firefox$ 也沒有實作 * getScreenBBox() 於是我們必需自行空間轉換所需的 matirx ,也就是 CTM。 這要透過 parse transform attribute 取得。例如 * matrix() * translate() * rotate() * ... 全都要自行 parse 後,轉成 matrix ,將各層的 matrix 相乘算出 CTM 。 CTM 是用來將一圖形,從定義的空間轉換到 viewport ,也就是瀏覽器的空間。 user 透過操作 matrix ,改變 CTM ,進而將圖形透過線性空間的轉換,達成放大、縮小、旋轉、移動等效果。 因此, CTM 的取得是要讀出從 leaft 到 root ,每一層 svg node 的 transform attribute ,加以 parse 。接著,將 getBBox() 傳回的長方形範圍,轉成代表四個角落的點,透過 CTM 做空間轉換,計算出對應的位置。最後,加入一個 rect 類別的 SVG node ,畫出 boundary box 的位置。如下列即是透過此方法算出的 boundary box。 [attach:bbox.png] 最外面紅色的方框即為 boundary box 。 parse transform attribute 最快的方式,就是透過 regular expression。我將 regular expression 定義如下 {{{ var _f = "[+\\-]?\\d+(\\.\\d+)?" var _s = " *[ ,] *"; var func_reg = "\\w* *\\( *(_f_s)*_f *\\)" }}} 由於參數之間的逗點和空白重複多次,於是定義 _s 取代,參數本身也是一樣,以 _f 取代。透過 replace function 能組回原來所需的 pattern 。 {{{ func_reg = func_reg.replace("_f", _f, "g"); func_reg = func_reg.replace("_s", _s, "g"); }}} 如此,整個 regular expression 會更清楚而容易定義,也較不容易發生錯誤。 另外,在 parse 時,我透過 match function ,將 transform attribute 裡的每一個 function 抽取出來,再取得其中的參數,這樣問題就能簡單化。 {{{ func_r = new RegExp(func_reg, "g"); funcs = mstr.match(func_r); for(i = 0; i < funcs.length; i++) { func = funcs[i]; fs = func.match(float_r); }}} 如此,我們只需比對 func 前面幾個字,就可以知道 function 的名稱,然後再從 fs 每個所有的參數內容。這個方式之所以可行,主要是因為 transform 裡面定義的參數都是浮點數。因此在 parse 時就容易許多。當然,這個 parser 不是很完整。如果有 attribute 的內容的格式不正確,並無法檢查出來,直接忽略。但就開發先期,策略性的簡化問題也不為過。只是事後必需記得回過頭來修。
最後更新時間: 2009-09-14 13:55:08 CST |
引用
查詢:
COMMENTS: