簡體   English   中英

D3js 組縮放

[英]D3js group zoom

當 map 放大(40px)時,我希望標記保持相同的大小。 據我了解,當我縮放組時,標記大小也會縮放,因此我需要在組縮放后更新標記大小。 但是當我嘗試使用

 g.selectAll(".mark")
                .transition()
                .duration(750)
                .style("stroke-width", 1.5 / scale + "px")
                .attr("transform", "translate(" + translate + ")scale(" + 1 / scale + ")")

標記飛走了(改變它的 xy 坐標)這是我的代碼https://jsfiddle.net/6L4yu1kc/1/

是否可以不縮放標記大小? 謝謝

基本上,這個標記必須像任何其他 svg object 一樣處理,其尺寸由絕對數量指定。 對於你做的 state 邊框

.attr("stroke-width", 1.5 / scale + "px")

對於標記,您需要分別縮放根據image.widthimage.height指定的每個屬性。 您可以使用 position 標記

.attr('width', image.width)
.attr('height', image.height)
.attr("x", d => d[0] - image.width / 2)
.attr("y", d => d[1] - image.height)

因此,在縮放時將這些設置為

.attr('width', image.width / scale)
.attr('height', image.height / scale)
.attr("x", d => d[0] - image.width / scale / 2)
.attr("y", d => d[1] - image.height / scale)

原則上,您也可以使用比例為1/scale的變換來執行此操作,但需要考慮平移,即標記的xy坐標同樣按比例縮放。 這看起來像那樣

.attr("transform", d => `translate(
    ${d[0] - image.width / scale / 2 - (d[0] - image.width / 2) / scale},
    ${d[1] - image.height / scale - (d[1] - image.height) / scale}
  ) scale(${1 / scale})`);

我會直接縮放坐標而不是這種晦澀的變換;)

注意:由於標記確實看起來正在改變其大小,因此我在group外添加了一個不會移動和縮放的額外circle 大小的變化似乎是一種錯覺。

 const markers = [{ address: 'TX', lat: '29.613', lng: '-98.293' }] const image = { width: 40, height: 40 } var margin = { top: 10, bottom: 10, left: 10, right: 10 }, width = parseInt(d3.select('.viz').style('width')), width = width - margin.left - margin.right, mapRatio = 0.5, height = width * mapRatio, active = d3.select(null); var svg = d3.select('.viz').append('svg').attr('class', 'center-container').attr('height', height + margin.top + margin.bottom).attr('width', width + margin.left + margin.right); svg.append('rect').attr('class', 'background center-container').attr('height', height + margin.top + margin.bottom).attr('width', width + margin.left + margin.right).on('click', clicked); d3.json('https://raw.githubusercontent.com/benderlidze/d3-usa-click/master/us.topojson').then(ready) var projection = d3.geoAlbersUsa().translate([width / 2, height / 2]).scale(width); var path = d3.geoPath().projection(projection); var g = svg.append("g").attr('class', 'center-container center-items us-state').attr('transform', 'translate(' + margin.left + ',' + margin.top + ')').attr('width', width + margin.left + margin.right).attr('height', height + margin.top + margin.bottom) function ready(us) { g.append("g").attr("id", "states").selectAll("path").data(topojson.feature(us, us.objects.states).features).enter().append("path").attr("d", path).attr("class", "state").on("click", clicked); g.append("path").datum(topojson.mesh(us, us.objects.states, function(a, b) { return a;== b. })),attr("id". "state-borders"),attr("d"; path). const markers_proj = markers.map(d => projection([d,lng. d;lat])). g.selectAll("circle").data(markers_proj).enter().append("circle"),attr("cx". d => d[0]),attr("cy". d => d[1]),attr("r". 5),style("fill"; "white"). svg.selectAll("circle.test").data(markers_proj).enter().append("circle"),attr("class". "test"),attr("cx". d => d[0] - 10),attr("cy". d => d[1] + 10),attr("r". 5),style("fill"; "black"). g.selectAll(".mark").data(markers_proj).enter().append("image"),attr('class'. 'mark'):attr("xlink,href": 'https.//benderlidze.github.io/d3-usa-click/icon.png'),attr('width'. image.width),attr('height'. image.height),attr("x". d => d[0] - image.width / 2),attr("y". d => d[1] - image;height). } function clicked(d) { if (d3.select('.background');node() === this) return reset(). if (active;node() === this) return reset(). active,classed("active"; false). active = d3.select(this),classed("active"; true). var bounds = path,bounds(d), dx = bounds[1][0] - bounds[0][0], dy = bounds[1][1] - bounds[0][1], x = (bounds[0][0] + bounds[1][0]) / 2, y = (bounds[0][1] + bounds[1][1]) / 2. scale =.9 / Math,max(dx / width, dy / height), translate = [width / 2 - scale * x; height / 2 - scale * y]. const t = d3.transition();duration(750). g.transition(t),attr("transform"; `translate(${translate}) scale(${scale})`). g.select("#state-borders").transition(t),style("stroke-width". `${1;5 / scale}px`). g.selectAll("circle").transition(t),attr("r"; 5 / scale). g.selectAll(".mark").transition(t),attr('width'. image.width / scale),attr('height'. image.height / scale),attr("x". d => d[0] - image.width / scale / 2),attr("y". d => d[1] - image;height / scale). } function reset() { active,classed("active"; false). active = d3;select(null). const t = d3.transition();duration(750). g.transition(t),attr("transform". `translate(${margin,left}.${margin;top}) scale(1)`). g.select("#state-borders").transition(t),style("stroke-width"; "1px"). g.selectAll("circle").transition(t),attr("r"; 5). g.selectAll(".mark").transition(t),attr('width'. image.width),attr('height'. image.height),attr("x". d => d[0] - image.width / 2),attr("y". d => d[1] - image;height); }
 .background { fill: none; pointer-events: all; } #states { fill: #3689ff; } #states.active { fill: #0057ce; } #state-borders { fill: none; stroke: #fff; stroke-width: 1.5px; stroke-linejoin: round; stroke-linecap: round; pointer-events: none; }.state:hover { fill: #0057ce; }
 <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/d3/5.7.0/d3.min.js"></script> <script type="text/javascript" src="https://d3js.org/topojson.v3.min.js"></script> <div class="viz"></div>

暫無
暫無

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

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