React Native Mapbox(v10) 사용법

11439 단어 mapreactnativemobile

용법:



SAMPLE VIDEO

샘플 데이터:

{
  "type": "FeatureCollection",
  "name": "GeoJsonData",

  "features": [
    {
      "type": "Feature",
      "properties": {
        "status": "sold",
        "Name": "دورات مياة",
        "description": null,
      },
      "geometry": {
        "type": "MultiPolygon",
        "coordinates": [
          [
            [
              [46.6973896223821, 24.7938909593501],
              [46.69730684623009, 24.79405349682493],
              [46.69722194475514, 24.79401653642232],
              [46.69730416732871, 24.79385517629931],
              [46.6973896223821, 24.7938909593501]
            ]
          ]
        ]
      }
    },
*
*
*
]}


Mapbox.js

import React, {useRef, useState} from 'react';
import {InteractionManager, TouchableOpacity, View} from 'react-native';
import styles from './style';
import MapboxGL, {Camera} from '@rnmapbox/maps';
import {MAP_NOX_ACCESS_TOKEN} from '../../utils/constants/constants';
import {ICONOGRAPHY, IMAGES} from '../../assets';
import * as turf from '@turf/turf';
import {
  COLOR_GREEN_PLOT_OPACITY,
} from '../../utils/colors';
import {isIOS} from '../../utils/helper';
import HeaderComponentPlotMap from './HeaderComponentPlotMap';
import PopupBottom from './popupBottom';
import CustomIcon from '../CustomIcon';

MapboxGL.setAccessToken(MAP_NOX_ACCESS_TOKEN);

const MapBox = props => {
  const {navigation} = props || {};
  const url = 'https://cdn.wasalt.com/kml3.json';
  const style_MB = {
    neighborhoods: {
      fillColor: COLOR_RED_PLOT_OPACITY,
      fillOpacity: 0.5,
    },
    selectedNeighborhoods: {
      fillColor: COLOR_GREEN_PLOT_OPACITY,
      fillOpacity: 0.5,
    },
    neighborhoodsD: {
      fillColor: RED_SELECTED_PLOT,
    },
    selectedNeighborhoodsD: {
      fillColor: GREEN_SELECTED_PLOT,
    },
    line2: {
      lineColor: COLOR_WHITE,
      lineWidth: 0.5,
    },
    selectedText: {
      textColor: COLOR_WHITE,
      textHaloColor: COLOR_BLACK,
      textHaloWidth: 1,
      textSize: 16,
    },
    selectedBorder: {
      lineColor: COLOR_WHITE,
      lineWidth: 3.5,
    },
    borderText: {
      symbolPlacement: 'line-center',
      textColor: COLOR_BLACK,
      textHaloColor: COLOR_WHITE,
      textHaloWidth: 1.5,
      textSize: 18,
      textLetterSpacing: 0.1,
    },
    dotStyle: {
      iconImage: IMAGES.CIRCLE_FILLED,
      iconSize: 0.3,
    },
    gobck: {
      position: 'absolute',
      zIndex: 1,
      height: 30,
      width: 30,
      top: 50,
      left: 20,
      backgroundColor: 'red',
    },
    deselectText: {
      textColor: COLOR_WHITE,
      textHaloColor: COLOR_BLACK,
      textHaloWidth: 1,
    },
  };

  const [selectedDist, setSelectedDist] = useState();
  const [selectedPolySides, setselectedPolySides] = useState();
  const [isSateliteStyle, setSateliteStyle] = useState(true);
  const [headerHeight, setheaderHeight] = useState(0);
  let centerCoordinate = [46.691913306713104, 24.796909229152348];
  let zoomLevel = 15;
  let _map = useRef(null);
  const camera = useRef(null);

  /**
   * Calculates the haversine distance between point A, and B.
   * @param {number[]} latlngA [lat, lng] point A
   * @param {number[]} latlngB [lat, lng] point B
   * @param {boolean} isMiles If we are using meters, else km.
   * @param {boolean} isMiles If we are using miles, else km.
   */
  // const haversineDistance = (
  //   latlngA,
  //   latlngB,
  //   isMeters = false,
  //   isMiles = false,
  // ) => {
  //   const squared = x => x * x;
  //   const toRad = x => (x * Math.PI) / 180;
  //   const R = 6371; // Earth’s mean radius in km

  //   const dLat = toRad(latlngB[0] - latlngA[0]);
  //   const dLon = toRad(latlngB[1] - latlngA[1]);

  //   const dLatSin = squared(Math.sin(dLat / 2));
  //   const dLonSin = squared(Math.sin(dLon / 2));

  //   const a =
  //     dLatSin +
  //     Math.cos(toRad(latlngA[0])) * Math.cos(toRad(latlngB[0])) * dLonSin;
  //   const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
  //   let distance = R * c;

  //   if (isMiles) {
  //     distance /= 1.609344;
  //   }
  //   if (isMeters) {
  //     distance *= 1000;
  //   }

  //   return distance;
  // };

  const onPressPolygon = items => {
    console.log('onPressPolygon', items);
    let feature = items?.nativeEvent.payload;
    let polygonCoordinates = feature?.geometry?.coordinates[0];
    let arrayOfPolygonSides = [];

    //Showing polygon border dimension using LineString
    for (let i = 0; i < polygonCoordinates.length - 1; i++) {
      let line = turf.lineString([
        polygonCoordinates[i],
        polygonCoordinates[i + 1],
      ]);
      let length = turf.length(line, {units: 'meters'});
      let lineStrings = {
        type: 'Feature',
        properties: {
          Length: Number(length).toFixed(1) + 'm',
        },
        geometry: {
          type: 'LineString',
          coordinates: [polygonCoordinates[i], polygonCoordinates[i + 1]],
        },
      };
      arrayOfPolygonSides.push(lineStrings);
    }

    let finalObj = {
      type: 'FeatureCollection',
      features: arrayOfPolygonSides,
    };
    setselectedPolySides(finalObj);
    setSelectedDist(feature);

    //get bound area to move properly to selected polygon
    var bboxPolygon = turf.bbox(feature);
    let minCoor = [bboxPolygon[0], bboxPolygon[1]];
    let maxCoor = [bboxPolygon[2], bboxPolygon[3]];
    camera?.current?.fitBounds(minCoor, maxCoor, 20, 2000);
  };
  const onMapLoad = () => {
    InteractionManager.runAfterInteractions(() =>
      camera?.current?.setCamera({
        centerCoordinate,
        zoomLevel,
        animationDuration: 5000,
        animationMode: 'flyTo',
      }),
    );
  };

  const onPressMapView = () => {
    setSelectedDist();
    setselectedPolySides();
  };

  const setMapTypeFunc = () => {
    setselectedPolySides();
    setSelectedDist();
    setTimeout(() => {
      setSateliteStyle(v => !v);
    }, 500);
  };

  const onCloseBottomCard = () => {
    setselectedPolySides();
    setSelectedDist();
  };

  const SelectedPolygon = () =>
    selectedDist ? (
      <MapboxGL.ShapeSource id="selectedNYC" shape={selectedDist}>
        <MapboxGL.FillLayer
          sourceID="nyc"
          id="nycSelectedFillRed"
          style={style_MB.neighborhoodsD}
          filter={['!=', 'status', 'sold']}
        />
        <MapboxGL.FillLayer
          sourceID="nyc"
          id="nycSelectedFillGreen"
          style={style_MB.selectedNeighborhoodsD}
          filter={['==', 'status', 'sold']}
        />

        <MapboxGL.SymbolLayer
          sourceID="selectedNYC"
          id="image1"
          style={style_MB.dotStyle}
          maxZoomLevel={17}
        />
        <MapboxGL.SymbolLayer
          sourceID="selectedNYC"
          id="Name1"
          style={{
            ...style_MB.selectedText,
            textField: '{Name}',
          }}
          minZoomLevel={17}
        />
      </MapboxGL.ShapeSource>
    ) : null;

  const SelectedPolygonBorder = () =>
    selectedPolySides ? (
      <MapboxGL.ShapeSource id="borderSrc" shape={selectedPolySides}>
        <MapboxGL.LineLayer
          sourceID="borderSrc"
          id="borderLine"
          style={style_MB.selectedBorder}
        />
        <MapboxGL.SymbolLayer
          sourceID="borderSrc"
          id="border"
          minZoomLevel={3}
          style={{
            ...style_MB.borderText,
            textField: '{Length}',
          }}
        />
      </MapboxGL.ShapeSource>
    ) : null;

  return (
    <View style={styles.page}>
      <HeaderComponentPlotMap
        getHeight={v => setheaderHeight(v)}
        navigation={navigation}
      />
      <TouchableOpacity
        style={styles.mapType(isSateliteStyle, headerHeight)}
        onPress={setMapTypeFunc}>
        <CustomIcon
          color={!isSateliteStyle ? COLOR_GRAY_70 : COLOR_SECONDARY}
          name={ICONOGRAPHY.FLOORS}
          size={20}
        />
      </TouchableOpacity>

      <View style={styles.container}>
        <MapboxGL.MapView
          // zoomEnabled={false}
          // scrollEnabled={false}
          // pitchEnabled={false}
          // rotateEnabled={false}
          // onRegionDidChange={onRegionDidChange}
          onPress={onPressMapView}
          style={styles.map}
          styleURL={
            isSateliteStyle
              ? MapboxGL.StyleURL.Satellite
              : MapboxGL.StyleURL.Street
          }
          ref={_map}
          localizeLabels={true}
          scaleBarEnabled={isIOS() ? true : false}
          compassEnabled={true}
          scaleBarPosition={{bottom: 0, left: 8}}
          compassPosition={{bottom: 20, left: 8}}
          logoEnabled={false}
          onDidFinishLoadingMap={onMapLoad}>
          <Camera ref={camera} />
          <MapboxGL.ShapeSource
            id="nyc"
            url={url}
            onPress={items => {
              onPressPolygon(items);
            }}>
            <MapboxGL.FillLayer
              id="nycFill"
              style={style_MB.neighborhoods}
              filter={['!=', 'status', 'sold']}
            />
            <MapboxGL.FillLayer
              id="nycFilled"
              style={style_MB.selectedNeighborhoods}
              filter={['==', 'status', 'sold']}
            />
            <MapboxGL.LineLayer
              sourceID="nyc"
              id="nycFillLine"
              style={style_MB.line2}
            />
            <MapboxGL.SymbolLayer
              sourceID="nyc"
              id="image"
              style={style_MB.dotStyle}
              maxZoomLevel={17}
            />
            <MapboxGL.SymbolLayer
              sourceID="nyc"
              id="Name"
              style={{
                ...style_MB.deselectText,
                textField: '{Name}',
              }}
              minZoomLevel={17}
            />
          </MapboxGL.ShapeSource>

          <SelectedPolygon />

          <SelectedPolygonBorder />
        </MapboxGL.MapView>
      </View>
      {selectedDist === null || selectedDist === undefined ? null : (
        <PopupBottom
          navigation={navigation}
          clickedPolygon={selectedDist}
          onPressCloseButton={onCloseBottomCard}
        />
      )}
    </View>
  );
};

export default MapBox;

좋은 웹페이지 즐겨찾기