我很难在d3.js中将矩形放在文本后面作为背景。我读到为了做到这一点,你必须附加到相同的g元素,但在我的情况下,它不会那样工作。 我的代码:plunker
var urls = [{
"wor": "Nordmerika",
"number": "10.9",
"lon": "-100.33",
"lat": "47.61"
}, {
"wor": "Latinamerika",
"number": "14.2",
"lon": "-56.62",
"lat": "-8.53"
}, {
"wor": "Afrika",
"number": "51.8",
"lon": "24.5085",
"lat": "8.7832"
}, {
"wor": "Asien",
"number": "27.5",
"lon": "104.238281",
"lat": "34.51561"
}, {
"wor": "GUS | Russland",
"number": "3.4",
"lon": "62.753906",
"lat": "47.923705"
}, {
"wor": "Europa | MSOE",
"number": "10.9",
"lon": "15.2551",
"lat": "54.526"
}]
//starting map
var margin = {
top: 10,
left: 10,
bottom: 10,
right: 10
},
width = parseInt(d3.select('#map').style('width')),
width = width - margin.left - margin.right,
mapRatio = .5,
height = width * mapRatio;
//Map projection
var projection = d3.geo.equirectangular()
.scale(width / 5.8)
.translate([width / 2, height / 2]) //translate to center the map in view
//Generate paths based on projection
var path = d3.geo.path()
.projection(projection);
//Create an SVG
var svg = d3.select("#map")
.append("svg")
.attr("viewBox", "0 0 " + width + " " + height)
.attr("preserveAspectRatio", "xMinYMin");
//Group for the map features
var features = svg.append("g")
.attr("class", "features");
var labelWidths = [];
d3.json("countries.topojson", function(error, geodata) {
if (error) return console.log(error); //unknown error, check the console
var layerOne = svg.append("g");
var layerTwo = svg.append("g");
var layerThree = svg.append("g");
//Create a path for each map feature in the data
features.selectAll("path")
.data(topojson.feature(geodata, geodata.objects.subunits).features) //generate features from TopoJSON
.enter()
.append("path")
.attr("d", path)
.on("click", clicked)
.style('fill', '#cdd5db')
.style('stroke', '#ffffff')
.style('stroke-width', '0.5px')
.on('mouseover', function(d, i) {
d3.select(this).style('stroke-width', '2px');
})
.on('mouseout', function(d, i) {
d3.select(this).style('stroke-width', '0.5px');
});
var bubbles = layerOne.attr("class", "bubble")
.selectAll("circle")
.data(urls)
.enter()
.append("circle")
.attr("cx", function(d, i) {
return projection([d.lon, d.lat])[0];
})
.attr("cy", function(d, i) {
return projection([d.lon, d.lat])[1];
})
.attr("r", function(d) {
if (width >= 1000) {
return (d.number)
} else {
return d.number
}
})
.style('fill', function(d) {
if (d.wor == 'Afrika') {
return '#dc0f6e'
} else {
return '#3e3e3e'
}
});
var text = layerTwo
.attr('class', 'text')
.selectAll('text')
.data(urls)
.enter()
.append('text')
.attr('x', function(d, i) {
if (d.number < 10) {
return projection([d.lon, d.lat])[0] + 60;
} else {
return projection([d.lon, d.lat])[0]
}
})
.attr('y', function(d, i) {
return projection([d.lon, d.lat])[1];
})
.text(function(d) {
return d.number;
})
.attr("dy", function(d) {
if (this.getBBox().width > d.number * 3) {
return '-2em'
} else {
return "0.3em"
}
})
.attr("text-anchor", "middle")
.style('fill', '#fff')
.style('font-weight', 'bold')
.style('font-size', '1em');
var labels = layerThree
.attr('class', 'labels')
.selectAll('text')
.data(urls)
.enter()
.append('text')
.attr('x', function(d, i) {
return projection([d.lon, d.lat])[0] + 60;
})[plunker][1]
.attr('y', function(d, i) {
return projection([d.lon, d.lat])[1];
})
.attr("text-anchor", "middle")
.text(function(d) {
return d.wor;
})
.attr('dy', function(d) {
labelWidths.push(this.getBBox().width)
var radius = d.number * 2
if (radius > 10) {
return d.number * 4;
} else {
return '-0.5em'
}
})
.style('font-size', '1em')
.style('font-weight', 'bold');
var rect = layerThree
.attr('class', 'rectlabels')
.selectAll('rect')
.data(urls)
.enter()
.append('rect')
.attr('x', function(d, i) {
return projection([d.lon, d.lat])[0] + 60;
})
.attr('y', function(d, i) {
return projection([d.lon, d.lat])[1];
})
.attr('dy', function(d) {
return '1em'
})
.style('fill', '#ffffff')
.attr('width', function(d, i) {
return labelWidths[i] / 10 + 'em'
})
.attr('height', '1em');
function clicked(d, i) {
}
});
答案 0 :(得分:0)
看起来矩形与文本没有正确对齐,原因有两个:
<text>
锚定在中间,<rects>
锚定在<rect>
的左上角。dy
元素上以不同的金额设置<text>
,这会将文字向下移动该距离,但所有<text>
元素都有dy=1em
,所以他们没有减少相同数量。我建议您创建6个<g>
元素,每个标签一个,每个元素包含<rect>
元素和<text>
元素。那么你只需要设置x
&amp; <{1}}元素上的y
属性,它的子节点应该保持在一起。
我认为您还应该尝试删除<g>
属性,而是将text-anchor
元素向左移动一半宽度(<g>
)以使其在坐标上居中。由于您的宽度为(labelWidths[i] / 10) / 2
单位,因此您可能需要以像素为单位进行相应调整。
尝试不使用em
元素,看看这是否有助于垂直对齐。