日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

基于Web的svg编辑器(2)——层次结构设计(DOM结构)

發布時間:2023/12/31 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于Web的svg编辑器(2)——层次结构设计(DOM结构) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

svg 編輯器系列(2)其實在之前已經寫過了,但寫得不好,所以這次重寫一下,順便也把示例代碼重寫了。

本文主要講解一款 svg 編輯器的DOM結構,該如何分層以及這樣分層的原因。DOM 結構主要參考了一款名為 svgedit的開源 svg 編輯器。

代碼實現

代碼用到了 svgjs 庫。不過應該還是挺好懂的。

演示鏈接:f-star.github.io/web-editor-…

源碼地址:github.com/F-star/web-…

網頁截圖:

總覽

DOM 結構如下:

svg 編輯器 ├── workarea (視口層)└── svgcanvas (掛載層)└── svgRoot (最上層的svg)├── canvasBg (svg背景層)├── svgcontent (繪制層)| ├── layout1 (圖層一)| ├── layout2 (圖層二)| └── ...├── guideLine (輔助線層) 復制代碼

視口層

div#workarea

顧名思義,該層為編輯器的可視范圍。當 svgRoot 的高或寬大于該層的寬高時,會顯示滾動條。

掛載層

div#svgcanvas

掛載層負責 svg 的掛載。它會保持寬高和 svgRoot 相同。你可能會奇怪這層到底有什么用,直接掛載到適口層不也行嗎?沒錯,直接掛載在視口層也是可行的,但軟件設計需要考慮到一些可能會發生的情況。這里我們加上了這層,是考慮到后期我們可能會需要在 svgRoot 的同一層上添加一些 div 元素(畢竟svg中是無法添加 div 元素的),比如說添加一些備忘錄。

svgRoot

svg#svgRoot

該元素為 根部svg 元素,它并不是真正繪制 svg 的載體,真正繪制 svg 圖形的地方是它的內嵌 svg 元素,即繪制層。我們追加這層根部 svg 的目的,是為了使超出內嵌 svg 范圍外的矢量圖形,仍然能顯示出來(svgRoot 比)。如圖所示:

這里給個圖片

svg背景層

svg#canvasBg

它負責顯示出畫布的位置,一般設置為白色。

繪制層

svg#svgcontent

矢量圖形真正繪制的地方。導出的 svg 文件內容即是這個元素下的所有內容。注意要設置 overflow="visible"

繪制層的圖層

g#layout

類似 PhotoShop,我們引入了“圖層”的概念。圖層就像疊好的一張張半透明(軟件中其實是全透明)的白紙,你可以選擇任意一張進行繪畫。另外上層的紙的不透明的部分,會擋住它的下層的相同區域的顯示。

輔助線層

作為一款編輯器,我們需要一些輔助線,提供一些選中效果以及一些交互。比如點擊一個圖形,就顯示一個包圍著它的矩形,我稱之為“選中框”,此外這個矩形上有一些控制點,對它們進行拖拽等操作,可以對當前這個矩形進行縮放或者旋轉。為了實現這些功能,輔助線是 svg 編輯器十分重要的部分。

但是為什么我們把輔助線層放到 根部svg 下,而不是直接放到繪制層呢?原因是在實現畫布“縮放”功能的時候,畫布的縮放其實是通過設置 svg#svgcontent 的 viewBox 屬性來實現的(后面的svg編輯器系列會詳細講解),這種縮放會導致元素的 stroke-width(線寬)也會跟著變大變小。這樣的話,用戶體驗就很不好了。

放大還好,選中框的線條雖然很大,但被選中的那個元素也好大。當如果是縮小的話,并縮小到很小的時候,就會有一個問題,那就是選中框也變細變小了,這樣選中框的一些變形控制點也不好點中了。

輔助線層下的元素一般來說,在編輯器初始化的時候就應該進行創建,并將其設置 style="display: none;"。比如說選中框,選中一個元素時,輔助線層下相關的元素一些屬性會被修改(如元素的位置),然后顯示出來;取消選中時,則將相關元素全部設置為不可見。我不建議直接刪除或添加這些元素,因為這會有性能損失。

初始化

const svgRoot = SVG('svgcanvas').id('svgroot'); // svg root const canvasBg = svgRoot.nested().id('canvasBg'); // svg 內容的底色,寬高需和 svg content 同步 const svgContent = svgRoot.nested().id('svgcontent'); // svg 的真正內容位置。 const draw = svgContent.group(); // svgContent 下創建一個 group,作為第一個“圖層”(類似ps的圖層概念)const guideLine = svgRoot.group().id('guideLine'); // 放置輔助線的父容器 const selectedBox = guideLine.group().id('selectedBox'); // 選中框相關輔助線 const selectedBoxOutline = selectedBox.polygon() // 選中框-矩形輪廓.fill('none').stroke({width: 1, color: '#4d84ff'}).hide();// 選中框的 6個 縮放控制點 const scaleGrips = (() => { ... }) 復制代碼

SVG('svgcanvas') 的意思是在 id 為 svgcanvas 的元素下創建一個根部 svg。

// 參數配置 const config = {bgcolor: '#fff',contentW: 517,contentH: 384, }// 初始化 svgContent.size(config.contentW, config.contentH).move(config.contentW, config.contentH); // 設置寬高和左上角坐標 canvasBg.size(config.contentW, config.contentH).move(config.contentW, config.contentH); svgRoot.size(config.contentW * 3, config.contentH * 3); workarea.scroll( (svgRoot.width() - workarea.w())/2, (svgRoot.height() - workarea.h())/2 ); // 滾動條拖到中間 canvasBg.rect('100%', '100%').fill(config.bgcolor); // canvasBg 添加 白色 rect,實現達到填充背景色效果 復制代碼

svgcontent(繪制層)的寬為 w,高為 h。則有:

  • svgroot 的寬為 w * 3, 高為 h * 3;
  • canvasbg 的寬為 w,高為 h;
  • workarea 的 scrollLeft 為 (w * 3 - workarea.width) / 2,(w * 3 - workarea.height) / 2。(使畫布位于視口層的正中心)

最后我們用代碼繪制一個 path,并調用寫好的 showSelectedBox() 方法,顯示它的選中框。

結尾

這篇文章主要講述了 svg 編輯器的層次結構(DOM結構)設計和這樣設計的原因,并簡單講述了 svg 編輯器初始化時需要做的事情。

下一篇系列文章的內容應該是講解如何進行工具(如選擇工具切換為鋼筆工具)的激活和切換,以及如何配合事件響應函數實現其中一個簡單的工具功能。

總結

以上是生活随笔為你收集整理的基于Web的svg编辑器(2)——层次结构设计(DOM结构)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。