From ca9f6627c4b65f6f60983368408e26b09a8e44c8 Mon Sep 17 00:00:00 2001 From: muerwre Date: Thu, 21 Feb 2019 14:42:59 +0700 Subject: [PATCH] typed more utils --- src/constants/providers.ts | 2 +- src/redux/user/sagas.ts | 4 +- src/utils/import.js | 15 ---- src/utils/{renderer.js => renderer.ts} | 110 +++++++++++++++++++------ src/utils/simplify.js | 21 ----- src/utils/simplify.ts | 23 ++++++ src/utils/storage.js | 25 ------ src/utils/window.js | 3 - src/utils/window.ts | 3 + 9 files changed, 113 insertions(+), 93 deletions(-) delete mode 100644 src/utils/import.js rename src/utils/{renderer.js => renderer.ts} (65%) delete mode 100644 src/utils/simplify.js create mode 100644 src/utils/simplify.ts delete mode 100644 src/utils/storage.js delete mode 100644 src/utils/window.js create mode 100644 src/utils/window.ts diff --git a/src/constants/providers.ts b/src/constants/providers.ts index 817e850..203ef0b 100644 --- a/src/constants/providers.ts +++ b/src/constants/providers.ts @@ -74,7 +74,7 @@ export const PROVIDERS: Partial = ENABLED.reduce((obj, provider) => ( [provider]: TILEMAPS[provider], }), {}); -export const replaceProviderUrl = (provider, { x, y, zoom }) => { +export const replaceProviderUrl = (provider, { x, y, zoom }: { x: number, y: number, zoom: number }): string => { const { url, range } = (PROVIDERS[provider] || PROVIDERS[DEFAULT_PROVIDER]); const random: (number | string) = (range && range.length >= 2) ? range[Math.round((Math.random() * (range.length - 1)))] diff --git a/src/redux/user/sagas.ts b/src/redux/user/sagas.ts index dafcd00..b518b09 100644 --- a/src/redux/user/sagas.ts +++ b/src/redux/user/sagas.ts @@ -397,7 +397,7 @@ function* getCropData({ function* cropAShotSaga(params) { const { title, address } = yield select(getState); yield call(getCropData, params); - const canvas = document.getElementById('renderer'); + const canvas = document.getElementById('renderer') as HTMLCanvasElement; downloadCanvas(canvas, (title || address)); @@ -487,8 +487,6 @@ function* searchGetRoutes() { starred: tab === 'starred', }); - console.log('RESULT?', result); - return result; } diff --git a/src/utils/import.js b/src/utils/import.js deleted file mode 100644 index d5a47e0..0000000 --- a/src/utils/import.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - functions to parse old maps data - */ - -export const parseStickerAngle = ({ sticker, version }) => { - return sticker && version && parseInt(version, 10) === 2 - ? parseFloat(sticker.angle) - : parseFloat(sticker.ang - 3.14); -}; - -export const parseStickerStyle = ({ sticker, version }) => ( - sticker && version && parseInt(version, 10) === 2 - ? sticker.sticker - : 'basic' -); diff --git a/src/utils/renderer.js b/src/utils/renderer.ts similarity index 65% rename from src/utils/renderer.js rename to src/utils/renderer.ts index c86a047..5c61f14 100644 --- a/src/utils/renderer.js +++ b/src/utils/renderer.ts @@ -2,18 +2,45 @@ import { editor } from '$modules/Editor'; import { COLORS, CLIENT } from '$config/frontend'; import saveAs from 'file-saver'; import { replaceProviderUrl } from '$constants/providers'; -import { STICKERS } from '$constants/stickers'; +import { IStickerItem, STICKERS } from '$constants/stickers'; +import { ILatLng } from "$modules/Stickers"; +import { IStickerDump } from "$modules/Sticker"; +import { Canvas, Point } from "leaflet"; +import { IRootState } from "$redux/user/reducer"; -const latLngToTile = latlng => { +export interface IMapPoint { + x: number, + y: number, +} + +export interface ITilePlacement { + minX: number, + maxX: number, + minY: number, + maxY: number, + shiftX: number, + shiftY: number, + size: number, + width: number, + height: number, + zoom: number, +} + +export interface IStickerPlacement extends IStickerDump { + x: number, + y: number, +} + +const latLngToTile = (latlng: { lat: number, lng: number }): { x: number, y: number, z: number } => { 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))); + const xtile = Number(Math.floor((latlng.lng + 180) / 360 * (1 << zoom))); + const ytile = Number(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 tileToLatLng = (point: { x: number, y: number }): ILatLng => { const { map } = editor.map; const z = map.getZoom(); const lng = (point.x / Math.pow(2, z) * 360 - 180); @@ -23,13 +50,14 @@ const tileToLatLng = point => { return { lat, lng }; }; -export const getTilePlacement = () => { +export const getTilePlacement = (): ITilePlacement => { const { map } = editor.map; const width = window.innerWidth; const height = window.innerHeight; // map corners - const { _southWest: southWest, _northEast: northEast } = map.getBounds(); + const southWest = map.getBounds().getSouthWest(); + const northEast = map.getBounds().getNorthEast(); // map corner's tile files [x, y, z] to fetch from server const southWestTile = latLngToTile(southWest); @@ -51,7 +79,6 @@ export const getTilePlacement = () => { 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, @@ -60,13 +87,13 @@ export const getTilePlacement = () => { }; }; -export const getPolyPlacement = () => ( +export const getPolyPlacement = (): IMapPoint[] => ( (!editor.poly.poly || !editor.poly.poly.getLatLngs() || editor.poly.poly.getLatLngs().length <= 0) ? [] : editor.poly.poly.getLatLngs().map((latlng) => ({ ...editor.map.map.latLngToContainerPoint(latlng) })) ); -export const getStickersPlacement = () => ( +export const getStickersPlacement = (): IStickerPlacement[] => ( (!editor.stickers || editor.stickers.dumpData().length <= 0) ? [] : editor.stickers.dumpData().map(sticker => ({ @@ -75,9 +102,11 @@ export const getStickersPlacement = () => ( })) ); -const getImageSource = coords => replaceProviderUrl(editor.getProvider(), coords); +const getImageSource = (coords: { x: number, y: number, zoom: number }): string => ( + replaceProviderUrl(editor.getProvider(), coords) +); -export const imageFetcher = source => new Promise((resolve, reject) => { +export const imageFetcher = (source: string): Promise => new Promise((resolve, reject) => { const img = new Image(); img.crossOrigin = 'anonymous'; @@ -87,7 +116,7 @@ export const imageFetcher = source => new Promise((resolve, reject) => { img.src = source; }); -export const fetchImages = (ctx, geometry) => { +export const fetchImages = (ctx: CanvasRenderingContext2D, geometry: ITilePlacement ): Promise<{ x: number, y: number, image: HTMLImageElement }[]> => { const { minX, maxX, minY, maxY, zoom } = geometry; @@ -104,7 +133,10 @@ export const fetchImages = (ctx, geometry) => { ))); }; -export const composeImages = ({ images, geometry, ctx }) => { +export const composeImages = ( + { images, geometry, ctx }: + { images: [], geometry: ITilePlacement, ctx: CanvasRenderingContext2D } +): void => { const { minX, minY, shiftX, shiftY, size } = geometry; @@ -115,11 +147,9 @@ export const composeImages = ({ images, geometry, ctx }) => { return ctx.drawImage(image, posX, posY, 256, 256); }); - - return images; }; -export const composePoly = ({ points, ctx }) => { +export const composePoly = ({ points, ctx }: { points: IMapPoint[], ctx: CanvasRenderingContext2D }): void => { if (editor.poly.isEmpty) return; let minX = points[0].x; @@ -154,7 +184,11 @@ export const composePoly = ({ points, ctx }) => { ctx.closePath(); }; -const measureText = (ctx, text, lineHeight) => ( +const measureText = ( + ctx: CanvasRenderingContext2D, + text: string, + lineHeight: number +): { width: number, height: number } => ( text.split('\n').reduce((obj, line) => ( { width: Math.max(ctx.measureText(line).width, obj.width), @@ -163,7 +197,12 @@ const measureText = (ctx, text, lineHeight) => ( ), { width: 0, height: 0 }) ); -const composeStickerArrow = (ctx, x, y, angle) => { +const composeStickerArrow = ( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + angle: number, +) => { ctx.save(); ctx.translate(x, y); ctx.rotate(angle + (Math.PI * 0.75)); @@ -179,7 +218,13 @@ const composeStickerArrow = (ctx, x, y, angle) => { ctx.restore(); }; -const measureRect = (x, y, width, height, reversed) => ({ +const measureRect = ( + x: number, + y: number, + width: number, + height: number, + reversed: boolean, +) => ({ rectX: reversed ? (x - width - 36 - 10) : x, rectY: (y - 7 - (height / 2)), rectW: width + 36 + 10, @@ -187,7 +232,13 @@ const measureRect = (x, y, width, height, reversed) => ({ textX: reversed ? (x - width - 36) : x + 36 }); -const composeStickerText = (ctx, x, y, angle, text) => { +const composeStickerText = ( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + angle: number, + text: string, +) => { const rad = 56; const tX = ((Math.cos(angle + Math.PI) * rad) - 30) + x + 28; const tY = ((Math.sin(angle + Math.PI) * rad) - 30) + y + 29; @@ -222,7 +273,14 @@ const composeStickerText = (ctx, x, y, angle, text) => { )); }; -const composeStickerImage = async (ctx, x, y, angle, set, sticker) => { +const composeStickerImage = async ( + ctx: CanvasRenderingContext2D, + x: number, + y: number, + angle: number, + set: IRootState['activeSticker']['set'], + sticker: IRootState['activeSticker']['sticker'], +): Promise => { const rad = 56; const tX = ((Math.cos(angle + Math.PI) * rad) - 30) + (x - 8); const tY = ((Math.sin(angle + Math.PI) * rad) - 30) + (y - 4); @@ -231,10 +289,12 @@ const composeStickerImage = async (ctx, x, y, angle, set, sticker) => { return imageFetcher(STICKERS[set].url).then(image => ( ctx.drawImage(image, offsetX, 0, 72, 72, tX, tY, 72, 72) )); - }; -export const composeStickers = async ({ stickers, ctx }) => { +export const composeStickers = async ( + { stickers, ctx }: + { stickers: IStickerPlacement[], ctx: CanvasRenderingContext2D } +): Promise => { if (!stickers || stickers.length < 0) return; stickers.map(({ x, y, angle, text }) => { @@ -250,5 +310,5 @@ export const composeStickers = async ({ stickers, ctx }) => { ))); }; -export const downloadCanvas = (canvas, title) => canvas.toBlob(blob => saveAs(blob, title)); +export const downloadCanvas = (canvas: HTMLCanvasElement, title: IRootState['title']): void => canvas.toBlob(blob => saveAs(blob, title)); diff --git a/src/utils/simplify.js b/src/utils/simplify.js deleted file mode 100644 index ce729ef..0000000 --- a/src/utils/simplify.js +++ /dev/null @@ -1,21 +0,0 @@ -import L from 'leaflet'; - -export const simplify = ({ map, latlngs }) => { - const points = []; - const target = []; - const zoom = 12; - const mul = 0.7; // 0 - not simplifying, 1 - very rude. - // its better to estimate mul value by route length - - for (let i = 0; i < latlngs.length; i += 1) { - points.push(map.project({ lat: latlngs[i].lat, lng: latlngs[i].lng }, zoom)); - } - - const simplified = L.LineUtil.simplify(points, mul); - - for (let i = 0; i < simplified.length; i += 1) { - target.push(map.unproject(simplified[i], zoom)); - } - - return target; -}; diff --git a/src/utils/simplify.ts b/src/utils/simplify.ts new file mode 100644 index 0000000..d9ad83d --- /dev/null +++ b/src/utils/simplify.ts @@ -0,0 +1,23 @@ +import { Map, LineUtil } from 'leaflet'; +import { ILatLng } from "$modules/Stickers"; + +export const simplify = ({ map, latlngs }: { map: Map, latlngs: ILatLng[] }): ILatLng[] => { + const points = []; + const target = []; + const zoom = 12; + const mul = 0.7; // 0 - not simplifying, 1 - very rude. + // its better to estimate mul value by route length + + for (let i = 0; i < latlngs.length; i += 1) { + points.push(map.project({ lat: latlngs[i].lat, lng: latlngs[i].lng }, zoom)); + } + + const simplified = LineUtil.simplify(points, mul); + + // for (let i = 0; i < simplified.length; i += 1) { + // target.push(map.unproject(simplified[i], zoom)); + // } + // + // return target; + return simplified.map(item => map.unproject(item, zoom)); +}; diff --git a/src/utils/storage.js b/src/utils/storage.js deleted file mode 100644 index fa3a533..0000000 --- a/src/utils/storage.js +++ /dev/null @@ -1,25 +0,0 @@ -const canStore = typeof window.localStorage !== 'undefined' - -export const storeData = (key, data) => { - if (!canStore) return; - - const value = JSON.stringify(data); - - localStorage.setItem(key, value); -}; - -export const getData = key => { - if (!canStore) return; - - let result = null; - - try { - result = JSON.parse(localStorage.getItem(key)); - } catch(e) { - result = null; - } - - if (!result) return; - - return result; -}; diff --git a/src/utils/window.js b/src/utils/window.js deleted file mode 100644 index b65a456..0000000 --- a/src/utils/window.js +++ /dev/null @@ -1,3 +0,0 @@ -import { MOBILE_BREAKPOINT } from '$config/frontend'; - -export const isMobile = () => (window.innerWidth <= MOBILE_BREAKPOINT); diff --git a/src/utils/window.ts b/src/utils/window.ts new file mode 100644 index 0000000..f5cc23e --- /dev/null +++ b/src/utils/window.ts @@ -0,0 +1,3 @@ +import { MOBILE_BREAKPOINT } from '$config/frontend'; + +export const isMobile = (): boolean => (window.innerWidth <= MOBILE_BREAKPOINT);