GeoJSON-lag
Viðbótarpakki til að leggja GeoJSON beint á kortið. Feature eru rastuð í flísar, svo tugþúsundir þeirra kosta enga hluti á hvert feature. API-heiti, sjálfgefnir stílar og hegðun smellprófunar eru samræmd á Android, iOS og React.
01 · Yfirlit
GeoJSON er þáttað í létt feature-líkön og teiknað gegnum rasterflísaferli MapConductor. Hver sem þjónustuaðilinn er — Google Maps, MapLibre, MapKit, HERE — er kóðinn og niðurstaðan sú sama.
Þáttun
FeatureCollection, stakt Feature, ber rúmfræði, og textarunur samkvæmt RFC 8142. Straumþáttarar fylgja með.
Flísateiknun
Feature eru rastuð í 512 px flísar og sýnd sem rasterlag, án nokkurs ávana á vigureiginleika þjónustuaðilans.
Smellprófun
Smellir eru prófaðir gegn sömu hnitum og teiknuð voru, þar með talin göt, fjölhlutar og rúmfræðisöfn.
Hver rúmfræðigerð er studd á sama hátt á öllum þremur vettvöngunum.
02 · Grunnnotkun
Settu lagið inn í content-svið kortasýnarinnar. Þáttaðu í bakgrunni og réttu niðurstöðuna til features.
dependencies {
implementation("com.mapconductor:geojson:<version>")
}val mapViewState = rememberMapLibreMapViewState(
cameraPosition = MapCameraPosition(
position = GeoPoint.fromLongLat(139.7671, 35.6812),
zoom = 12.0,
),
)
val layerState = remember { GeoJSONLayerState() }
var features by remember { mutableStateOf(emptyList<GeoJSONFeature>()) }
LaunchedEffect(Unit) {
features = withContext(Dispatchers.IO) {
assets.open("wards.geojson").use(GeoJSONParser::parseStream)
}
}
MapLibreMapView(state = mapViewState) {
GeoJSONLayer(state = layerState, features = features)
}.package(url: "https://github.com/MapConductor/ios-geojson-layer", from: "<version>") // iOS 15+ / depends on MapConductorCore
@StateObject private var mapViewState = MapKitViewState(
cameraPosition: MapCameraPosition(
position: GeoPoint.fromLongLat(longitude: 139.7671, latitude: 35.6812),
zoom: 12.0
)
)
@StateObject private var layerState = GeoJSONLayerState()
@State private var features: [GeoJSONFeature] = []
var body: some View {
MapKitMapView(state: mapViewState) {
GeoJSONLayer(state: layerState, features: features)
}
.task {
features = GeoJSONParser.parse(fileURL: wardsURL)
}
}npm install @mapconductor/react-geojson \
@mapconductor/js-sdk-core @mapconductor/js-sdk-reactconst state = useMapLibreViewState({
mapDesignType: MapLibreDesign.OsmBrightJa,
cameraPosition: createMapCameraPosition({
position: createGeoPoint({ latitude: 35.6812, longitude: 139.7671 }),
zoom: 12,
}),
});
const layerState = useMemo(() => new GeoJSONLayerState(), []);
const features = useMemo(() => GeoJSONParser.parseFeatures(GEOJSON), []);
return (
<MapLibreMapView2D state={state}>
<GeoJSONLayer state={layerState} features={features} />
</MapLibreMapView2D>
);Þegar feature-gögn eða stíll breytast ógildir lagið vefslóð flísanna innanhúss, svo rasterskyndiminni korta-SDK-sins heldur aldrei áfram að skila úreltri mynd.
03 · Stílun
Stíll leysist í þremur lögum
Sjálfgefin gildi alls lagsins, yfirskrift á hvert feature, og StyleProvider sem ræður úr því kvikt. Neðri lögin vinna, og allt sem er ótilgreint erfist frá því ofar. Byrjaðu á sjálfgefnu gildunum og bættu neðri lögunum við aðeins eftir þörfum.
3-1. Stíleigindir
Stíleigindirnar eru aðeins fjórar, auk opacity, visible og minZoom / maxZoom á laginu til að stýra birtingu.
3-2. Að setja sjálfgefin gildi lagsins
Byrjaðu hér. Það sem þú réttir GeoJSONLayerState verður grunnurinn fyrir hvert feature, og staðan er sýnileg, svo síðari úthlutun teiknar upp á nýtt.
val layerState = remember {
GeoJSONLayerState(
strokeColor = Color.argb(220, 30, 136, 229),
fillColor = Color.argb(60, 30, 136, 229),
strokeWidth = 1.5f,
pointRadius = 8f,
opacity = 1f,
minZoom = 8, maxZoom = 22,
)
}
// Staðan er sýnileg: úthlutaðu síðar og flísarnar eru endurgerðar
layerState.fillColor = Color.argb(90, 214, 64, 69)@StateObject private var layerState = GeoJSONLayerState(
opacity: 1.0,
layerStyle: GeoJSONTileRenderer.LayerStyle(
strokeColor: UIColor(red: 30/255, green: 136/255, blue: 229/255, alpha: 0.86),
fillColor: UIColor(red: 30/255, green: 136/255, blue: 229/255, alpha: 0.24),
strokeWidth: 1.5,
pointRadius: 8.0
)
)
// Svið LayerStyle eru let, svo skiptu út allri strúktúrunni (alpha býr á UIColor)
layerState.layerStyle = GeoJSONTileRenderer.LayerStyle(
strokeColor: layerState.layerStyle.strokeColor,
fillColor: UIColor.systemRed.withAlphaComponent(0.35),
strokeWidth: layerState.layerStyle.strokeWidth,
pointRadius: layerState.layerStyle.pointRadius
)import { colorArgb, colorRgb, argbToCss } from '@mapconductor/react-geojson';
const layerState = useMemo(() => new GeoJSONLayerState({
strokeColor: colorArgb(220, 30, 136, 229),
fillColor: colorArgb(60, 30, 136, 229),
strokeWidth: 1.5,
pointRadius: 8,
opacity: 1,
minZoom: 8, maxZoom: 22,
}), []);
// colorRgb fyrir ógegnsæjan lit, argbToCss þegar farið er niður í CSS
const legend = argbToCss(colorRgb(30, 136, 229)); // "rgba(30,136,229,1.0000)"Litasnið
Android og React nota 32 bita ARGB-heiltölu (alfa í efsta bæti); iOS ber alfa í UIColor-inu sjálfu. React kemur með colorArgb(a,r,g,b), colorRgb(r,g,b) og argbToCss(), í sömu viðfangaröð og Color.argb() á Android. Allir þrír eru sjálfgefið #1E88E5 — ógegnsæ útlína, fylling með alfa 128.
3-3. Yfirskrift á hvert feature
Feature getur borið sín eigin strokeColor, fillColor, strokeWidth, pointRadius og visible. Null merkir sjálfgefið gildi; gildi vinnur. Þegar stíllinn er ráðinn við hleðslu og breytist aldrei eftir það er þetta einfaldasta og fljótasta leiðin.
val parsed = GeoJSONParser.parseStream(input)
// Eftir þáttun, lestu eigindin og brenndu stílinn inn
val styled = parsed.map { f ->
when (f.properties["status"]) {
"alert" -> f.copy(fillColor = Color.argb(120, 214, 64, 69), strokeWidth = 3f)
"closed" -> f.copy(visible = false)
else -> f // Skilið eftir sem null, svo sjálfgefið gildi lagsins er notað
}
}
GeoJSONLayer(state = layerState, features = styled)let parsed = GeoJSONParser.parse(data: data)
let styled = parsed.map { f -> GeoJSONFeature in
switch f.properties["status"] as? String {
case "alert":
var copy = f
copy.fillColor = UIColor.systemRed.withAlphaComponent(0.47)
copy.strokeWidth = 3.0
return copy
case "closed":
var copy = f
copy.visible = false
return copy
default:
return f // Sé það nil gildir sjálfgefið gildi lagsins
}
}const styled = useMemo(() =>
GeoJSONParser.parseFeatures(GEOJSON).map(f => {
const status = f.properties.status;
if (status === 'alert') {
return { ...f, fillColor: colorArgb(120, 214, 64, 69), strokeWidth: 3 };
}
if (status === 'closed') return { ...f, visible: false };
return f; // Sé það null gildir sjálfgefið gildi lagsins
}), []);
<GeoJSONLayer state={layerState} features={styled} />3-4. Að ráða úr því kvikt með StyleProvider
Að lita eftir gildi í eigind, að draga fram valið feature, að færa þröskuld úr viðmótinu — stíll sem fylgir reglu á heima í StyleProvider. Hann er kallaður einu sinni fyrir hvert feature, tekur við sjálfgefnum gildum lagsins og skilar endanlegum stíl.
Þú færð
Feature-ið (með eigindum) og núverandi sjálfgefin gildi lagsins. Venjan er að afrita sjálfgefnu gildin og breyta einu sviði.
Þú skilar
LayerStyle með öll fjögur sviðin fyllt. Skilaðu sjálfgefna gildinu fyrir allt sem þú snertir ekki og fyrsta lagið heldur áfram að virka.
// Þetta er fun interface, svo eitt lambda dugar
val densityStyle = GeoJSONStyleProviderInterface { feature, defaultStyle ->
val pop = (feature.properties["population"] as? Number)?.toInt() ?: 0
val fill = when {
pop > 500_000 -> Color.argb(150, 173, 20, 87)
pop > 200_000 -> Color.argb(120, 244, 143, 177)
else -> Color.argb(80, 248, 187, 208)
}
defaultStyle.copy(fillColor = fill) // Það sem þú lætur í friði heldur sjálfgefna gildinu
}
val layerState = remember {
GeoJSONLayerState(styleProvider = densityStyle)
}
// Sé því skipt út síðar eru öll feature endurmetin
layerState.styleProvider = DefaultGeoJSONStyleProviderfinal class DensityStyleProvider: GeoJSONStyleProvider {
func style(
for feature: GeoJSONFeature,
defaultStyle: GeoJSONTileRenderer.LayerStyle
) -> GeoJSONTileRenderer.LayerStyle {
let pop = (feature.properties["population"] as? Int) ?? 0
let fill: UIColor =
pop > 500_000 ? UIColor(red: 173/255, green: 20/255, blue: 87/255, alpha: 0.59)
: pop > 200_000 ? UIColor(red: 244/255, green: 143/255, blue: 177/255, alpha: 0.47)
: UIColor(red: 248/255, green: 187/255, blue: 208/255, alpha: 0.31)
return GeoJSONTileRenderer.LayerStyle(
strokeColor: defaultStyle.strokeColor,
fillColor: fill,
strokeWidth: defaultStyle.strokeWidth,
pointRadius: defaultStyle.pointRadius
)
}
}
layerState.styleProvider = DensityStyleProvider()// Á vefnum, í stað StyleProvider, mappaðu yfir þáttunarniðurstöðuna og
// gefðu hverju feature sinn eigin stíl (niðurstaðan er sú sama)
const styleOf = (props: Record<string, unknown>) => {
const pop = Number(props.population ?? 0);
if (pop > 500_000) return colorArgb(150, 173, 20, 87);
if (pop > 200_000) return colorArgb(120, 244, 143, 177);
return colorArgb(80, 248, 187, 208);
};
const features = useMemo(
() => GeoJSONParser.parseFeatures(GEOJSON)
.map(f => ({ ...f, fillColor: styleOf(f.properties) })),
[],
);Að skipta út provider-num — eða breyta stöðu sem hann les — endurmetur hvert feature og endurbyggir flísarnar. Þar sem hann keyrir fyrir hvert feature skaltu forreikna allt dýrt (regluleg segð, netköll, dagsetningaþáttun) utan hans.
3-5. Hvað skal velja
04 · Smellprófun
MapConductor býður aðeins eina rauf fyrir smell á kortið, svo það er forritsins að framsenda á lagið — af ásetningi, ekki sjálfvirkt. processClick skilar true aðeins þegar feature var hitt.
val layerState = remember {
GeoJSONLayerState(
onClick = { feature, position -> selected = feature },
)
}
MapLibreMapView(
state = mapViewState,
onMapClick = { point ->
// Smellprófað með 15 px vikmörkum sem fylgja aðdrættinum
val consumed = layerState.processClick(point, 15.0, mapViewState.zoom)
if (!consumed) selected = null
},
) {
GeoJSONLayer(state = layerState, features = features)
}layerState.onClick = { feature, position in
selected = feature
}
MapKitMapView(
state: mapViewState,
onMapClick: { point in
selected = nil
layerState.processClick(geoPoint: point)
}
) {
GeoJSONLayer(state: layerState, features: features)
}const layerState = useMemo(() => new GeoJSONLayerState({
onClick: (feature, position) => setSelected(feature),
}), []);
// Sendu það áfram úr smellstjóra kortsins
const handleMapClick = (point: GeoPointInterface) => {
const consumed = layerState.processClick(point, 10, state.camera.zoom);
if (!consumed) setSelected(null);
};Vikmörk í pixlum
Sendu vikmörk í pixlum og núverandi aðdrátt til processClick fyrir þröskuld sem fylgir aðdrættinum. Sé þeim sleppt gildir sjálfgefna gildið í heimshnitum (~0,0002°).
Skörun
Það feature sem var teiknað síðast — efst — og passar, er skilað.
Rúmfræði
Punktar, línur, marghyrningar með götum, fjölhlutar og rúmfræðisöfn.
05 · Gagnamagn og hleðsla
Fyrir stór gögn notaðu straumþáttarana og þáttaðu utan aðalþráðar. Það eru líka tvær leiðir til að halda á feature.
Fast og í miklu magni
Óbreytanlegir gagnahlutir — enginn stöðuhlutur á hvert feature, svo tugþúsundir haldast léttar. Notaðu þetta fyrir stórt GeoJSON.
Fá og breytast oft
Viðbragðsuppfærslur á hvert feature. Kostnaður við stöðustýringu safnast upp í miklu magni, svo notaðu það aðeins þar sem þarf.
// parseStream fyrir stórt FeatureCollection
val features = withContext(Dispatchers.IO) {
GeoJSONParser.parseStream(input)
}
// GeoJSON Text Sequences, RFC 8142
val seq = withContext(Dispatchers.IO) { GeoJSONSeqParser.parse(file) }
GeoJSONSeqParser.streamParse(file) { feature -> buffer.add(feature) }let features = GeoJSONParser.parse(fileURL: fileURL)
GeoJSONSeqParser.streamParse(fileURL: fileURL) { feature in
// Bættu við einu í einu, í lotum, eða varðveitt
}const features = GeoJSONParser.parseFeatures(text);
const seq = GeoJSONSeqParser.parse(text); // Línuskipt runa
// tileSize er sjálfgefið 512; þú getur hækkað það í Retina-þéttleika
<GeoJSONLayer state={layerState} features={features} tileSize={512} />val layerState = remember { GeoJSONLayerState() }
var features by remember { mutableStateOf(emptyList<GeoJSONFeature>()) }
var loading by remember { mutableStateOf(true) }
// parseStream returns immutable GeoJSONFeature values — no state object per feature
LaunchedEffect(Unit) {
features = withContext(Dispatchers.IO) {
context.assets.open("tokyo-buildings.geojson")
.use(GeoJSONParser::parseStream)
}
loading = false
}
MapLibreMapView(state = mapViewState) {
GeoJSONLayer(state = layerState, features = features)
}
if (loading) {
LinearProgressIndicator(modifier = Modifier.fillMaxWidth())
}