簡體   English   中英

使用 D3 在外部加載的 svg 上縮放到路徑的邊界框

[英]Zoom to bounding box of path on externally loaded svg using D3

我正在使用 D3 加載一個不使用 topojson 的外部 SVG 地圖(因為該地圖是手工創建的,而不是傳統地圖)。 我正在嘗試定位元素#lines path以便在單擊時,每個路徑都會縮放並填充其邊界框。

我正在嘗試使用 Mike Bostock 的這個示例,但無法弄清楚如何使用不使用 topojson 的數據復制它。 看到這一行:

.data(topojson.feature(us, us.objects.states).features)

這甚至可能嗎?

這是我用來加載 SVG 的代碼。

var mapContainer = $('.map');

d3.xml("../assets/subwaymap.svg", function(error, subwayMap) {
  if (error) throw error;
  $('.map').append(subwayMap.documentElement)

我嘗試使用.getBBOX獲取邊界框,但對它的連接方式感到困惑。 似乎我見過的所有示例都使用d3.create("svg")然后添加其中的所有功能,但是由於我的數據已經附加到 DOM 中,這是否有必要? D3 相當新。 謝謝!

兩個初步考慮: d3.create("svg")在實際 D3 代碼中很少使用。 此外,您沒有將數據附加到 DOM,只有您加載的 SVG 元素(除非您調用該“數據” )。

回到你的問題,你不需要path.bounds來讓你的代碼工作,實際上你甚至不需要d3.zoom 您所需要的只是獲取元素的框(使用getBBox )並進行適當的轉換。

但是,真正的問題是您需要將所有元素包裝在<g> ,因為您無法將轉換應用於 SVG 1.1 中的根 SVG(顯然這在 SVG 2 中是可能的)。

這是一個基本的演示。 在這個演示中,我使用了一個由不同元素(圓形、矩形、文本...)組成的外部 SVG,它代表您要附加的 SVG。 您可以通過以下方式獲得此 SVG:

const svg = d3.select("svg");

然后,考慮到你以某種方式設法解決了我提到的<g>問題,你得到了那個組......

const g = svg.select("g");

...然后選擇要放大的元素(此處為所有內容),綁定事件偵聽器:

const elements = g.selectAll("*")
    .on("click", clicked);

在這個演示中,我使用 Bostock 的數學來節省(我的)時間,但您可以更改它。 單擊元素可放大,再次單擊可縮小。

 const width = 500, height = 400; const svg = d3.select("svg"); const g = svg.select("g"); const elements = g.selectAll("*") .each(function() { d3.select(this).datum({}) }) .on("click", clicked); function clicked(d) { d.clicked = !d.clicked; const bounds = this.getBBox(); const x0 = bounds.x; const x1 = bounds.x + bounds.width; const y0 = bounds.y; const y1 = bounds.y + bounds.height; g.transition().duration(1000).attr("transform", d.clicked ? "translate(" + (width / 2) + "," + (height / 2) + ") scale(" + (1 / Math.max((x1 - x0) / width, (y1 - y0) / height)) + ") translate(" + (-(x0 + x1) / 2) + "," + (-(y0 + y1) / 2) + ")" : "transform(0,0) scale(1)"); }
 <svg width="500" height="400"> <g> <circle cx="50" cy="50" r="30" stroke="black" stroke-width="3" fill="teal"></circle> <rect x="300" y="20" rx="20" ry="20" width="150" height="150" style="fill:tomato;stroke:black;stroke-width:3"/> <polygon points="200,100 250,190 160,210" style="fill:lavender;stroke:purple;stroke-width:3" /> <path d="M 140 350 q 150 -200 350 0" stroke="blue" stroke-width="5" fill="none" /> <text x="30" y="300" transform="rotate(-30, 30, 300)">Foo Bar Baz</text> </g> </svg> <script src="https://d3js.org/d3.v5.min.js"></script>

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM