From 5d4a43abb181ae4fd63d2365210ea4949f10012e Mon Sep 17 00:00:00 2001 From: Hsieh Chin Fan Date: Mon, 14 Oct 2024 14:47:04 +0800 Subject: feat: improve GeoLink generation * Stop searching pattern by linkify, Add links with geo URI scheme by async function instead * Search text nodes with patterns, and replace them with links * Add checker for valid degree/meter coordinated * Add query string "xy" anyway --- src/dumbyUtils.mjs | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'src/dumbyUtils.mjs') diff --git a/src/dumbyUtils.mjs b/src/dumbyUtils.mjs index 8bd4423..7b06840 100644 --- a/src/dumbyUtils.mjs +++ b/src/dumbyUtils.mjs @@ -1,5 +1,6 @@ import LeaderLine from 'leader-line' import { insideWindow, insideParent } from './utils' +import proj4 from 'proj4' export const coordPattern = /^geo:([-]?[0-9.]+),([-]?[0-9.]+)/ @@ -333,3 +334,52 @@ export const addAnchorByPoint = ({ return { ref: anchorName, link, title: desc } } + +/** + * setGeoSchemeByCRS. + * @description Add more information into Anchor Element within Geo Scheme by CRS + * @param {String} crs - EPSG/ESRI Code for CRS + * @return {Function} - Function for link + */ +export const setGeoSchemeByCRS = (crs) => (link) => { + const transform = proj4(crs, 'EPSG:4326') + const params = new URLSearchParams(link.search) + let xy = params.get('xy')?.split(',')?.map(Number) + + // Set coords for Geo Scheme + if (link.href.startsWith('geo:0,0')) { + if (!xy) return null + + const [lon, lat] = transform.forward(xy) + .map(value => parseFloat(value.toFixed(6))) + link.href = `geo:${lat},${lon}` + } + + const [lat, lon] = link.href + .match(coordPattern) + .slice(1) + .map(Number) + + if (!xy) { + xy = transform.inverse([lon, lat]) + params.set('xy', xy) + } + + // set query strings + params.set('crs', crs) + params.set('q', `${lat},${lon}`) + link.search = params + + const unit = proj4(crs).oProj.units + const invalidDegree = unit === 'degrees' && ( + (lon > 180 || lon < -180 || lat > 90 || lat < -90) || + (xy.every(v => v.toString().length < 3)) + ) + const invalidMeter = unit === 'm' && xy.find(v => v < 100) + if (invalidDegree || invalidMeter) { + link.replaceWith(document.createTextNode(link.textContent)) + return null + } + + return link +} -- cgit v1.2.3-70-g09d2