Tile class
Tile represents a map tile.
class Tile {
/// indicates that the tile is loading the tile image
static const LOADING = 0;
/// indicates that the tile image is ready for rendering
static const READY = 1;
/// indicates that an error occured when loading the tile image
static const ERROR= 2;
/// the tile coordinats
final Point2D tc;
/// the layer this tile is rendered on
final TileLayer layer;
CanvasElement _canvas;
ImageElement _img;
int _state = LOADING;
/**
* Creates a tile at tile coordinates [tc] = (ti, tj)
* for the layer [layer]. It will be rendered on
* [_canvas].
*/
Tile(this.tc, this._canvas, this.layer);
/**
* Detach the tile from the map viewport.
*
* A detached tile whose image becomes available isn't
* rendered anymore.
*/
void detach() => _canvas = null;
/**
* Trigger loading of the tile image.
*/
void load() {
var url = layer.bindTileToUrl(tc.x, tc.y, layer.map.zoom);
_img = _DEFAULT_CACHE.lookup(url,
onLoad: (e) {
_state = READY;
render();
},
onError: (e) {
_state = ERROR;
render();
}
);
_state = _img.complete ? READY : LOADING;
render();
}
/// the top left corner in viewport coordinates where the tile
/// should be rendered
Point2D get _topLeftInViewport =>
layer.map.zoomPlaneToViewport(tc.scale(
sx: layer.tileSize.width,
sy: layer.tileSize.height
));
void _renderReady() {
if (_canvas == null) return;
var context = _canvas.context2D;
context.globalAlpha = layer.opacity;
var tl = _topLeftInViewport;
var ts = layer.tileSize;
context.clearRect(tl.x, tl.y, ts.width, ts.height);
context.drawImage(_img, tl.x, tl.y);
}
/// Returns the image of the parent tile of this tile, provided
/// there is a parent tile and its image is already in the cache.
/// Otherwise returns [:null:].
ImageElement get _parentImage {
var z = layer.map.zoom;
if (z == 0) return null;
z--;
var ti = tc.x ~/ 2;
var tj = tc.y ~/ 2;
var url = layer.bindTileToUrl(ti, tj, z);
var img = _DEFAULT_CACHE.get(url);
return img;
}
void _renderLoading() {
var img = _parentImage;
var context = _canvas.context2D;
if (img == null) {
var tl = _topLeftInViewport;
var ts = layer.tileSize;
context.clearRect(tl.x,tl.y, ts.width, ts.height);
} else {
var tl = _topLeftInViewport;
var ts = layer.tileSize;
// the quadrant of the parent tile to be rendered (scaled by 2)
// in place of the current tile
var src = new html.Rect(
(tc.x % 2) * ts.width ~/ 2,
(tc.y % 2) * ts.height ~/ 2,
ts.width ~/ 2,
ts.height ~/ 2
);
// the rectangle where the current tile is rendered
var dest = new html.Rect(tl.x, tl.y, ts.width, ts.height);
context.drawImageToRect(img,dest,sourceRect:src);
}
}
void _renderError() {
var context = _canvas.context2D;
context.globalAlpha = layer.opacity;
var ts = layer.tileSize;
var tl = _topLeftInViewport;
var center =
new Point2D(tl.x, tl.y)
+ (new Point2D(ts.width, ts.height) / 2).toInt();
context
..save()
..strokeStyle="rgba(255,0,0,0.5)"
..lineWidth=10
..beginPath()
..arc(center.x, center.y, 50, 0, math.PI * 2, true)
..stroke()
..beginPath()
..moveTo(center.x - 30, center.y -30)
..lineTo(center.x + 30, center.y + 30)
..moveTo(center.x - 30, center.y + 30)
..lineTo(center.x +30 , center.y - 30)
..stroke()
..restore()
;
}
/// renders the tile
void render() {
if (_canvas == null) return;
switch(_state) {
case LOADING: _renderLoading(); break;
case READY: _renderReady(); break;
case ERROR: _renderError(); break;
}
}
}
Static Properties
const ERROR #
indicates that an error occured when loading the tile image
static const ERROR= 2
const LOADING #
indicates that the tile is loading the tile image
static const LOADING = 0
const READY #
indicates that the tile image is ready for rendering
static const READY = 1
Constructors
new Tile(Point2D tc, CanvasElement _canvas, TileLayer layer) #
Creates a tile at tile coordinates tc = (ti, tj) for the layer layer. It will be rendered on _canvas.
Tile(this.tc, this._canvas, this.layer);
Properties
Methods
void detach() #
Detach the tile from the map viewport.
A detached tile whose image becomes available isn't rendered anymore.
void detach() => _canvas = null;
void load() #
Trigger loading of the tile image.
void load() {
var url = layer.bindTileToUrl(tc.x, tc.y, layer.map.zoom);
_img = _DEFAULT_CACHE.lookup(url,
onLoad: (e) {
_state = READY;
render();
},
onError: (e) {
_state = ERROR;
render();
}
);
_state = _img.complete ? READY : LOADING;
render();
}
void render() #
renders the tile
void render() {
if (_canvas == null) return;
switch(_state) {
case LOADING: _renderLoading(); break;
case READY: _renderReady(); break;
case ERROR: _renderError(); break;
}
}