svg 項目實踐——添加可編輯的 svg 圖片
轉載自:LeapFE
https://segmentfault.com/a/1190000039754124
最近的項目中遇到一個需求,在頁面上添加一個可以自由拖拽、縮放、編輯顏色的 svg 圖片,項目中引用了兩個現有的插件,對插件進行解讀之後略有心得,與大家分享一下。
自由拖拽縮放的節點 —— react-rnd
說到拖拽,我們的第一反應當然是監聽鼠標事件來修改 dom
元素的位置,而縮放的話,則是在對元素邊界進行操作時重新修正元素的 position
和 width
、height
屬性。這部分就不予過多的贅述,有興趣的朋友可以參考下 react-rnd 這個插件,它引用了 react-draggable 和 react-resizeable 兩個插件來實現元素的拖拽和縮放。
此時我們理論上已經實現了 dom
元素的拖拽和縮放,但是在添加了 svg 圖片之後我們很快發現,由於外層的拖拽是由 document.addEventListener
來實現的,但是我們在 mouseDown
的時候,鼠標點擊的位置實際上是 svg
內的 document
。
那麼這個時候應該怎麼處理呢?最簡單的思路:把 svg
的 document
取出來,放到父級的 document
裏面。
自由的 svg —— react-svg
有了把 svg
的 document
取出來的思路,我們很容易能找到一個插件:react-svg,它的實現思路與我們上面提到的完全一致,此處貼上它的核心代碼供各位查看:
此時我們發現,我們添加的 svg 圖片已經可以自由的拖拽和縮放了。另外由於 react-svg 還開放了一個屬性 beforeInjection
,我們可以通過這個屬性來在 svg
掛載之前修改它的屬性,如 stroke
、stroke-width
、fill
等,因此我們可以更加靈活得處理我們的 svg 圖片。
svg 的縮放 —— preserveAspectRatio、vector-effect
我們很快又發現一個問題,svg
的縮放默認是等比的,也就是說當我們橫向拉長圖片的時候,它並不會變大,只會橫向偏移居中。
這個時候我們就要用到 svg
自帶的一個屬性:preserveAspectRatio
,用來表示是否強制進行統一縮放,當設置爲 none
的時候,svg 圖片不會進行強制統一縮放,如果需要,會縮放指定元素的圖形內容,使元素的邊界完全匹配視圖矩形。如下圖。其他類型強制縮放可參考 MDN。
現在我們的 svg
終於可以自由縮放了,但是很快我們又發現,把一個 svg
放大之後,它的線條寬度也跟着變寬了,那麼有沒有什麼屬性來保持線條寬度不變呢?答案是有的,vector-effect
,但是這個屬性只對部分 svg
元素( <circle>, <ellipse>, <foreignObject>, <image>, <line>, <path>, <polygon>, <polyline>, <rect>, <text>, <textPath> <tspan>, <use>
)生效,而它的屬性有以下幾個:
none
該值指定不應用矢量效果,即,使用默認的渲染行爲,即首先用指定的繪畫填充形狀的幾何形狀,然後使用指定的繪畫描邊輪廓。
non-scaling-stroke
該值修改了筆觸的方式。通常,筆觸涉及在當前用戶座標系中計算形狀路徑的筆觸輪廓,並用筆觸顏料(顏色或漸變)填充輪廓。該值的最終視覺效果是筆觸寬度不依賴於元素的變換(包括非均勻縮放和剪切變換)和縮放級別。
non-scaling-size
該值指定元素及其後代使用的特殊用戶座標系。儘管從宿主座標空間進行任何轉換更改,該用戶座標系的比例也不會更改。但是,它沒有指定抑制旋轉和偏斜。同樣,它也不指定用戶座標系的原點。由於此值抑制了用戶座標系的縮放,因此它還具有 non-scaling-stroke
的特性。
non-rotation
該值指定元素及其後代使用的特殊用戶座標系。儘管從宿主座標空間發生任何變換更改,該用戶座標系的旋轉和傾斜仍被抑制。但是,它沒有指定抑制縮放。同樣,它也沒有指定用戶座標系的原點。
fixed-position
該值指定元素及其後代使用的特殊用戶座標系。儘管從宿主座標空間進行任何轉換更改,用戶座標系的位置都是固定的。但是,它沒有指定抑制旋轉,偏斜和縮放。當同時指定了該矢量效果和 transform
屬性, transform
屬性將因該矢量效果而被消耗。
當我們設置vector-effect="non-scaling-stroke"
後,我們的svg
終於看起來正常了~
尾聲
以上就是我們在做給頁面上添加一個可以自由拖拽、縮放、編輯顏色的 svg 圖片時總結的一些東西,希望對各位有所幫助。另外我們還有一個沒有解決的問題,如果path
的內容是通過類似同心圓的方式來繪製圖形的時候,我們並沒有什麼好的方法來保證縮放時候線條寬度的變化,如果有人有什麼好的意見或者方法,可以聯繫我交流指導,可以知音樓搜曹文亮
或者添加本人微信caowl_1013
, 謝謝。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/-1Ygh9omO3kFSLdtYOW1Lg