ns-mapbox-gl-export
Version:
This module adds control which can export PDF and images.
455 lines • 20.2 kB
JavaScript
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.DPI = exports.PageOrientation = exports.Size = exports.Unit = exports.Format = void 0;
const jspdf_1 = require("jspdf");
require("jspdf-autotable");
const file_saver_1 = require("file-saver");
const mapbox_gl_1 = __importStar(require("mapbox-gl"));
require("js-loading-overlay");
const fabric_1 = require("fabric");
exports.Format = {
JPEG: 'jpg',
PNG: 'png',
PDF: 'pdf',
SVG: 'svg',
};
exports.Unit = {
in: 'in',
mm: 'mm',
};
exports.Size = {
'4.1 x 5.8 (A6)': [148, 105],
'4.9 x 6.9 (B6)': [176, 125],
'5.8 x 8.3 (A5)': [210, 148],
'6.9 x 9.8 (B5)': [250, 176],
'8.3 x 11.7 (A4)': [297, 210],
'8.5 x 11 (LETTER)': [279, 216],
'9.8 x 13.9 (B4)': [353, 250],
'11.7 x 16.5 (A3)': [420, 297],
'11 x 17 (TABLOID)': [420, 297],
'13.9 x 19.7 (B3)': [500, 353],
'16.5 x 23.4 (A2)': [594, 420],
'19.7 x 27.8 (B2)': [707, 500],
'22 x 34 (D)': [863, 558],
'24 x 36 (E)': [914, 609],
};
exports.PageOrientation = {
Landscape: 'landscape',
Portrait: 'portrait',
};
exports.DPI = {
72: 72,
96: 96,
200: 200,
300: 300,
400: 400,
};
class MapGenerator {
constructor(map, size = exports.Size['8.3 x 11.7 (A4)'], dpi = 300, format = exports.Format.PNG.toString(), unit = exports.Unit.mm, accessToken, logoURL, adjustment) {
this.padTo2Digits = (num) => num.toString().padStart(2, '0');
this.formatDate = (date) => [
this.padTo2Digits(date.getMonth() + 1),
this.padTo2Digits(date.getDate()),
date.getFullYear(),
].join('/');
this.map = map;
this.width = size[0];
this.height = size[1];
this.dpi = dpi;
this.format = format;
this.unit = unit;
this.accessToken = accessToken;
this.logoURL = logoURL;
this.adjustment = adjustment;
}
generate(loader, fName, pdfOptions, callback) {
try {
const this_ = this;
if (loader) {
JsLoadingOverlay.show({
overlayBackgroundColor: '#5D5959',
overlayOpacity: '0.6',
spinnerIcon: 'ball-spin',
spinnerColor: '#5733d6',
spinnerSize: '2x',
overlayIDName: 'overlay',
spinnerIDName: 'spinner',
offsetX: 0,
offsetY: 0,
containerID: null,
lockScroll: false,
overlayZIndex: 9998,
spinnerZIndex: 9999,
});
}
const actualPixelRatio = window.devicePixelRatio;
Object.defineProperty(window, 'devicePixelRatio', {
get() {
return this_.dpi / 96;
},
});
const hidden = document.createElement('div');
hidden.className = 'hidden-map';
document.body.appendChild(hidden);
const container = document.createElement('div');
container.style.width = this.toPixels(this.width);
container.style.height = this.toPixels(this.height);
hidden.appendChild(container);
const style = this.map.getStyle();
if (style) {
if (style.sources) {
const sources = style.sources;
Object.keys(sources).forEach((name) => {
const src = sources[name];
Object.keys(src).forEach((key) => {
if (!src[key])
delete src[key];
});
});
}
}
const mapScale = this.getMapScaleInFeets(this.map.getZoom());
const validStyle = style || 'mapbox://styles/mapbox/streets-v11';
const renderMap = new mapbox_gl_1.Map({
accessToken: this.accessToken || mapbox_gl_1.default.accessToken || '',
container,
style: validStyle,
center: this.map.getCenter(),
zoom: this.map.getZoom(),
bearing: this.map.getBearing(),
pitch: this.map.getPitch(),
interactive: false,
preserveDrawingBuffer: true,
fadeDuration: 0,
attributionControl: false,
transformRequest: this.map._requestManager._transformRequestFn,
});
const addImagesToRenderMap = () => {
var _a, _b;
const images = ((_b = (_a = renderMap.style) === null || _a === void 0 ? void 0 : _a.imageManager) === null || _b === void 0 ? void 0 : _b.images) || {};
if (images && Object.keys(images).length > 0) {
Object.keys(images).forEach((key) => {
if (!key || !images[key].data)
return;
if (!renderMap.hasImage(key)) {
const image = images[key];
if (image
&& typeof image.width === 'number'
&& typeof image.height === 'number'
&& image.data instanceof Uint8Array) {
renderMap.addImage(key, {
width: image.width,
height: image.height,
data: image.data,
});
}
else {
console.error(`Invalid image object structure for key: ${key}`);
}
}
});
}
renderMap.loadImage('https://geoviewer.io/img/ns_marker.png', (error, image) => {
if (error) {
console.error('Error loading image:', error);
return;
}
if (!renderMap.hasImage('gl-draw-ns-marker')) {
if (image) {
renderMap.addImage('gl-draw-ns-marker', image, { sdf: true });
console.log('Image added successfully.');
}
}
else {
console.log('Image already exists.');
}
});
};
if (!renderMap.isStyleLoaded()) {
console.log('Waiting for renderMap to load...');
renderMap.once('style.load', addImagesToRenderMap);
}
else {
addImagesToRenderMap();
}
renderMap.once('idle', () => {
var _a;
const canvas = renderMap.getCanvas();
const fileName = `${fName || 'map'}.${this_.format}`;
switch (this_.format) {
case exports.Format.PNG:
this_.toPNG(canvas, fileName, callback);
break;
case exports.Format.JPEG:
this_.toJPEG(canvas, fileName, callback);
break;
case exports.Format.PDF:
this_.toPDF(renderMap, fileName, Object.assign({ scale: `1'' = ${mapScale.toString()} ft` }, pdfOptions), callback);
break;
case exports.Format.SVG:
this_.toSVG(canvas, fileName, callback);
break;
default:
console.error(`Invalid file format: ${this_.format}`);
break;
}
renderMap.remove();
(_a = hidden.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(hidden);
Object.defineProperty(window, 'devicePixelRatio', {
get() {
return actualPixelRatio;
},
});
if (loader) {
JsLoadingOverlay.hide();
}
});
}
catch (e) {
if (loader) {
JsLoadingOverlay.hide();
}
console.error(e);
}
}
toPNG(canvas, fileName, callback) {
canvas.toBlob((blob) => {
if (callback)
callback(null, blob);
else {
(0, file_saver_1.saveAs)(blob, fileName);
}
});
}
toJPEG(canvas, fileName, callback) {
canvas.toBlob((blob) => {
if (callback) {
callback(null, blob);
}
else {
const uri = canvas.toDataURL('image/jpeg', 0.85);
const a = document.createElement('a');
a.href = uri;
a.download = fileName;
a.click();
a.remove();
}
}, 'image/jpeg', 0.85);
}
toPDF(map, fileName, pdfOptions, callback) {
try {
const canvas = map.getCanvas();
const maxWidth = this.width - 20;
const maxHeight = this.height - 55;
const imageWidth = maxWidth;
let imageHeight = (canvas.height / canvas.width) * imageWidth;
let yPosition = 13 + (maxHeight - imageHeight) / 2;
if (!(pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.hideTitle) && (pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.hideFooter)) {
yPosition += 15;
}
if (this.height > this.width) {
imageHeight += 12;
yPosition -= 5;
}
const pdf = new jspdf_1.jsPDF({
orientation: this.width > this.height ? 'l' : 'p',
unit: this.unit,
compress: true,
format: [this.width, this.height],
});
const largePaperSize = ((this.width === 863 && this.height === 558)
|| (this.width === 558 && this.height === 863)
|| (this.width === 914 && this.height === 609)
|| (this.width === 609 && this.height === 914));
const imageData = largePaperSize ? canvas.toDataURL('image/jpeg', 0.9) : canvas.toDataURL('image/png');
pdf.addImage(imageData, largePaperSize ? 'JPEG' : 'PNG', 10, yPosition + (!(pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.hideTitle) ? 0 : 15), imageWidth, imageHeight, undefined, 'FAST');
if (!(pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.hideTitle)) {
pdf.setFontSize(13);
const width = pdf.internal.pageSize.getWidth();
const titleText = ((pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.title) || '').toString() || ' ';
const titleHeight = 9;
const padding = 2;
pdf.setFillColor(255, 255, 255);
pdf.rect(0, 0, width, titleHeight + padding * 2, 'F');
pdf.setTextColor(0, 0, 0);
pdf.text(titleText, width / 2, titleHeight / 2 + padding, {
align: 'center',
maxWidth: this.width - 20,
});
}
if (!(pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.hideFooter)) {
const columns = [
pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.scale,
pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.subTitle,
this.formatDate(new Date()),
'',
];
const infoRow = [
'This map may represent a visual display of related geographic information. Data provided here is not a guarantee of actual field conditions. To ensure complete accuracy, please contact the responsible staff for the most up-to-date information.',
];
const options = {
theme: 'grid',
tableLineColor: [0, 0, 0],
tableLineWidth: 0.5,
startY: this.height - 40,
styles: {
overflow: 'linebreak',
fontSize: 12,
fontStyle: 'bold',
halign: 'center',
valign: 'middle',
},
headStyles: {
fillColor: [255, 255, 255],
textColor: [0, 0, 0],
lineColor: [0, 0, 0],
lineWidth: 0.5,
minCellHeight: 25,
cellWidth: (this.width - 20) / 4,
},
bodyStyles: { minCellHeight: 100, lineColor: [0, 0, 0] },
margin: {
top: 0,
left: 10,
right: 10,
bottom: 0,
},
didDrawCell: (data) => {
var _a, _b, _c, _d;
if (data.section === 'head'
&& data.column.index === 3
&& (pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logoBase64)) {
const cellWidth = Number(data.cell.width);
const cellHeight = data.cell.height;
const logoWidth = ((_a = pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logoSize) === null || _a === void 0 ? void 0 : _a.width) || 20;
const logoHeight = ((_b = pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logoSize) === null || _b === void 0 ? void 0 : _b.height) || 20;
const x = data.cell.x + (cellWidth - logoWidth) / 2;
const y = data.cell.y + (cellHeight - logoHeight) / 2;
pdf.addImage(pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logoBase64, 'PNG', x, y, logoWidth, logoHeight);
}
else if (data.section === 'head'
&& data.column.index === 3
&& (this.logoURL || (pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logo))) {
const img = new Image();
img.src = `${this.logoURL || (pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logo)}?${Math.random()}`;
const cellWidth = typeof data.cell.width === 'number'
? data.cell.width
: parseFloat(data.cell.width);
const cellHeight = data.cell.height;
const logoWidth = ((_c = pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logoSize) === null || _c === void 0 ? void 0 : _c.width) || 20;
const logoHeight = ((_d = pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.logoSize) === null || _d === void 0 ? void 0 : _d.height) || 20;
const xPosition = data.cell.x + (cellWidth - logoWidth) / 2;
const yPosition = data.cell.y + (cellHeight - logoHeight) / 2;
pdf.addImage(img, 'JPEG', xPosition, yPosition, logoWidth, logoHeight);
}
},
};
pdf.autoTable(columns, [], options);
const informationRowOptions = Object.assign(Object.assign({}, options), { startY: pdf.autoTable.previous.finalY, bodyStyles: {
minCellHeight: 10,
lineColor: [0, 0, 0],
fontSize: 8.5,
halign: 'left',
}, cellWidth: this.width - 20 });
pdf.autoTable([columns], [infoRow], informationRowOptions);
}
const { lng, lat } = map.getCenter();
pdf.setProperties({
title: 'Map PDF',
subject: `center: [${lng}, ${lat}], zoom: ${map.getZoom()}`,
creator: 'Nobel Systems Map Exporter',
author: '(c)Nobel Systems',
});
if (callback) {
const pdfBlob = pdf.output('blob');
callback(null, pdfBlob);
}
else {
pdf.save(fileName);
}
}
catch (e) {
console.error(e);
}
}
toSVG(canvas, fileName, callback) {
const uri = canvas.toDataURL('image/png');
fabric_1.fabric.Image.fromURL(uri, (image) => {
const tmpCanvas = new fabric_1.fabric.Canvas('canvas');
const pxWidth = Number(this.toPixels(this.width, this.dpi).replace('px', ''));
const pxHeight = Number(this.toPixels(this.height, this.dpi).replace('px', ''));
image.scaleToWidth(pxWidth);
image.scaleToHeight(pxHeight);
tmpCanvas.setWidth(pxWidth);
tmpCanvas.setHeight(pxHeight);
tmpCanvas.add(image);
const svg = tmpCanvas.toSVG({
x: 0,
y: 0,
width: pxWidth,
height: pxHeight,
viewBox: {
x: 0,
y: 0,
width: pxWidth,
height: pxHeight,
},
});
if (callback) {
const blob = new Blob([svg], { type: 'image/svg+xml' });
callback(null, blob);
}
else {
const a = document.createElement('a');
a.href = `data:application/xml,${encodeURIComponent(svg)}`;
a.download = fileName;
a.click();
a.remove();
}
});
}
toPixels(length, conversionFactor = 96) {
if (this.unit === exports.Unit.mm) {
conversionFactor /= 25.4;
}
return `${conversionFactor * length}px`;
}
getMapScaleInFeets(zoom) {
return Math.round(591657550.5 / Math.pow(2, (zoom + 1 + Number(this.adjustment))) / 12).toFixed(0);
}
}
exports.default = MapGenerator;
//# sourceMappingURL=map-generator.js.map
;