Преглед изворни кода

added seperate IndoorFloor component to load each floor, added support to pass through svg information

Eric Li пре 2 година
родитељ
комит
aab50842d8

+ 24 - 0
src/components/Map/IndoorFloor.tsx

@@ -0,0 +1,24 @@
+import { View, Text } from 'react-native'
+import React from 'react'
+import BasementC from './MainMapComponent/images/BasementC.svg'
+import FirstFloorC from './MainMapComponent/images/FirstFloorC.svg'
+import SecondFloorC from './MainMapComponent/images/SecondFloorC.svg'
+import ThirdFloorC from './MainMapComponent/images/ThirdFloorC.svg'
+import FourthFloorC from './MainMapComponent/images/FourthFloorC.svg'
+import FifthFloorC from './MainMapComponent/images/FifthFloorC.svg'
+
+// export const IndoorFloor: React.FC<{floorNum: number}> = (props) => {
+function IndoorFloor(props) {
+  const compArray = [
+      <BasementC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
+      <FirstFloorC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
+      <SecondFloorC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
+      <ThirdFloorC viewBox='250 136 310 310' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
+      <FourthFloorC viewBox='260 151 270 260' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
+      <FifthFloorC viewBox='257 153 270 290' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
+  ]
+
+  return compArray[props.floorNum]
+}
+
+export default IndoorFloor

+ 9 - 21
src/components/Map/MainMapComponent/IndoorMap.tsx

@@ -12,15 +12,9 @@ import { FontAwesome } from "@expo/vector-icons";
 import ReactDOMServer from 'react-dom/server'; //npm i --save-dev @types/react-dom
 
 
-import BasementC from './images/BasementC.svg';
-import FirstFloorC from './images/FirstFloorC.svg'
-import SecondFloorC from './images/SecondFloorC.svg'
-import ThirdFloorC from './images/ThirdFloorC.svg'
-import FourthFloorC from './images/FourthFloorC.svg'
-import FifthFloorC from './images/FifthFloorC.svg'
 import { Landmark } from '../../../hooks/useLandmarks';
 import { ZoomableViewEvent } from '@openspacelabs/react-native-zoomable-view/src/typings';
-
+import IndoorFloor from '../IndoorFloor'
 
 interface IndoorMapProps {
   navigation: MapStackNavigationProp
@@ -107,14 +101,6 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
 
 
 
-  const compArray = [
-    <BasementC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
-    <FirstFloorC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
-    <SecondFloorC style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
-    <ThirdFloorC viewBox='250 136 310 310' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
-    <FourthFloorC viewBox='260 151 270 260' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
-    <FifthFloorC viewBox='257 153 270 290' style={{ opacity: 0.7 }} height={"100%"} width={"100%"} />,
-  ]
 
 
   const childToWeb = (child: any) => {
@@ -212,14 +198,14 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
               initialOffsetY={5}
               onLongPress={(event) => {
                 console.log(event.nativeEvent)
-                serialize()
+                // serialize()
                 addLandmark(event)
               }}>
 
 
 
               <Svg onLayout={event => {
-                // console.log("OFFICIAL: " + event.nativeEvent.layout.width + " , " + event.nativeEvent.layout.height)
+                console.log("OFFICIAL: " + event.nativeEvent.layout.width + " , " + event.nativeEvent.layout.height)
                 setSVGdim([event.nativeEvent.layout.width, event.nativeEvent.layout.height])
 
                 const transformedLandmarks = localLandmarks.map(item => {
@@ -231,7 +217,9 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
               >
                 {/* {firstTime == true ? undefined : loadCircles} */}
                 {loadCircles}
-                {compArray[floor]}
+                <IndoorFloor floorNum={floor}/>
+
+
               </Svg>
 
 
@@ -249,8 +237,8 @@ const IndoorMap: React.FC<IndoorMapProps> = ({ navigation, landmarks, promptAddL
         setLocalLandmarks(landmarks)
       }} /> */}
 
-      <Button title='Press me to svgString' color={colors.red} onPress={serialize}></Button>
-      {/* <Button title="Go back to map" color={colors.red} onPress={() => navigation.goBack()} /> */}
+      {/* <Button title='Press me to svgString' color={colors.red} onPress={serialize}></Button> */}
+      <Button title="Go back to map" color={colors.red} onPress={() => navigation.goBack()} />
       {/* <TouchableOpacity style={styles.arrowButton} onPress={() => setFloor(prevState => prevState+1)} ><Text>Increase floor by 1</Text></TouchableOpacity> */}
 
     </View>
@@ -265,7 +253,7 @@ const styles = StyleSheet.create({
     borderColor: "black",
     borderWidth: 2,
     marginVertical: 7,
-    aspectRatio: 8 / 10,  // (caters to portrait mode) (width is 66% the value of height dimension)
+    aspectRatio: 8 / 10,  // (caters to portrait mode) (width is 80% the value of height dimension)
     // flex: 1,
     // // backgroundColor: "#fff",
     // justifyContent: "center",

+ 78 - 2
src/components/Map/Panels/AddLandmarkPanel.tsx

@@ -9,7 +9,7 @@ import { FontAwesome } from "@expo/vector-icons";
 import * as ImagePicker from 'expo-image-picker';
 import { ImageInfo } from "expo-image-picker/build/ImagePicker.types";
 import React, { memo, useEffect, useState } from "react";
-import { ActivityIndicator, Dimensions, Image, Platform, SafeAreaView, Text, TextInput, TouchableOpacity, View } from 'react-native';
+import { ActivityIndicator, Dimensions, Image, Platform, SafeAreaView, Text, TextInput, TouchableOpacity, View, ImageSourcePropType} from 'react-native';
 import { ScrollView } from "react-native-gesture-handler";
 import Modal from 'react-native-modal';
 import { checkMultiple, PERMISSIONS, RESULTS } from "react-native-permissions";
@@ -19,6 +19,10 @@ import { colors, getMediaPermissions, lmTypes } from "../../../utils/GlobalUtils
 import { IconButton, SecondaryButton } from "../../Buttons";
 import { PhotoPicker } from "../../PhotoPicker";
 import TouchOpaq from "./LandmarkDetailsPanel/TouchOpaq";
+import {Svg , Rect, Image as ImageSVG} from 'react-native-svg'
+import ReactDOMServer from 'react-dom/server'; //npm i --save-dev @types/react-dom
+
+import IndoorFloor from "../IndoorFloor";
 
 /**
  * Props for the {@link AddLandmarkPanel} component.
@@ -52,6 +56,10 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({newLandmark, setNewLandma
     const [photos, setPhotos] = useState<LMPhoto[]>([])
     const [photoSourceMenuOpened, togglePhotoSourceMenu] = useState<boolean>(false)
 
+    const imgWidth = 346
+    const imgHeight = 443
+    const imageDim = 5
+
     const { 
         addLandmarkAsync, 
         resetAddLm, 
@@ -76,12 +84,80 @@ const AddLandmarkPanel: React.FC<AddLandmarkProps> = ({newLandmark, setNewLandma
         resetAddLm();
     }, [visible]);
 
+
+
+
+    const renderIndoorLandmarkPin = (landmark: Landmark) => {
+        return (
+            <ImageSVG
+              x={landmark.longitude * imgWidth}
+              y={landmark.latitude * imgHeight}
+              width={imageDim}
+              height={imageDim}
+              href={lmTypes[landmark.landmark_type]['image'] as ImageSourcePropType} />
+          )
+    } 
+
+    // const renderLandmarkSvg = (floor: number) => {
+    //     return (
+    //         <Svg height={imgHeight} width={imgWidth}>
+    //             <IndoorFloor floorNum={floor} />
+    //             {renderIndoorLandmarkPin(newLandmark)}
+    //         </Svg>
+    //     )
+    // }
+
+
+
+    const childToWeb = (child: any) => {
+        const { type, props } = child;
+        const name = type && type.displayName;
+        const webName = name && name[0].toLowerCase() + name.slice(1);
+        const Tag = webName ? webName : type;
+        return <Tag {...props}>{toWeb(props.children)}</Tag>;
+      };
+    
+      const toWeb = (children: any) => React.Children.map(children, childToWeb);
+    
+      function renderLandmarkSvg(floor) {
+        return (
+        // <svg height="100%" width="100%" style="background-color:#33AAFF" preserveAspectRatio="xMidYMid meet"><rect x="50" y="50" width="50" height="50" fill="#3399ff" stroke-width="3" stroke="rgb(0,0,0)"></rect></svg>
+        //                                 style={{backgroundColor:'#33AAFF'}}
+          <Svg height="100%" width="100%" style={{ backgroundColor: '#33AAFF' }}>
+          <Rect
+            x="50"
+            y="50"
+            width="50"
+            height="50"
+            fill="#3399ff"
+            strokeWidth="3"
+            stroke="rgb(0,0,0)"
+          />
+        </Svg>
+        )
+      }
+
+    function serialize() {
+        const element = renderLandmarkSvg(newLandmark.floor);
+        const webJsx = toWeb(element);
+        const svgString = ReactDOMServer.renderToStaticMarkup(webJsx);
+        console.log(svgString)
+        return svgString
+      }
+
     /**
      * Calls {@link addLandmarkAsync} from {@link useLandmarks} to initate the process of adding a landmark, then closes the modal.
      */
     const submit = async () => {
         // create svg content here, then pass it to addLandmarkAsync as the value of indoorLmLocImg
-        await addLandmarkAsync({landmarkValue: newLandmark, photos: photos, indoorLmLocImg: undefined }); // pass it in here
+        if(typeof newLandmark.floor === 'number'){
+            let rectangle = serialize()
+            await addLandmarkAsync({landmarkValue: newLandmark, photos: photos, indoorLmLocImg: rectangle }); // pass it in here
+        }
+        else{
+            await addLandmarkAsync({landmarkValue: newLandmark, photos: photos }); 
+        }
+        
         close()
     }