protomaps-leaflet
Version:
Vector tile rendering and labeling for [Leaflet](https://github.com/Leaflet/Leaflet).
101 lines (100 loc) • 4.13 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import potpack from "potpack";
// https://github.com/tangrams/tangram/blob/master/src/styles/text/font_manager.js
export const Font = (name, url, weight) => {
const ff = new FontFace(name, `url(${url})`, { weight: weight });
document.fonts.add(ff);
return ff.load();
};
const mkimg = (src) => __awaiter(void 0, void 0, void 0, function* () {
return new Promise((resolve, reject) => {
const img = new Image();
img.onload = () => resolve(img);
img.onerror = () => reject("Invalid SVG");
img.src = src;
});
});
const MISSING = `
<svg width="20px" height="20px" viewBox="0 0 50 50" version="1.1" xmlns="http://www.w3.org/2000/svg">
<rect width="50" height="50" fill="#cccccc"/>
<g transform="translate(5,5)">
<path fill="none" stroke="#666666" stroke-width="7" d="m11,12a8.5,8 0 1,1 17,0q0,4-4,6t-4.5,4.5-.4,4v.2m0,3v7"/>
</g>
</svg>
`;
export class Sheet {
constructor(src) {
this.src = src;
this.canvas = document.createElement("canvas");
this.mapping = new Map();
this.missingBox = { x: 0, y: 0, w: 0, h: 0 };
}
load() {
return __awaiter(this, void 0, void 0, function* () {
let src = this.src;
const scale = window.devicePixelRatio;
if (src.endsWith(".html")) {
const c = yield fetch(src);
src = yield c.text();
}
const tree = new window.DOMParser().parseFromString(src, "text/html");
const icons = Array.from(tree.body.children);
const missingImg = yield mkimg(`data:image/svg+xml;base64,${btoa(MISSING)}`);
const boxes = [
{
w: missingImg.width * scale,
h: missingImg.height * scale,
img: missingImg,
id: "",
},
];
const serializer = new XMLSerializer();
for (const ps of icons) {
const svg64 = btoa(serializer.serializeToString(ps));
const image64 = `data:image/svg+xml;base64,${svg64}`;
const img = yield mkimg(image64);
boxes.push({
w: img.width * scale,
h: img.height * scale,
img: img,
id: ps.id,
});
}
const packresult = potpack(boxes);
this.canvas.width = packresult.w;
this.canvas.height = packresult.h;
const ctx = this.canvas.getContext("2d");
if (ctx) {
for (const box of boxes) {
if (box.x !== undefined && box.y !== undefined) {
ctx.drawImage(box.img, box.x, box.y, box.w, box.h);
if (box.id)
this.mapping.set(box.id, {
x: box.x,
y: box.y,
w: box.w,
h: box.h,
});
else
this.missingBox = { x: box.x, y: box.y, w: box.w, h: box.h };
}
}
}
return this;
});
}
get(name) {
let result = this.mapping.get(name);
if (!result)
result = this.missingBox;
return result;
}
}