當地圖放大(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/
是否可以不縮放標記大小?謝謝
uj5u.com熱心網友回復:
基本上,這個標記必須像任何其他具有由絕對數量指定的尺寸的 svg 物件一樣對待。對于您所做的州邊界
.attr("stroke-width", 1.5 / scale "px")
image.width對于標記,您需要分別縮放以或指定的每個屬性image.height。您可以使用定位標記
.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})`);
我會直接縮放坐標而不是這個模糊的變換;)
注意:因為它看起來確實像標記正在改變它的大小,所以我在不移動和縮放的circle外部添加了一個額外的。group大小的變化似乎是一種視覺錯覺。
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>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/443687.html
標籤:javascript d3.js
