Docs / एक्सटेंशन लेयर / GeoJSON लेयर

GeoJSON लेयर

GeoJSON को जैसा-का-तैसा मानचित्र पर ओवरले करने के लिए एक एक्सटेंशन पैकेज है। फीचर को टाइल में रेस्टराइज़ करके रेंडर करने के कारण, दसियों हजारों फीचर के स्तर पर भी 1 फीचर-1 ऑब्जेक्ट बनाने की आवश्यकता नहीं होती है। Android, iOS, और React पर API नाम, स्टाइल डिफ़ॉल्ट मान, और हिट टेस्ट का व्यवहार संरेखित है।

ANDROID
com.mapconductor:geojson
IOS
MapConductorGeoJSON
REACT
@mapconductor/react-geojson-layer
रेंडरिंग विधि
रेस्टर टाइल
प्लेटफ़ॉर्म

01 · अवलोकन

GeoJSON को पार्स करके हल्के फीचर मॉडल में बदलता है और MapConductor की रेस्टर टाइल पाइपलाइन के माध्यम से रेंडर करता है। प्रदाता (Google Maps, MapLibre, MapKit, HERE आदि) कुछ भी हो, कोड और दिखावट समान रहता है।

पर्सपेक्टिव

01

FeatureCollection, व्यक्तिगत Feature, और कच्ची ज्यामिति, साथ ही RFC 8142 टेक्स्ट सीक्वेंस का समर्थन करता है। स्ट्रीमिंग पार्सर भी शामिल है।

टाइल रेंडरिंग

02

फीचर्स को 512px टाइल्स में रैस्टराइज़ करता है और उन्हें एक रैस्टर लेयर के रूप में मैप पर लोड करता है। यह प्रदाता की वेक्टर क्षमताओं पर निर्भर नहीं करता है।

हिट टेस्टिंग

03

रेंडरिंग में उपयोग किए गए समान निर्देशांकों के साथ क्लिक का पता लगाता है। इसमें छिद्रित बहुभुज, मल्टी-पार्ट, और ज्यामिति संग्रह का समर्थन शामिल है।

Point
MultiPoint
LineString
MultiLineString
Polygon
MultiPolygon
GeometryCollection

सभी ज्यामिति प्रकारों को 3 प्लेटफ़ॉर्म पर समान रूप से समर्थन देता है।

02 · बुनियादी उपयोग

लेयर को बस मैप व्यू के content स्कोप के अंदर रखें। पार्सिंग बैकग्राउंड में की जाती है और परिणाम को features में पास किया जाता है।

build.gradle.kts
dependencies {
    implementation("com.mapconductor:geojson:<version>")
}
com.mapconductor.geojson · Compose
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)
}

जब फीचर की सामग्री या स्टाइल बदलती है, तो लेयर आंतरिक रूप से टाइल URL को अमान्य कर देती है। मानचित्र SDK की ओर से रेस्टर कैश पुरानी छवि वापस नहीं करता है।

03 · स्टाइल निर्धारण

स्टाइल 3 स्तरों में हल की जाती है

यह "पूरी लेयर के लिए डिफ़ॉल्ट मान", "प्रति फीचर ओवरराइड", और "StyleProvider द्वारा गतिशील निर्धारण" के 3 स्तर हैं। निचला स्तर जितना अधिक शक्तिशाली होता है, और निर्दिष्ट न किए गए आइटम ऊपर के स्तर से विरासत में मिलते हैं। पहले केवल लेयर डिफ़ॉल्ट मान से शुरू करना और फिर आवश्यकतानुसार निचले स्तरों को जोड़ना मूल दृष्टिकोण है।

चित्र · निर्धारण का क्रम
LAYER 1
लेयर के डिफ़ॉल्ट
GeoJSONLayerState
हर फ़ीचर पर लगने वाला आधार: strokeColor, fillColor, strokeWidth, pointRadius।
LAYER 2
हर फ़ीचर का ओवरराइड
GeoJSONFeature.strokeColor …
हर फ़ीचर पर उन्हीं नामों के फ़ील्ड। null छोड़ने पर लेयर का डिफ़ॉल्ट जस का तस लगता है।
LAYER 3
गतिशील निर्धारण
GeoJSONStyleProvider
हर फ़ीचर के लिए एक बार बुलाया जाता है और अंतिम स्टाइल लौटाता है — प्रॉपर्टी के आधार पर रंग तय करना यहीं होता है।
कोई प्रोवाइडर न दिया जाए तो DefaultGeoJSONStyleProvider लगता है: फ़ीचर का मान हो तो वह, वरना लेयर का डिफ़ॉल्ट। तीसरी परत दरअसल इसी संबंध को ही बदल देने का तरीका है।

3-1. स्टाइल गुण

केवल 4 गुणों का उपयोग किया जाता है। इसके अतिरिक्त, लेयर पक्ष में प्रदर्शन नियंत्रण के लिए opacity, visible, minZoom / maxZoom हैं।

गुण
प्रकार
डिफ़ॉल्ट मान
विवरण
strokeColor
ARGB Int / UIColor / number
#FF1E88E5
लाइन और पॉलीगॉन की रूपरेखा का रंग।
fillColor
ARGB Int / UIColor / number
#801E88E5
पॉलीगॉन का भरण और पॉइंट के वृत्त का रंग। डिफ़ॉल्ट रूप से अर्ध-पारदर्शी है।
strokeWidth
Float / CGFloat / number
2.0
लाइन चौड़ाई (पिक्सेल)। चूंकि इसे टाइल में रेस्टराइज़ किया जाता है, ज़ूम करने पर भी मोटाई स्थिर रहती है।
pointRadius
Float / CGFloat / number
8.0
पॉइंट बनाने वाले वृत्त की त्रिज्या (पिक्सेल)।
opacity
Float / Double / number
1.0
पूरे रेस्टर लेयर की अपारदर्शिता। यह अलग से व्यक्तिगत रंग के अल्फा को प्रभावित करता है।
visible
Boolean
true
रेंडरिंग और हिट टेस्ट दोनों से बाहर रखा गया है। फीचर पक्ष पर भी इसी नाम का फ़ील्ड होता है।
minZoom / maxZoom
Int / number
0 / 22
उत्पन्न रेस्टर लेयर को प्रदर्शित करने के लिए ज़ूम सीमा। सीमा से बाहर टाइल जनरेशन नहीं चलती है।

3-2. लेयर डिफ़ॉल्ट तय करना

पहले यहाँ से शुरू करें। GeoJSONLayerState में पास किए गए मान सभी फ़ीचर की नींव बनाते हैं। स्थिति observable है, इसलिए बाद में मान असाइन करने पर फिर से रेंडर होगा।

Kotlin · ARGB Int
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,
    )
}

// स्टेट अवलोकनीय है: बाद में मान देने पर टाइल दोबारा बनती हैं
layerState.fillColor = Color.argb(90, 214, 64, 69)

रंग निर्दिष्ट करने का प्रारूप

Android और React ARGB के 32-बिट पूर्णांक (अल्फा सबसे ऊपरी बाइट) का उपयोग करते हैं, iOS UIColor का उपयोग करता है जिसमें अल्फा रंग के साथ ही होता है। React में colorArgb(a,r,g,b) / colorRgb(r,g,b) / argbToCss() हेल्पर हैं, और Android के Color.argb() के समान क्रम है। 3 प्लेटफ़ॉर्म के डिफ़ॉल्ट रंग सभी #1E88E5 (लाइन अपारदर्शी, भराव अल्फा 128) पर सेट हैं।

3-3. प्रति फ़ीचर ओवरराइड करना

फ़ीचर में strokeColor / fillColor / strokeWidth / pointRadius / visible हो सकते हैं। यदि null रहता है तो डिफ़ॉल्ट मान, यदि मान है तो वही मान जीतता है। डेटा लोड होने पर स्टाइल तय हो जाता है (बाद में नहीं बदलता), तो यह तरीका सबसे सीधा और तेज़ तरीका है।

Kotlin · GeoJSONFeature.copy
val parsed = GeoJSONParser.parseStream(input)

// पार्स करने के बाद प्रॉपर्टी देखकर स्टाइल पक्की कर दें
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   // null छोड़ा है, इसलिए लेयर का डिफ़ॉल्ट लगता है
    }
}

GeoJSONLayer(state = layerState, features = styled)

3-4. StyleProvider से गतिशील रूप से तय करना

properties के मान से रंग अलग करना, केवल चयनित फ़ीचर को जोरदार बनाना, UI से थ्रेशोल्ड बदलना ── इस तरह के "नियम से तय होने वाले स्टाइल" StyleProvider में लिखे जाते हैं। यह हर फ़ीचर के लिए कॉल होता है, लेयर डिफ़ॉल्ट प्राप्त करता है और अंतिम स्टाइल लौटाता है।

पास किया जाने वाला डेटा

फीचर की मुख्य वस्तु (properties सहित) और उस समय की लेयर डिफ़ॉल्ट वैल्यू। डिफ़ॉल्ट वैल्यू की copy करना और केवल कुछ हिस्सों को बदलना एक मानक तरीका है।

वापसी मान

एक LayerStyle जिसमें सभी 4 आइटम भरे हुए हों। जिन आइटम्स को नहीं छुआ गया है, यदि आप डिफ़ॉल्ट वैल्यू वापस कर देते हैं, तो पहली परत की सेटिंग्स प्रभावी होंगी।

Kotlin · GeoJSONStyleProviderInterface
// यह fun interface है, इसलिए एक लैम्ब्डा से लिखा जा सकता है
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)   // जिन्हें नहीं छूते, वे डिफ़ॉल्ट पर रहते हैं
}

val layerState = remember {
    GeoJSONLayerState(styleProvider = densityStyle)
}

// बाद में बदलने पर हर फ़ीचर दोबारा आँका जाता है
layerState.styleProvider = DefaultGeoJSONStyleProvider

StyleProvider को बदलने या संदर्भित स्थिति बदलने पर, सभी फ़ीचर के स्टाइल का पुनर्मूल्यांकन होता है और टाइल फिर से बनाई जाती है। चूंकि इसे हर आइटम के लिए कॉल किया जाता है, कृपया भारी प्रक्रियाओं (रेगुलर एक्सप्रेशन, नेटवर्क, दिनांक पार्सिंग आदि) को provider के बाहर पहले से गणना कर लें।

3-5. किसका उपयोग करें

तरीका
उपयुक्त स्थिति
टिप्पणी
LayerState
डेटा को एक ही रूप में आरेखित करें।
सबसे हल्का। सबसे पहले यहाँ से शुरू करें।
Feature override
लोड होने पर स्टाइल निश्चित हो और बाद में न बदले।
पार्स परिणाम को केवल map करें। provider कॉल की लागत नहीं है।
StyleProvider
स्टाइल नियमों से तय होता है। नियम स्वयं निष्पादन के दौरान बदलते हैं।
लॉजिक को एक जगह पर एकत्र किया जा सकता है। RN में नेटिव पंजीकरण आवश्यक है।

04 · टैप पहचान

MapConductor का क्लिक लिसनर केवल एक ही है, इसलिए लेयर में फॉरवर्डिंग ऐप साइड से की जाती है। जानबूझकर स्वचालित पंजीकरण नहीं किया गया है। processClick, फ़ीचर के मिलने पर ही true लौटाता है।

Kotlin
val layerState = remember {
    GeoJSONLayerState(
        onClick = { feature, position -> selected = feature },
    )
}

MapLibreMapView(
    state = mapViewState,
    onMapClick = { point ->
        // 15 px के बराबर सहनशीलता से जाँच (ज़ूम के साथ बदलती है)
        val consumed = layerState.processClick(point, 15.0, mapViewState.zoom)
        if (!consumed) selected = null
    },
) {
    GeoJSONLayer(state = layerState, features = features)
}

पिक्सेल सहनशीलता

processClick को सहनशील पिक्सेल और वर्तमान ज़ूम स्तर देने पर, ज़ूम के अनुसार पता लगाना संभव होता है। यदि छोड़ा जाता है, तो यह विश्व निर्देशांकों की डिफ़ॉल्ट सहनशीलता (लगभग 0.0002°) होती है।

ओवरलैप होने पर

अंतिम रूप से रेंडर किया गया (यानी सबसे ऊपर वाला) फीचर वापस आता है।

समर्थित ज्यामिति

बिंदु, रेखा, छिद्रित बहुभुज, मल्टी-पार्ट ज्यामिति संग्रह।

05 · डेटा मात्रा और लोडिंग

बड़े डेटा के लिए स्ट्रीमिंग पार्सर का उपयोग करें और बैकग्राउंड में पार्स करें। फ़ीचर रखने के दो तरीके भी हैं।

स्थैतिक और बड़े मात्रा के लिए

GeoJSONFeature

अपरिवर्तनीय डेटा ऑब्जेक्ट। यह हल्का होता है क्योंकि इसमें यहां तक कि हजारों आइटम्स के लिए भी स्टेट ऑब्जेक्ट नहीं बनाया जाता है। बड़े GeoJSON के लिए यही विकल्प है।

थोड़ी संख्या और बार-बार बदलने वाले के लिए

GeoJSONFeatureState

एक-एक करके प्रतिक्रियाशील रूप से अपडेट किया जा सकता है। जब संख्या अधिक होती है, तो स्टेट प्रबंधन की लागत प्रभावी होती है, इसलिए केवल आवश्यक हिस्सों तक सीमित रखें।

Kotlin · streaming
// बड़े FeatureCollection के लिए parseStream
val features = withContext(Dispatchers.IO) {
    GeoJSONParser.parseStream(input)
}

// RFC 8142 वाले GeoJSON Text Sequences
val seq = withContext(Dispatchers.IO) { GeoJSONSeqParser.parse(file) }
GeoJSONSeqParser.streamParse(file) { feature -> buffer.add(feature) }
वीडियो में दिखाया गया कार्यान्वयन · Android + MapLibreKotlin · Jetpack Compose
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())
}
नमूना वीडियो · बड़े GeoJSON को टाइल के रूप में लोड करना
वीडियो अभी नहीं बनास्क्रॉल का अनुसरण करते हुए टाइल क्रमशः लोड होती हैं और रेंडरिंग भरता जाता है। डेटा की मात्रा बढ़ने पर भी ऑपरेशन रुकता नहीं है, यह स्थिर छवि में संप्रेषित नहीं होता है।

06 · वर्तमान सीमाएं

लेयर पर क्लिक श्रोताओं का स्वचालित पंजीकरण नहीं किया जाता है। processClick में अग्रेषित करें (यह एक जानबूझकर किया गया डिज़ाइन है)।
हिट टेस्ट के लिए रेखा और बिंदु की डिफ़ॉल्ट सहनशीलता आंतरिक स्थिरांक है। प्रत्येक कॉल पर पिक्सेल सहनशीलता पास करके समायोजित किया जा सकता है।
रेखापुंज टाइल के रूप में प्रस्तुत करने के कारण, मैप SDK देशी वेक्टर सुविधा क्वेरी का उपयोग नहीं किया जाता है।
पार्सर अमान्य इनपुट के लिए अपवाद नहीं फेंकता है, बल्कि एक खाली सुविधा सरणी लौटाता है (iOS)।

संबंधित पेज