map/labels: dynamic labels (zoom levels, sizes)

This commit is contained in:
Nils Schneider 2015-04-21 16:28:06 +02:00
parent fc921e6c59
commit d5a9c52788

View File

@ -9,9 +9,7 @@ define(["leaflet", "rbush"],
["center", "ideographic", 2 / 8], ["center", "ideographic", 2 / 8],
["right", "ideographic", 3 / 8]] ["right", "ideographic", 3 / 8]]
var labelOffset = 8 var fontFamily = "Roboto"
var font = "10px Roboto"
var labelHeight = 12
var nodeRadius = 4 var nodeRadius = 4
var ctx = document.createElement("canvas").getContext("2d") var ctx = document.createElement("canvas").getContext("2d")
@ -29,20 +27,25 @@ define(["leaflet", "rbush"],
return o return o
} }
function prepareLabel(fillStyle) { function prepareLabel(fillStyle, fontSize, offset, stroke, minZoom) {
return function (d) { return function (d) {
var font = fontSize + "px " + fontFamily
return { position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude), return { position: L.latLng(d.nodeinfo.location.latitude, d.nodeinfo.location.longitude),
label: d.nodeinfo.hostname, label: d.nodeinfo.hostname,
offset: offset,
fillStyle: fillStyle, fillStyle: fillStyle,
height: labelHeight, height: fontSize * 1.2,
font: font,
stroke: stroke,
minZoom: minZoom,
width: measureText(font, d.nodeinfo.hostname).width width: measureText(font, d.nodeinfo.hostname).width
} }
} }
} }
function calcOffset(loc) { function calcOffset(offset, loc) {
return [ labelOffset * Math.cos(loc[2] * 2 * Math.PI), return [ offset * Math.cos(loc[2] * 2 * Math.PI),
-labelOffset * Math.sin(loc[2] * 2 * Math.PI)] -offset * Math.sin(loc[2] * 2 * Math.PI)]
} }
function labelRect(p, offset, anchor, label) { function labelRect(p, offset, anchor, label) {
@ -84,10 +87,10 @@ define(["leaflet", "rbush"],
// - label (string) // - label (string)
// - color (string) // - color (string)
var labelsOnline = d.online.map(prepareLabel("rgba(0, 0, 0, 0.9)")) var labelsOnline = d.online.map(prepareLabel("rgba(0, 0, 0, 0.9)", 10, 8, true, 13))
var labelsOffline = d.offline.map(prepareLabel("rgba(212, 62, 42, 0.9)")) var labelsOffline = d.offline.map(prepareLabel("rgba(212, 62, 42, 0.9)", 9, 5, false, 16))
var labelsNew = d.new.map(prepareLabel("rgba(85, 128, 32, 0.9)")) var labelsNew = d.new.map(prepareLabel("rgba(48, 99, 20, 0.9)", 11, 8, true, 0))
var labelsLost = d.lost.map(prepareLabel("rgba(212, 62, 42, 0.9)")) var labelsLost = d.lost.map(prepareLabel("rgba(212, 62, 42, 0.9)", 11, 8, true, 0))
var labels = [] var labels = []
.concat(labelsNew) .concat(labelsNew)
@ -115,12 +118,12 @@ define(["leaflet", "rbush"],
trees[z].load(labels.map(nodeToRect(z))) trees[z].load(labels.map(nodeToRect(z)))
} }
labels.forEach(function (d) { labels = labels.map(function (d) {
var best = labelLocations.map(function (loc) { var best = labelLocations.map(function (loc) {
var offset = calcOffset(loc, d) var offset = calcOffset(d.offset, loc)
var z var z
for (z = maxZoom; z >= minZoom; z--) { for (z = maxZoom; z >= d.minZoom; z--) {
var p = map.project(d.position, z) var p = map.project(d.position, z)
var rect = labelRect(p, offset, loc, d) var rect = labelRect(p, offset, loc, d)
var candidates = trees[z].search(rect) var candidates = trees[z].search(rect)
@ -136,10 +139,8 @@ define(["leaflet", "rbush"],
return a.z - b.z return a.z - b.z
})[0] })[0]
if (best === undefined) if (best !== undefined) {
return d.offset = calcOffset(d.offset, best.loc)
d.offset = calcOffset(best.loc, d)
d.minZoom = best.z d.minZoom = best.z
d.anchor = best.loc d.anchor = best.loc
@ -148,11 +149,11 @@ define(["leaflet", "rbush"],
var rect = labelRect(p, d.offset, best.loc, d) var rect = labelRect(p, d.offset, best.loc, d)
trees[z].insert(rect) trees[z].insert(rect)
} }
})
labels = labels.filter(function (d) { return d
return d.minZoom !== undefined } else
}) return undefined
}).filter(function (d) { return d !== undefined })
this.margin = 16 + labels.map(function (d) { this.margin = 16 + labels.map(function (d) {
return d.width return d.width
@ -193,16 +194,19 @@ define(["leaflet", "rbush"],
var ctx = canvas.getContext("2d") var ctx = canvas.getContext("2d")
ctx.font = font
ctx.lineWidth = 5 ctx.lineWidth = 5
ctx.strokeStyle = "rgba(255, 255, 255, 0.8)" ctx.strokeStyle = "rgba(255, 255, 255, 0.8)"
ctx.miterLimit = 2 ctx.miterLimit = 2
function drawLabel(d) { function drawLabel(d) {
ctx.font = d.label.font
ctx.textAlign = d.label.anchor[0] ctx.textAlign = d.label.anchor[0]
ctx.textBaseline = d.label.anchor[1] ctx.textBaseline = d.label.anchor[1]
ctx.fillStyle = d.label.fillStyle ctx.fillStyle = d.label.fillStyle
if (d.label.stroke)
ctx.strokeText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]) ctx.strokeText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1])
ctx.fillText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1]) ctx.fillText(d.label.label, d.p.x + d.label.offset[0], d.p.y + d.label.offset[1])
} }