[英]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.width
或image.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
的變換來執行此操作,但需要考慮平移,即標記的x
和y
坐標同樣按比例縮放。 這看起來像那樣
.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.