首頁 >web前端 >css教學 >如何從DOM轉換為SVG坐標並再次返回

如何從DOM轉換為SVG坐標並再次返回

Joseph Gordon-Levitt
Joseph Gordon-Levitt原創
2025-02-10 10:05:12379瀏覽

How to Translate from DOM to SVG Coordinates and Back Again

關鍵要點

  • SVG擁有自身基於viewBox屬性定義的坐標系,可縮放至任意尺寸。這使得根據光標位置添加SVG元素變得複雜,尤其是在響應式設計中。
  • 嵌入HTML頁面的SVG成為DOM的一部分,可像其他元素一樣操作。這允許完全避免坐標系間的轉換。
  • 從DOM到SVG坐標的轉換可通過getBoundingClientRect()方法提取位置和尺寸來實現。然而,從SVG到DOM坐標的轉換更具挑戰性,需要使用SVG自身的矩陣分解機制。
  • SVG或單個元素可以通過平移、縮放、旋轉和/或傾斜進行變換,這會影響最終的SVG坐標。 .getScreenCTM()方法可應用於任何元素以及SVG本身,以考慮所有變換。

使用SVG相對簡單——直到您想混合DOM和矢量交互。

SVGs在其viewBox屬性中定義了自己的坐標系。例如:

<code class="language-xml"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 800 600"></svg></code>

這設置了從0,0開始的800單位寬度和600單位高度。這些單位是用於繪圖的任意測量單位,可以使用單位的小數部分。如果您將此SVG放置在800 x 600像素的區域中,每個SVG單位應該直接映射到一個屏幕像素。

但是,矢量圖像可以縮放至任意大小——尤其是在響應式設計中。您的SVG可以縮小到400 x 300,甚至可以在10 x 1000的空間中拉伸變形。如果您想根據光標位置放置它們,則向此SVG添加更多元素會變得更加困難。

注意:有關SVG坐標的更多信息,請參閱Sara Soueidan的視口、viewBox和preserveAspectRatio文章。

避免坐標轉換

您也許能夠完全避免坐標系之間的轉換。

嵌入HTML頁面(而不是圖像或CSS背景)的SVG成為DOM的一部分,可以像其他元素一樣進行操作。例如,一個包含單個圓的基本SVG:

<code class="language-xml"><svg id="mysvg" xmlns="https://www.w3.org/2000/svg" viewbox="0 0 800 600" preserveaspectratio="xMidYMid meet">
  <circle id="mycircle" cx="400" cy="300" r="50"></circle>
</svg></code>

您可以對其應用CSS效果:

<code class="language-css">circle {
  stroke-width: 5;
  stroke: #f00;
  fill: #ff0;
}

circle:hover {
  stroke: #090;
  fill: #fff;
}</code>

您還可以附加事件處理程序來修改屬性:

<code class="language-javascript">const mycircle = document.getElementById('mycircle');

mycircle.addEventListener('click', (e) => {
  console.log('circle clicked - enlarging');
  mycircle.setAttribute('r', 60);
});</code>

下面的示例向SVG圖像添加三十個隨機圓圈,在CSS中應用懸停效果,並在單擊圓圈時使用JavaScript將半徑增加十個單位。

查看CodePen上的示例

SVG到DOM坐標轉換

可能需要將DOM元素疊加在SVG元素之上——例如,在世界地圖上顯示的活動國家/地區上顯示菜單或信息框。假設SVG嵌入到HTML中,元素成為DOM的一部分,因此可以使用getBoundingClientRect()方法提取位置和尺寸。 (在上面的示例中打開控制台,以顯示半徑增加後單擊圓圈的新屬性。)

Element.getBoundingClientRect()在所有瀏覽器中都受支持,並返回一個DOMRect對象,其中包含以下像素尺寸屬性:

  • .x.left:元素左側相對於視口原點的x坐標
  • .right:元素右側相對於視口原點的x坐標
  • .y.top:元素頂部相對於視口原點的y坐標
  • .bottom:元素底部相對於視口原點的y坐標
  • .width:元素的寬度(在IE8及以下版本中不受支持,但與.right減去.left相同)
  • .height:元素的高度(在IE8及以下版本中不受支持,但與.bottom減去.top相同)

所有坐標都相對於瀏覽器視口,因此在頁面滾動時會發生變化。可以通過將window.scrollX添加到.leftwindow.scrollY添加到.top來計算頁面上的絕對位置。

DOM到SVG坐標轉換

這更具挑戰性。假設您想將新的SVG元素放置在其viewBox上單擊事件發生的位置。事件處理程序對象提供DOM .clientX.clientY像素坐標,但必須將其轉換為SVG單位。

您可能會認為可以通過應用乘法因子來計算SVG點的坐標。例如,如果1000單位寬度的SVG放置在500像素寬的容器中,您可以將任何DOM x坐標乘以2以獲得SVG位置。 這行不通! …

  • 不能保證SVG完全適合您的容器。
  • 如果元素尺寸發生變化——也許是響應用戶調整瀏覽器大小——則必須重新計算寬度和高度因子。
  • SVG或一個或多個元素可以在2D或3D空間中進行變換。
  • 即使您克服了這些障礙,它也永遠不會像您預期的那樣工作,並且經常存在誤差。

幸運的是,SVG提供了自身的矩陣分解機制來轉換坐標。第一步是使用createSVGPoint()方法在SVG上創建一個點,並將屏幕/事件x和y坐標傳入:

<code class="language-xml"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 800 600"></svg></code>

然後,您可以應用從SVG的.getScreenCTM()方法的逆矩陣創建的矩陣變換,該方法將SVG單位映射到屏幕坐標:

<code class="language-xml"><svg id="mysvg" xmlns="https://www.w3.org/2000/svg" viewbox="0 0 800 600" preserveaspectratio="xMidYMid meet">
  <circle id="mycircle" cx="400" cy="300" r="50"></circle>
</svg></code>

svgP現在具有.x.y屬性,它們提供SVG viewBox上的坐標。

以下代碼將圓圈放置在SVG畫布上單擊的點處:

<code class="language-css">circle {
  stroke-width: 5;
  stroke: #f00;
  fill: #ff0;
}

circle:hover {
  stroke: #090;
  fill: #fff;
}</code>

注意:createElementNS()方法與標準DOM createElement()方法相同,只是它指定了一個XML命名空間URI。換句話說,它作用於SVG文檔而不是HTML。

轉換為變換的SVG坐標

還有一個更複雜的方面。 SVG或單個元素可以通過平移、縮放、旋轉和/或傾斜進行變換,這會影響最終的SVG坐標。例如,以下<g></g>圖層比標準SVG單位大4倍,因此坐標將是包含SVG坐標的四分之一:

<code class="language-xml"><svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 800 600"></svg></code>

生成的矩形看起來在位置200, 200處具有400單位的寬度和高度。

幸運的是,.getScreenCTM()方法可以應用於任何元素以及SVG本身。生成的矩陣考慮所有變換,因此您可以創建一個簡單的svgPoint()轉換函數:

<code class="language-xml"><svg id="mysvg" xmlns="https://www.w3.org/2000/svg" viewbox="0 0 800 600" preserveaspectratio="xMidYMid meet">
  <circle id="mycircle" cx="400" cy="300" r="50"></circle>
</svg></code>

以下演示在所有現代瀏覽器中都能工作,(如果您將JavaScript轉換為ES5,則在IE11中也能工作!)。當點擊/點擊SVG時,會在光標點添加一個圓圈。

當點擊變換的<g></g>區域時也會發生這種情況,但是將該元素而不是SVG本身傳遞給svgPoint()函數以確保計算正確的坐標:

查看CodePen上的示例

理想情況下,最好避免DOM到/從SVG坐標轉換,但是,當不可能這樣做時,請使用上面描述的方法來確保該過程在所有頁面尺寸下都健壯。

關於從DOM到SVG坐標以及反向轉換的常見問題解答

DOM和SVG坐標有什麼區別?

文檔對像模型(DOM)和可縮放矢量圖形(SVG)都是Web開發的組成部分,但它們具有不同的用途。 DOM是HTML和XML文檔的編程接口。它表示文檔的結構,並提供了一種操作其內容和視覺表示的方法。另一方面,SVG是一種基於XML的矢量圖像格式,用於二維圖形。兩者之間的主要區別在於它們的坐標系。 DOM使用基於像素的坐標系,而SVG使用基於viewBox屬性的系統,該系統可以縮放和轉換。

如何將DOM坐標轉換為SVG坐標?

將DOM坐標轉換為SVG坐標涉及使用SVG元素的createSVGPoint方法在SVG坐標系中創建一個點。然後,您可以使用matrixTransform方法將該點轉換為SVG坐標系。此方法採用DOMMatrix對象,該對象表示SVG元素的變換矩陣。

如何將SVG坐標轉換回DOM坐標?

要將SVG坐標轉換回DOM坐標,您可以使用SVGMatrix對象的inverse方法。此方法返回一個新的SVGMatrix對象,它是原始矩陣的逆矩陣。通過將SVG點乘以此逆矩陣,您可以將其轉換回DOM坐標系。

viewBox屬性在SVG中的作用是什麼?

SVG中的viewBox屬性用於指定SVG圖像的縱橫比和坐標系。它允許您控制SVG元素的縮放和定位。 viewBox屬性採用四個值:min-x、min-y、width和height。這些值定義了SVG坐標系中的矩形。

如何在我的項目中使用DOM到SVG包?

DOM到SVG包是用於將DOM坐標轉換為SVG坐標以及反向轉換的有用工具。要在您的項目中使用它,您需要使用npm(JavaScript編程語言的包管理器)安裝它。安裝後,您可以在JavaScript文件中引入它並使用其方法執行轉換。

SVG中的cx屬性是什麼?

SVG中的cx屬性用於指定圓心x坐標。它是創建SVG圓的基本屬性之一。 cx屬性的值是用戶坐標系中的長度。

我可以在網頁中同時使用DOM和SVG嗎?

是的,您可以在網頁中同時使用DOM和SVG。 SVG嵌入在HTML中,因此它是DOM的一部分。您可以使用DOM方法和屬性來操作SVG元素。這使您能夠在網頁上創建動態和交互式圖形。

SVG中的坐標係與HTML中的坐標係有何不同?

SVG中的坐標係與HTML中的坐標係不同。在HTML中,坐標係是基於像素的,原點位於頁面的左上角。在SVG中,坐標係由viewBox屬性定義,原點位於viewBox的左上角。這使得SVG圖形可以縮放且與分辨率無關。

如何轉換SVG坐標?

您可以使用transform屬性轉換SVG坐標。此屬性允許您對SVG元素應用各種變換,例如平移、旋轉、縮放和傾斜。 transform屬性的值是變換函數列表,每個函數都按列出的順序應用於元素。

在DOM和SVG坐標之間轉換的一些常見用例是什麼?

在許多情況下,在DOM和SVG坐標之間進行轉換非常有用。例如,如果您正在創建交互式SVG圖形,您可能需要將鼠標坐標(位於DOM坐標系中)轉換為SVG坐標以操作SVG元素。相反,如果您正在創建自定義SVG元素,您可能需要將其坐標轉換回DOM坐標係以將其正確放置在頁面上。

以上是如何從DOM轉換為SVG坐標並再次返回的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn