orchidmap-front/src/utils/renderer.js
2018-11-28 17:57:56 +07:00

146 lines
4.2 KiB
JavaScript

import { editor } from '$modules/Editor';
import { COLORS, CONFIG } from '$config';
import saveAs from 'file-saver';
const latLngToTile = latlng => {
const { map } = editor.map;
const zoom = map.getZoom();
const xtile = parseInt(Math.floor((latlng.lng + 180) / 360 * (1 << zoom)));
const ytile = parseInt(Math.floor((1 - Math.log(Math.tan(latlng.lat * Math.PI / 180) + 1 / Math.cos(latlng.lat * Math.PI / 180)) / Math.PI) / 2 * (1 << zoom)));
return { x: xtile, y: ytile, z: zoom };
};
const tileToLatLng = point => {
const { map } = editor.map;
const z = map.getZoom();
const lng = (point.x / Math.pow(2, z) * 360 - 180);
const n = Math.PI - 2 * Math.PI * point.y / Math.pow(2, z);
const lat = (180 / Math.PI * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n))));
return { lat, lng };
};
export const getTilePlacement = () => {
const { map } = editor.map;
const width = window.innerWidth;
const height = window.innerHeight;
// map corners
const { _southWest: southWest, _northEast: northEast } = map.getBounds();
// map corner's tile files [x, y, z] to fetch from server
const southWestTile = latLngToTile(southWest);
const northEastTile = latLngToTile(northEast);
// filling tile file ranges
const { x: minX, y: maxY, z: zoom } = southWestTile;
const { x: maxX, y: minY } = northEastTile;
// actual coords of file's corners (they're shifted from view)
const southWestTileCoords = tileToLatLng(southWestTile);
const tileTransformTranslate = map.latLngToLayerPoint(southWestTileCoords);
const msw2 = map.latLngToLayerPoint(southWest);
return {
minX,
maxX,
minY,
maxY,
shiftX: tileTransformTranslate.x - msw2.x,
// shiftY: window.innerHeight + (tileTransformTranslate.y - msw2.y),
shiftY: ((maxY - minY) * 256) - (window.innerHeight + (tileTransformTranslate.y - msw2.y)),
size: 256,
width,
height,
zoom,
};
};
export const getPolyPlacement = () => (
(!editor.poly.poly || !editor.poly.poly.getLatLngs() || editor.poly.poly.getLatLngs().length <= 0)
? []
: editor.poly.poly.getLatLngs().map((latlng) => ({ ...editor.map.map.latLngToContainerPoint(latlng) }))
);
const getImageSource = ({ x, y, zoom }) => (`http://b.basemaps.cartocdn.com/light_all/${zoom}/${x}/${y}.png`);
export const imageFetcher = source => new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
img.onload = () => resolve(img);
img.onerror = () => reject(img);
img.src = source;
});
export const fetchImages = (ctx, geometry) => {
const {
minX, maxX, minY, maxY, zoom
} = geometry;
const images = [];
for (let x = minX; x <= maxX; x += 1) {
for (let y = minY; y <= maxY; y += 1) {
images.push({ x, y, source: getImageSource({ x, y, zoom }) });
}
}
return Promise.all(images.map(({ x, y, source }) => (
imageFetcher(source).then(image => ({ x, y, image }))
)));
};
export const composeImages = ({ images, geometry, ctx }) => {
const {
minX, minY, shiftX, shiftY, size
} = geometry;
images.map(({ x, y, image }) => {
const posX = ((x - minX) * size) + shiftX;
const posY = ((y - minY) * size) - shiftY;
return ctx.drawImage(image, posX, posY, 256, 256);
});
return images;
};
export const composePoly = ({ points, ctx }) => {
let minX = points[0].x;
let maxX = points[0].x;
let minY = points[0].y;
let maxY = points[0].y;
ctx.strokeStyle = 'red';
ctx.lineCap = 'round';
ctx.lineJoin = 'round';
ctx.lineWidth = CONFIG.STROKE_WIDTH + 0.5;
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (let i = 1; i < points.length; i += 1) {
ctx.lineTo(points[i].x, points[i].y);
// gradient bounds
if (points[i].x < minX) minX = points[i].x;
if (points[i].x > maxX) maxX = points[i].x;
if (points[i].y < minY) minY = points[i].y;
if (points[i].y > maxY) maxY = points[i].y;
}
const gradient = ctx.createLinearGradient(minX, minY, minX, maxY);
gradient.addColorStop(0, COLORS.PATH_COLOR[0]);
gradient.addColorStop(1, COLORS.PATH_COLOR[1]);
ctx.strokeStyle = gradient;
ctx.stroke();
ctx.closePath();
return true;
};
export const downloadCanvas = (canvas, title) => canvas.toBlob(blob => saveAs(blob, title));