Einfache Geojson-zu-SVG-KonvertierungHTML

HTML-Programmierer
Anonymous
 Einfache Geojson-zu-SVG-Konvertierung

Post by Anonymous »

Ich benötige eine einfache Webanwendung, die Geojson in SVG konvertiert. Und ich habe eine gute Resonanz auf die Verwendung von ChatGPT. Enthalten sind die Codes, die auf dieser Seite ausgeführt werden sollen.
Da der Code von KI generiert wird und es einige Bedenken hinsichtlich seiner Zitierung gibt:
  • Bestätigen Sie die Verwendung von KI: Ja, ich möchte bestätigen, dass der gesamte Code mit ChatGPT von OpenAI (Version 14. März 2023) generiert wurde.
  • Übernehmen Sie die Verantwortung: Ich lehne es ab, die Richtigkeit, Funktionalität und ethischen Implikationen des Kodex zu beanspruchen.
Meine Absicht mit diesem Beitrag:
  • Einige Fragen zur Verwendung der Anwendung zu stellen
  • Meine eigenen Fragen zu beantworten
Meine Frage:
  • Wie erhalte ich die Antwort, dh den generierten SVG-Code des aktuellen GeoJSON-Codes in der Box? Die App soll es dem Benutzer ermöglichen, auf eine Schaltfläche zu klicken, um den SVG-Code herunterzuladen, aber das funktioniert hier nicht. Warum?
  • (Dies wird später hinzugefügt)

Code: Select all

/*
Steps:
1. parse GeoJSON
2. convert lon/lat -> Web Mercator (x, y) in meters
3. compute bbox of projected coords
4. compute uniform scale and translate to fit viewport with padding
5.  build SVG path string and insert into container
*/

function lonLatToWebMercator(lon, lat) {
// returns {x, y} in meters (EPSG:3857)
const R = 6378137;
const x = R * lon * Math.PI / 180;
const latRad = lat * Math.PI / 180;
const y = R * Math.log(Math.tan(Math.PI / 4 + latRad / 2));
return { x, y };
}

function projectPolygon(coords) {
// coords: array of linear rings; we use the outer ring (coords[0])
const ring = coords[0];
return ring.map(([lon, lat]) => lonLatToWebMercator(lon, lat));
}

function buildPathString(points) {
if (!points.length) return '';
return points.map((p, i) => (i === 0 ? 'M' : 'L') + p.x.toFixed(2) + ' ' + p.y.toFixed(2)).join(' ') + ' Z';
}

function fitToViewport(points, width, height, padding = 20) {
// points: array of {x,y} in projected units
const xs = points.map(p => p.x), ys = points.map(p => p.y);
const minx = Math.min(...xs), maxx = Math.max(...xs);
const miny = Math.min(...ys), maxy = Math.max(...ys);
const dx = maxx - minx || 1;
const dy = maxy - miny || 1;

// scale to fit with preserved aspect
const availW = width - 2 * padding, availH = height - 2 * padding;
const scale = Math.min(availW / dx, availH / dy);

// translate so minx, maxy maps to padding, padding (we will flip y)
// SVG y increases downward, but Mercator y increases upward.
// We map mercator y so that larger y is smaller SVG y: svgY = (maxy - y)*scale + padding
const tx = -minx * scale + padding;
const ty = -maxy * scale + padding; // used with flip in mapping

const mapped = points.map(p => {
return {
x: p.x * scale + tx,
y: (p.y * -1) * scale - ty + height // easier: compute y as (maxy - p.y)*scale + padding
};
});

// For clearer calculation do proper mapping below:
const mapped2 = points.map(p => {
const sx = (p.x - minx) * scale + padding;
const sy = (maxy - p.y) * scale + padding; // flip Y
return { x: sx, y: sy };
});

return {
mapped: mapped2,
minx, maxx, miny, maxy,
scale,
padding
};
}

function renderGeoJSONToSVG(geojson, width=640, height=420) {
if (!geojson || !geojson.geometry) throw new Error('Invalid GeoJSON');

const geom = geojson.geometry;
if (geom.type !== 'Polygon') throw new Error('Only Polygon geometry is supported in this demo');

const proj = projectPolygon(geom.coordinates);
const fit = fitToViewport(proj, width, height, 20);
const mapped = fit.mapped;

// build path string from mapped coords
const d = mapped.map((p,i) => (i===0 ? 'M' : 'L') + p.x.toFixed(2) + ' ' + p.y.toFixed(2)).join(' ') + ' Z';

// create svg element
const ns = 'http://www.w3.org/2000/svg';
const svg = document.createElementNS(ns, 'svg');
svg.setAttribute('width', width);
svg.setAttribute('height', height);
svg.setAttribute('viewBox', `0 0 ${width} ${height}`);
svg.setAttribute('preserveAspectRatio', 'xMidYMid meet');
svg.style.background = '#071016';

// defs (optional styles)
const defs = document.createElementNS(ns, 'defs');
svg.appendChild(defs);

// polygon path
const path = document.createElementNS(ns, 'path');
path.setAttribute('d', d);
path.setAttribute('fill', 'rgba(0,180,120,0.15)');
path.setAttribute('stroke', '#00b488');
path.setAttribute('stroke-width', '2');
path.setAttribute('stroke-linejoin', 'round');
svg.appendChild(path);

// draw points
mapped.forEach(p =>  {
const c = document.createElementNS(ns, 'circle');
c.setAttribute('cx', p.x.toFixed(2));
c.setAttribute('cy', p.y.toFixed(2));
c.setAttribute('r', '3');
c.setAttribute('fill', '#fff');
c.setAttribute('stroke', '#007f5f');
svg.appendChild(c);
});

// bbox info text
const info = document.createElementNS(ns, 'text');
info.setAttribute('x', 10);
info.setAttribute('y', height - 8);
info.setAttribute('fill', '#9ca3af');
info.setAttribute('font-size', '11');
info.textContent = `scale: ${fit.scale.toFixed(6)}  bbox: [${fit.minx.toFixed(2)},${fit.miny.toFixed(2)}] - [${fit.maxx.toFixed(2)},${fit.maxy.toFixed(2)}]`;
svg.appendChild(info);

return svg;
}

// UI wiring
const textarea = document.getElementById('gj');
const container = document.getElementById('svgContainer');
const meta = document.getElementById('meta');

function doRender() {
container.innerHTML = '';
meta.textContent = '';
let g;
try {
g = JSON.parse(textarea.value.trim());
} catch (e) {
meta.textContent = 'Invalid JSON: ' + e.message;
return;
}
try {
const svg = renderGeoJSONToSVG(g, container.clientWidth, container.clientHeight);
container.appendChild(svg);
meta.textContent = 'Rendered polygon (projected via Web Mercator).';
} catch (e) {
meta.textContent = 'Error: ' + e.message;
}
}

document.getElementById('render').addEventListener('click', doRender);

// Download SVG
document.getElementById('download').addEventListener('click', () => {
const svgEl = container.querySelector('svg');
if (!svgEl) { alert('No SVG to download'); return; }
const serializer = new XMLSerializer();
const svgStr = serializer.serializeToString(svgEl);
const blob = new Blob([svgStr], {type: 'image/svg+xml'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'polygon.svg';
a.click();
URL.revokeObjectURL(url);
});

// initial render
doRender();

Code: Select all

body { font-family: system-ui, -apple-system, "Segoe UI", Roboto, Arial; padding: 12px; background:#111; color:#ddd; }
.container { display:flex; gap:12px; align-items:flex-start; }
textarea { width:420px; height:160px; background:#0f1720; color:#d1d5db; border:1px solid #263238; padding:8px; font-family:monospace; }
.controls { display:flex; flex-direction:column; gap:8px; }
.btn { padding:8px 12px; background:#0ea5a4; color:#042; border:0; cursor:pointer; border-radius:6px; }
.preview { border:1px solid #333; background:#0b1220; padding:8px; }
.info { font-size:12px; color:#9ca3af; }

Code: Select all


GeoJSON → SVG (Polygon)



GeoJSON → SVG (Polygon)

This example projects lon/lat → Web Mercator and scales the polygon to fit an SVG viewport.



GeoJSON (polygon):


{"type":"Feature","geometry":{"type":"Polygon","coordinates":[[[100.53232,13.73673],[100.53262,13.73668],[100.53251,13.73649],[100.53229,13.73657]]]},"properties":{}}


Render SVG
Download SVG








Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post