Skip to content

Commit 03e9a07

Browse files
committed
update
1 parent 603458f commit 03e9a07

File tree

2 files changed

+148
-2
lines changed

2 files changed

+148
-2
lines changed

geojson-editor/src/App.vue

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import Drawer from './components/features/Drawer.vue';
1414
import Measurer from './components/features/Measurer.vue';
1515
import FeatureCollectionEditor from './components/features/FeatureCollectionEditor.vue';
1616
import ShowEditorButton from './components/features/ShowEditorButton.vue';
17+
import IO from './components/features/IO.vue';
1718
1819
import { DrawManager, GeoJSONLayerManager, MeasureManager, TIdentityGeoJSONFeature, MiddleButtonRoate, VertexEditor } from '../../packages/maplugin-maplibre';
1920
import { StoreEditor } from './stores';
@@ -37,7 +38,7 @@ function handleMapLoaded(map: maplibregl.Map) {
3738
tiles: ["https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"]
3839
}
3940
});
40-
41+
4142
// 中键旋转
4243
new MiddleButtonRoate(map);
4344
@@ -77,7 +78,7 @@ function handleMapLoaded(map: maplibregl.Map) {
7778
7879
vertexEditor.setFeature(f, (id, g) => {
7980
glManager.clearFeatureHidden(id);
80-
81+
8182
const featrue = glManager.query(id)!;
8283
featrue.geometry = g;
8384
glManager.update(featrue);
@@ -86,6 +87,10 @@ function handleMapLoaded(map: maplibregl.Map) {
8687
});
8788
8889
createMapControl(map, ShowEditorButton);
90+
createMapControl(map, IO, {
91+
onUpload: (features: Array<TIdentityGeoJSONFeature>) => glManager.add(...features),
92+
onDownload: () => glManager.fc
93+
});
8994
createMapControl(map, Drawer, { drawManager }, 'top-left');
9095
createMapControl(map, Measurer, { measureManager }, 'top-left');
9196
}
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
<template>
2+
<div class="up-down-load">
3+
<div class="upload" @click="handleUpload">
4+
<svg t="1731034374048" class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24"
5+
height="20">
6+
<path
7+
d="M576 631.466667V725.333333h170.666667c59.733333-8.533333 106.666667-64 106.666666-128 0-72.533333-55.466667-128-128-128-17.066667 0-29.866667 4.266667-42.666666 8.533334V469.333333c0-93.866667-76.8-170.666667-170.666667-170.666666s-170.666667 76.8-170.666667 170.666666c0 17.066667 4.266667 29.866667 4.266667 46.933334-8.533333-4.266667-17.066667-4.266667-25.6-4.266667C260.266667 512 213.333333 558.933333 213.333333 618.666667S260.266667 725.333333 320 725.333333h170.666667v-93.866666l-46.933334 46.933333L384 618.666667l149.333333-149.333334 149.333334 149.333334-59.733334 59.733333-46.933333-46.933333z m0 93.866666v85.333334h-85.333333v-85.333334h-42.666667v85.333334h-128C213.333333 810.666667 128 725.333333 128 618.666667c0-85.333333 55.466667-157.866667 128-183.466667C273.066667 311.466667 379.733333 213.333333 512 213.333333c110.933333 0 209.066667 72.533333 243.2 170.666667 102.4 12.8 183.466667 102.4 183.466667 213.333333s-85.333333 200.533333-192 213.333334h-128v-85.333334h-42.666667z"
8+
fill="#ccc" p-id="8232" style="--darkreader-inline-fill: #33373a;"></path>
9+
</svg>
10+
</div>
11+
<div class="download" @click="handleDownload">
12+
<svg t="1731034330703" class="icon" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg" width="24"
13+
height="20">
14+
<path
15+
d="M490.666667 644.266667V469.333333h85.333333v174.933334l46.933333-46.933334 59.733334 59.733334-68.266667 68.266666h132.266667c59.733333-8.533333 106.666667-64 106.666666-128 0-72.533333-55.466667-128-128-128-17.066667 0-29.866667 4.266667-42.666666 8.533334V469.333333c0-93.866667-76.8-170.666667-170.666667-170.666666s-170.666667 76.8-170.666667 170.666666c0 17.066667 4.266667 29.866667 4.266667 46.933334-8.533333-4.266667-17.066667-4.266667-25.6-4.266667C260.266667 512 213.333333 558.933333 213.333333 618.666667S260.266667 725.333333 320 725.333333h132.266667L384 657.066667l59.733333-59.733334 46.933334 46.933334z m123.733333 81.066666l-81.066667 81.066667-81.066666-81.066667H405.333333v85.333334h-85.333333C213.333333 810.666667 128 725.333333 128 618.666667c0-85.333333 55.466667-157.866667 128-183.466667C273.066667 311.466667 379.733333 213.333333 512 213.333333c110.933333 0 209.066667 72.533333 243.2 170.666667 102.4 12.8 183.466667 102.4 183.466667 213.333333s-85.333333 200.533333-192 213.333334h-85.333334v-85.333334h-46.933333z"
16+
fill="#ccc" style="--darkreader-inline-fill: #33373a;"></path>
17+
</svg>
18+
</div>
19+
</div>
20+
</template>
21+
22+
<script setup lang="ts">
23+
import { TIdentityGeoJSONFeature, Tools } from '../../../../packages/maplugin-core';
24+
25+
const props = defineProps<{
26+
onUpload(features: Array<TIdentityGeoJSONFeature>): void,
27+
onDownload(): GeoJSON.FeatureCollection
28+
}>();
29+
30+
const file_process: Array<{
31+
extension: string,
32+
description: string,
33+
contentType: string
34+
decode?(file: File, onFinish: (features: Array<TIdentityGeoJSONFeature>) => void): void,
35+
encode?(geojson: GeoJSON.FeatureCollection): string | Blob
36+
}> = [
37+
{
38+
extension: ".geojson",
39+
description: "geojson",
40+
contentType: "application/json",
41+
decode(file, onFinish) {
42+
const reader = new FileReader();
43+
44+
reader.onload = e => {
45+
try {
46+
const geojson = JSON.parse(e.target?.result as string) as GeoJSON.FeatureCollection;
47+
geojson.features.forEach(f => {
48+
f.properties ??= {};
49+
if (!f.properties['id']) {
50+
f.properties['id'] = Tools.uuid();
51+
}
52+
});
53+
onFinish(geojson.features as any);
54+
} catch (e) {
55+
alert("geojson文件格式不正确");
56+
}
57+
};
58+
59+
reader.readAsText(file);
60+
},
61+
62+
encode(geojson) {
63+
return JSON.stringify(geojson, null, 4);
64+
}
65+
}
66+
]
67+
68+
function handleUpload() {
69+
const input = document.createElement('input');
70+
input.type = 'file';
71+
input.accept = file_process.filter(x => x.encode).map(x => x.extension).join("|");
72+
input.onchange = function (e: any) {
73+
const file: File = e.target.files[0];
74+
const extension = file.name.split('.').pop()!;
75+
file_process.find(x => x.extension === `.${extension}`)?.decode?.(file, features => props.onUpload(features));
76+
input.remove();
77+
}
78+
input.click();
79+
}
80+
81+
async function handleDownload() {
82+
const geojson = props.onDownload();
83+
84+
if ((window as any)['showSaveFilePicker']) {
85+
const opts = {
86+
types: file_process.filter(x => x.encode).map(x => ({
87+
description: x.description,
88+
accept: {
89+
[x.contentType]: [x.extension]
90+
}
91+
})),
92+
};
93+
94+
try {
95+
const handle: FileSystemFileHandle = await (window as any).showSaveFilePicker(opts); // 打开保存文件对话框
96+
const writable: FileSystemWritableFileStream = await handle.createWritable(); // 创建可写入的文件对象
97+
98+
const extension = handle.name.split('.').pop()!;
99+
let encode = file_process.find(x => x.extension === `.${extension}`)!.encode;
100+
if (!encode) encode = file_process.find(x => x.extension === '.geojson')!.encode!;
101+
102+
writable.write(encode(geojson)).then(()=>{
103+
writable.close();
104+
});
105+
106+
} catch (e) {
107+
108+
}
109+
}
110+
else {
111+
const blob = new Blob([JSON.stringify(geojson)], { type: "application/json" });
112+
const url = URL.createObjectURL(blob);
113+
const a = document.createElement("a");
114+
a.href = url;
115+
a.download = "geojson.geojson";
116+
a.click();
117+
a.remove();
118+
}
119+
}
120+
121+
</script>
122+
123+
<style scoped>
124+
.up-down-load {
125+
display: flex;
126+
align-items: center;
127+
background: var(--color-bg);
128+
border-radius: 6px;
129+
overflow: hidden;
130+
}
131+
132+
.up-down-load>div {
133+
padding: 4px;
134+
line-height: 0;
135+
cursor: pointer;
136+
}
137+
138+
.up-down-load>div:hover {
139+
background-color: var(--color-hover);
140+
}
141+
</style>

0 commit comments

Comments
 (0)