ScaleIndicatorControl class
A scale indicator control displays information about the current map scale.
class ScaleIndicatorControl extends MapControl {
static const SVG_CONTENT = """<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
width="200"
height="100"
version="1.1">
<g class="scale-indicator-control">
<g class="scale-kilometers">
<rect class="bar" x="0" y="0" width="100" height="15"/>
<text class="label" x="5" y="12">1000 km</text>
</g>
<g class="scale-miles">
<rect class="bar" x="0" y="20" width="100" height="15"/>
<text class="label" x="5" y="32">500 mi</text>
</g>
</g>
</svg>
""";
@override
ScaleIndicatorControl([MapViewport map]): super(map);
@override
void build() {
_root = new Element.tag("div");
var svg = new SvgElement.svg(SVG_CONTENT);
var size = _map.viewportSize;
var y = size.height - 100;
_root.style
..position = "relative"
..left = "20px"
..top = "${y}px"
..width="200px"
..height = "100px";
_root.children.add(svg);
_subscriptions.add(
_map.onPropertyChanged
.where((e) => e.name == "zoom")
.listen((e) => _refresh())
);
_refresh();
}
_100PixelDistance() {
var zh = _map.zoomPlaneSize.width;
var w = _map.crs.projectedBounds.width;
var dist = 100 / zh * w;
return dist;
}
String _formatMeterDistance(m) {
if (m > 1000) {
m = m ~/ 1000;
m = m.round().toInt();
return "$m km";
} else if (m > 0) {
m = m.round().toInt();
return "$m m";
} else if (m < 0) {
m = (m * 100).round().toInt();
return "$m cm";
}
}
String _formatMilesDistance(ft) {
if (ft > 5000) {
ft = (ft * 0.000189394).round().toInt();
return "$ft mi";
} else if (ft > 0) {
ft = ft.round().toInt();
return "$ft ft";
} else {
ft = (ft * 10).round().toInt();
return "$ft in";
}
}
_refresh() {
var m = _100PixelDistance();
var ft = m * 3.28084;
_root.query(".scale-kilometers text").text = _formatMeterDistance(m);
_root.query(".scale-miles text").text = _formatMilesDistance(ft);
}
@override
get defaultPosition {
if (map != null) {
var vs = map.viewportSize;
if (vs.width != 0 && vs.height != 0) {
return new Point2D(20, vs.height - 150);
} else {
return null;
}
}
return null;
}
@override
void layout() {
applyPosition();
}
}
Extends
MapControl > ScaleIndicatorControl
Static Properties
const SVG_CONTENT #
static const SVG_CONTENT = """<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" width="200" height="100" version="1.1"> <g class="scale-indicator-control"> <g class="scale-kilometers"> <rect class="bar" x="0" y="0" width="100" height="15"/> <text class="label" x="5" y="12">1000 km</text> </g> <g class="scale-miles"> <rect class="bar" x="0" y="20" width="100" height="15"/> <text class="label" x="5" y="32">500 mi</text> </g> </g> </svg> """
Constructors
new ScaleIndicatorControl([MapViewport map]) #
@override ScaleIndicatorControl([MapViewport map]): super(map);
Properties
final defaultPosition #
the default position of the control if no position has been
set explicitly using placeAt.
Override in subclasses.
docs inherited from MapControl
@override
get defaultPosition {
if (map != null) {
var vs = map.viewportSize;
if (vs.width != 0 && vs.height != 0) {
return new Point2D(20, vs.height - 150);
} else {
return null;
}
}
return null;
}
final MapViewport map #
inherited from MapControl
the map this control is attached to, or null
MapViewport get map => _map;
final Element root #
inherited from MapControl
the root DOM element for this map control
Element get root => _root;
Methods
void applyPosition() #
inherited from MapControl
Applies the current position to the appropriate DOM element.
void applyPosition() {
if (root == null) return;
var pos = _position == null ? defaultPosition : _position;
if (pos == null) {
//TODO: log a warning ?
return;
}
root.style
..left = "${pos.x}px"
..top = "${pos.y}px";
}
void attach(MapViewport viewport) #
inherited from MapControl
Attaches this control to the map viewport.
void attach(MapViewport viewport) {
_require(viewport != null, "viewport must not be null");
// already attached ?
if (_map != null) {
if (_map == viewport) {
return; // don't attach again
} else {
detach(); // detach the currently attached, then attach the new one
}
}
this._map = viewport;
var controlsPane = _map.controlsPane;
//TODO: log a warning?
if (controlsPane == null) return;
build();
controlsPane.controls.add(this);
controlsPane.root.children.add(root);
applyPosition();
}
void build() #
Abstract method which builds the DOM tree for the control. Override in subclasses.
docs inherited from MapControl
@override
void build() {
_root = new Element.tag("div");
var svg = new SvgElement.svg(SVG_CONTENT);
var size = _map.viewportSize;
var y = size.height - 100;
_root.style
..position = "relative"
..left = "20px"
..top = "${y}px"
..width="200px"
..height = "100px";
_root.children.add(svg);
_subscriptions.add(
_map.onPropertyChanged
.where((e) => e.name == "zoom")
.listen((e) => _refresh())
);
_refresh();
}
void detach() #
inherited from MapControl
Detaches this control from the map viewport it is currently attached to (if any).
void detach() {
if (_map == null) return;
if (_root == null) return;
if (_map._controlsPane == null) return;
_map.controlsPane.root.children.remove(root);
_subscriptions.forEach((s) => s.cancel());
_subscriptions.clear();
}
void layout() #
Invoke this to force to (re-)layout the map control in the current map viewport.
docs inherited from MapControl
@override
void layout() {
applyPosition();
}
void placeAt(int x, int y) #
inherited from MapControl
Places the control at the position ( x, y).
void placeAt(int x, int y) {
_position = new Point2D(x,y);
applyPosition();
}