tile-painter
Version:
Parse Mapbox style documents into rendering functions
64 lines (47 loc) • 1.95 kB
JavaScript
import { initRenderer } from "./renderer.js";
export { initPainterOnly, initPainter, addPainters } from "./wrappers.js";
export function initMapPainter(params) {
const { context, styleLayer, spriteObject, tileSize = 512 } = params;
const painter = initRenderer(styleLayer, spriteObject, tileSize);
if (!painter) return () => null;
// TODO: should maxzoom be limited to 24? See the Mapbox style spec
const { id, type, source, minzoom = 0, maxzoom = 99 } = styleLayer;
const getData = (type === "raster")
? (source) => source
: (source) => source[id];
const clipRect = context.clipRect || clip2d;
const paint = (type === "background")
? paintBackground
: paintTile;
Object.assign(paint, { id, type, source, minzoom, maxzoom });
function paintBackground({ zoom }) {
// Background layer: just fill the whole canvas, no transform or clip
context.save();
painter(context, zoom); // No data needed
context.restore();
}
function paintTile({ source, position, crop, zoom, boxes }) {
// Input source is one tile's data for a single source,
// which for vector sources, could include multiple layers
let data = getData(source);
if (!data) return false;
context.save();
// Set clipping mask, to limit rendering to the desired output area
clipRect(position.x, position.y, position.w, position.w);
// Transform coordinates to align the crop portion of the source
// with the target position on the canvas
let scale = position.w / crop.w;
let tx = position.x - scale * crop.x;
let ty = position.y - scale * crop.y;
context.setTransform(scale, 0, 0, scale, tx, ty);
painter(context, zoom, data, boxes, scale);
context.restore();
return true; // Indicate that canvas has changed
}
function clip2d(x, y, width, height) {
let area = new Path2D();
area.rect(x, y, width, height);
context.clip(area);
}
return paint;
}