API Longdo Map Features

วิธีเขียน Mobile App แผนที่อย่างง่าย ด้วย Longdo Map React Native

บทความนี้จะพูดถึงการแนะนำวิธีการพัฒนาแอปพลิเคชันที่มีแผนที่ออนไลน์ (Longdo Map) ผ่าน framework ยอดฮิตอีกตัวอย่าง React Native ซึ่งในก่อนหน้านี้ เราได้มีบทความวิธีการสอนใช้ การใช้แผนที่ Longdo Map ใน Flutter Application ไปแล้ว วันนี้จึงเป็นตาของเฟรมเวิร์คตัวนี้กันบ้าง

Longdo Map first app
ตัวอย่างหน้าจอแสดงผลแผนที่ และเมนูต่าง ๆ

หัวข้อต่าง ๆ

  • Installation
  • Getting Started
  • Initial Map
  • UI Map
  • Marker
  • Geometries (Polyline, Polygon, Circle Etc.)
  • Routing
  • Search
  • Documentation

Installation

ติดตั้ง React Native CLI Quickstart ตามคำแนะนำให้เสร็จสิ้น หลังจากนั้นจึงติดตั้ง Longdo Map React Native ด้วยวิธีการต่อไปนี้ (Longdo Map React Native’s Github)

Setting Up (Expo)

เริ่มจากการสร้างโปรเจคและติดตั้ง dependency ต่างๆ

npm install -g expo-cli
npx create-expo-app <PROJECT_NAME> --template blank@47
cd <PROJECT_NAME>
npm install [email protected]
npm install longdo-map-react-native
  • PROJECT_NAME คือชื่อโปรเจคที่จะสร้าง

หลังจากนั้นให้ไปที่ไฟล์ babel.config.js เพื่อแก้ไขโค้ดส่วนที่อยู่ใน presets ดังนี้

presets: [
      'babel-preset-expo',
      ['@babel/preset-env', { "targets": "iOS >= 11, Android >= 56" }],
],

หลังจากนั้นไปที่ไฟล์ app.json ไปที่ ios ใส่ bundleIdentifier, android ใส่ package

"ios": {
      "bundleIdentifier": "BUNDLE_ID",
...
"android": {
      "package": "PACKAGE_NAME",
  • BUNDLE_ID และ PACKAGE_NAME คือเลข bundle และชื่อโปรเจคที่จะสร้าง

Setting Up (React Native CLI)

เริ่มจากการสร้างโปรเจคและติดตั้ง dependency ต่าง ๆ

npm install [email protected] longdo-map-react-native
npm install -D @babel/preset-env

หลังจากนั้นให้ไปที่ไฟล์ babel.config.js เพื่อแก้ไขโค้ดส่วนที่อยู่ใน presets ดังนี้

presets: [
    'module:metro-react-native-babel-preset',
    ['@babel/preset-env', { "targets": "iOS >= 11, Android >= 56" }],
],

Getting Started

  1. เพิ่ม Import Longdo ไปยังไฟล์ App.js
import Longdo from 'longdo-map-react-native';

2. ใส่ Key API

Longdo.apiKey = '[Your-Key-API]';

สามารถดูตัวอย่างแบบสมบูรณ์ได้ที่ example/App.js

Initial Map

การสร้างแผนที่พื้นฐาน แบ่งเป็น 2 ส่วน

  1. ส่วนหลัก
import { SafeAreaView, StyleSheet, Text, View } from "react-native";
import Longdo from "longdo-map-react-native";

let map;

export default function App() {
    Longdo.apiKey = "[Your-Key-API]";
    return (
        <SafeAreaView style={styles.container}>
            <Longdo.MapView
                ref={(r) => (map = r)}
                layer={Longdo.static("Layers", "GRAY")}
                zoom={15}
                zoomRange={{ min: 4, max: 18 }}
                location={{ lon: 100.5382, lat: 13.7649 }}
                lastView={false}
                // language={'en'}
            />
        </SafeAreaView>
    );
}

2. ส่วนปรับแต่งการแสดงผล (Style)

const styles = StyleSheet.create({
    container: {
        flex: 1,
        backgroundColor: "#fff",
        alignItems: "stretch",
        justifyContent: "center",
    },
});

ภาพผลลัพธ์

ตัวอย่างการแสดงผลแผนที่

ใช้คำสั่งต่าง ๆ หลังจาก Map ถูกสร้างเสร็จสิ้น

1. สร้างฟังก์ชันเมื่อแผนที่พร้อม

function mapOnReady() { 
   let location = {lon: 100.5382, lat: 13.7649}
   let newMarker = Longdo.object('Marker', location, 
     { 
       title: 'Marker', 
       detail: 'Marker'
     }
   map.call('Overlays.add', newMarker);
}

2. ผูก Event การทำงานเมื่อแผนที่พร้อม (onReady)

<Longdo.MapView 
   ref={r => (map = r)}
   layer={Longdo.static('Layers', 'GRAY')}
   zoom={15}
   zoomRange={{min: 5, max: 18}}
   location={{lon: 100.5382, lat: 13.7649}}
   lastView={false}
   // language={'en'}
   onReady={mapOnReady} 
/>
  • onReady คือ ฟังก์ชันเมื่อแผนที่พร้อม ดูเพิ่มเติมหัวข้อ `Longdo.MapView` Component

หมายเหตุ: จะถูกแนะนำเพิ่มเติมในหัวข้อ Map Event และ Overlay Event ต่อไป

ภาพผลลัพธ์

หลังจากแผนที่ถูกสร้างเสร็จสิ้น จะส่งไปยัง event onReady

Marker

การสร้างหมุดพิกัด (marker) แบบพื้นฐาน

async function addMarker() {
   let location = await map.call('location');
   let newMarker = Longdo.object('Marker', location, { detail: 'Marker' });
   map.call('Overlays.add', newMarker);
}

แบบใส่รูปเอง

async function addMarker() {
   let location = await map.call('location');
   let newMarker = Longdo.object('Marker', location, { title: 'Marker', detail: 'Marker', icon: { url: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABHNCSVQICAgIfAhkiAAAAAl
wSFlzAAAA3QAAAN0BcFOiBwAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAAVISURBVFiF7ZdbjFVnF
cd/a+9vn33OnMOZM/cZhtJCKnUAMwEb52IzlUhATUtJlMZGiMYmhdC0tYZofDBR05TERNLEkPbFYJoYcZDoYONDi71MAwz
SArZDbbgOEGbOzJy5nss++/r5MB0Clukwtgk+9P+8Lr9vr/2ttT7RWnMnZdzR7J8D/D8AqPkMRr4u20KXX2NyNGxgaypgR
ah5GIOvGJrFGi6hOVBtcZBuHS4UQOa6Bdn1slK7/CUsswLATECsCkdMEnPE6tcGz9b8WR/+VAAD6yRuR+yPHDZpjRgKrCo
w47cZEA6J8HTmoL68YIDsOvlp6PJL7WOLASoNVmom6gKVM4RvZw7q3tsCGHpQugjZH7o0AagkWJUg5oIT36ixmKIl1a1HP
8nIeK/TOBk6vBW6NBkxKFfBRSWcmhYuFoQgWnjmY0E9B/zlNSWf5+azlav3owHyAq+HBvkAIuBSWRFqaLIj1tWGtGY05jy
lmAhNXnJXMl59L77v8d3pN92OymJDVbeemstHAXwgad6nktXGKOfE452S4sh0DJhpFGeKAV2TPl11EctTH781vhYOTWXon
qzGicokC5epb2zib95ddlvw4VZg75wAJeBluYdziXr+4Taym9PY8YALZUXWM4iAMyXFxbJJf9FnY53PujqN+qiFHSum2Dd
eS9a3rgctFvIMXCgQi8XIWurner18UHtYv3ErAGPMlJ6c2Pz4qZ10bfkefzDu4Zt2xPN1DhsyLovMmRM7kfD2dIy9V+P8f
WimFi/m6tk93HRT8lndbZX5Rc0FGmJBQznP69mvyZ9uCdDRF21OR05xJDdOw+Jm/mXVAXDIr2NThbCj1uH+lI/1Uf2HPJM
DIzYXCkJvYdHHAi4yQnbUjvDCkiusijsYMYhVQlDk0cEuOTfeLumbAAD6o+RP/trTQ27wGtnAJI/Fe1GSg36KKkOxLe2xp
dbhC4kAgHOO4siYwZpE6XogAb6RnuKluy7zrfTUTUNGpUBVQORwb1kYHNooX77uN9uIVq3teFHFrB3JsKz38G70O7fBTFB
gsRSpE7jPjDgdGgx4Bn35GEvtkC13m/xmrJmWuMP2mlGW2+6tvvKMNJSHIfJBLFxbsay2Vw/d1AlbW1uTYZi0+/uPjh/vl
F8NuPbPhgNUCR8TWGVq8houRcKob9BeFRK3k3w1U5g78Q2KfCgOQ66ykWXf38WpPbtWzTmMZnW8U3YXPNl1PhA1oaFa4Iu
m5kQg+MBiW/OArUmnwbDnhzg7JtQ/9BRLNv2AwcfXvjsvwKz6OmTPhCdPnw/F3GRFOBqOBAZnJUXa8Hkk5lCjwJoPRMNV1
YKaniSXz+rbBpjV0XbZm47YntGYA5LkSWMtipANXj+b7TzNgcaMz8wSFOR0NfXmOAChA94k6ADOWAbve7GJBW9EnX36ydX
/1OqaKa+epJKW+1awY/sTvF3RyuGSyTUleGU4NSiMrd7K8udeIfKgPAJubib5cdPiheklKEvt/59Xsra+aGNPWP9sRUWCk
YLLmrZ2Ro00bznCqBICINW8jNxr3TN/vwvTJvxRp9hXaOSxyuy+Hx3L71xwCW6UiKg1HQ+6z+x8wjhx8jQTvQf4kn8FQ4S
uRETG18QNuKIMXnEqOeFlWGqWou9khh9/uFf/Hj5hJbtdrVzbvk1Z1ssiQsKZ8B8xzmqJghhA3IR/BxlOhrW0mJN6fWq8r
9EOfrjhDf3h9UN8Fi+jlWvaNoN0ekH02/P9J671PGA8P+Xpx8qRVJdQXrMdHloahM+09enp//b9TAA+je74u+BzgDsO8B/
ytjz4VPeucgAAAABJRU5ErkJggg==', offset: { x: 16, y: 16 }} }); 

    map.call('Overlays.add', newMarker); 
}

see more: Marker option Documentation

ผลลัพธ์การใส่ภาพให้กับ Marker

การใส่รูปให้กับ Marker โดย base64 png

หมายเหตุ: API รับรูปภาพเฉพาะ format data URL (base 64 และ url รูปภาพ)

Geometries – รูปทรงต่าง ๆ

Polygon

function addPolygon() {
    let geomLocation = [
      { lon: 99, lat: 14 },
      { lon: 100, lat: 13 },
      { lon: 102, lat: 13 },
      { lon: 103, lat: 14 }
    ];

    let newGeom = Longdo.object('Polygon', geomLocation, { detail: 'Polygon' });
    map.call('Overlays.add', newGeom);
}

ดูเพิ่มเติม: JavaScript Map API, React Native docs – Object

Routing

การค้นหาเส้นทาง ด้วยการส่งพิกัดจุดต้นและปลายทาง

function routing() {
    let starterPoint = Longdo.object('Marker', {lon: 100.5, lat: 13.7}, { detail: 'Home' });
    let destinationPoint = Longdo.object('Marker', {lon: 100.5382, lat: 13.7649}, { detail: 'Destination' });
    map.call('Route.add', starterPoint);
    map.call('Route.add', destinationPoint);
    map.call('Route.search');
}

Change the color path

map.call('Route.line', 'road', { lineColor: '#009910', lineWidth: '1', borderColor: '#000000', borderWidth : '1' });
  • เรียกคำสั่งข้างต้น ก่อนไปคำสั่ง Route.search

ดูเพิ่มเติม: React Native call functionJavaScript routing option

Search

การทำช่องค้นหา โดยเรียกผ่าน Web Service ให้ผลลัพธ์ตามตัวอย่างภาพนี้

search screenshot
import {NavigationContainer} from '@react-navigation/native';
import {createNativeStackNavigator} from '@react-navigation/native-stack';

let map;
let keyAPI = 'YOUR-KEY-APII'; //Registered the Key from https://map.longdo.com/console

function HomeScreen({navigation}) {
   Longdo.apiKey = keyAPI;
   return (
    <SafeAreaView style={styles.container}>
      <TextInput
        style={styles.input}
        placeholder="ใส่คำค้นหา"
        onFocus={() => navigation.navigate('Search')}
      />
      <Longdo.MapView
        ref={r => (map = r)}
        layer={Longdo.static('Layers', 'GRAY')}
        zoom={15}
        zoomRange={{min: 5, max: 18}}
        location={{lon: 100.5382, lat: 13.7649}}
        onSearch={onSearch}
        lastView={false}
      />
     </SafeAreaView>
   );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#fff',
    justifyContent: 'center',
  },
  input: {
    height: 40,
    margin: 12,
    borderWidth: 1,
    padding: 10,
    backgroundColor: '#fff',
    zIndex: 10,
  },
  buttonBack: {
    marginVertical: 12,
    marginHorizontal: 10,
    height: 40,
  },
  inputSearch: {
    flex: 6,
    height: 40,
    marginRight: 12,
    marginTop: 12,
    borderWidth: 1,
    padding: 10,
    backgroundColor: '#fff',
    zIndex: 10,
  },
  textSuggest: {
    paddingHorizontal: 20,
    paddingVertical: 10,
    marginHorizontal: 12,
    backgroundColor: 'white',
  },
})

ฟังก์ชัน SeachScreen มีการเรียกใช้ทั้ง suggest web service และ search web service

function SearchScreen({navigation}) {
  // *****************************************************************

  const [search, setSearch] = useState('');
  const [filteredDataSource, setFilteredDataSource] = useState([]);

  const searchFilterFunction = text => {
    if (text.length >= 3) {
      const urlSuggest =
        'https://search.longdo.com/mapsearch/json/suggest?limit=10&key=' +
        keyAPI +
        '&keyword=' +
        text;
      fetch(urlSuggest)
        .then(response => response.json())
        .then(responseJson => {
          setFilteredDataSource(responseJson.data);
        })
        .catch(error => {
          console.error(error);
        });
      setSearch(text);
    } else {
      setFilteredDataSource([]);
      setSearch(text);
    }
  };

  const ItemSeparatorView = () => {
    return (
      // Flat List Item Separator
      <View
        style={{
          height: 1,
          backgroundColor: '#C8C8C8',
          marginHorizontal: 12,
        }}
      />
    );
  };

  const getItem = item => {
    const urlSearch =
      'https://search.longdo.com/mapsearch/json/search?limit=20&key=' +
      keyAPI +
      '&keyword=' +
      item;
    fetch(urlSearch)
      .then(response => response.json())
      .then(responseJson => {
        map.call('Overlays.clear');
        responseJson.data.forEach(item => {
          let newMarker = Longdo.object(
            'Marker',
            {lat: item.lat, lon: item.lon},
            {
              title: item.name,
              detail: item.address,
            },
          );
          map.call('Overlays.add', newMarker);
        });
        let location = {
          lon: responseJson.data[0].lon,
          lat: responseJson.data[0].lat,
        };
        map.call('location', location);
        navigation.navigate('Home', {
          responseJson: responseJson.data,
        });
      })
      .catch(error => {
        console.error(error);
      });
  };

  const Item = ({title}) => {
    return (
      <View>
        <Text style={styles.textSuggest} onPress={() => getItem(title)}>
          {title}
        </Text>
      </View>
    );
  };
  const DATA = [
    {
      data: filteredDataSource.map(item => item.w),
    },
  ];

  // ***************************************************************
  return (
    <View>
      <View style={{flexDirection: 'row'}}>
        <TouchableOpacity style={styles.buttonBack}>
          <Button title="Back" onPress={() => navigation.navigate('Home')} />
        </TouchableOpacity>
        <TextInput
          style={styles.inputSearch}
          onChangeText={text => searchFilterFunction(text)}
          autoFocus
          value={search}
          placeholder="ใส่คำค้นหา"
        />
      </View>

      <SectionList
        sections={DATA}
        keyExtractor={(item, index) => item + index}
        ItemSeparatorComponent={ItemSeparatorView}
        renderItem={({item}) => <Item title={item} />}
      />
    </View>
  );
}

ส่วน view แสดงผล (มีการเรียกฟังก์ชัน SearchScreen และ HomeScreen ตามข้างต้น)

const Stack = createNativeStackNavigator();

const App: () => Node = () => {
  return (
    <NavigationContainer>
      <Stack.Navigator
        initialRouteName="Home"
        screenOptions={{
          headerShown: false,
        }}>
        <Stack.Screen name="Home" component={HomeScreen} />
        <Stack.Screen name="Search" component={SearchScreen} />
      </Stack.Navigator>
    </NavigationContainer>
  );
};

Documentation


จบไปแล้วครับ ตัวอย่างการเขียน Longdo Map ผ่าน React Native มีวิธีติดตาม Longdo Map ได้ง่ายๆ หลายช่องทาง ดังนี้

  • ศึกษาการใช้ Longdo Map เพิ่มเติมได้ที่ https://map.longdo.com/docs/
  • ดูเคล็ดลับและเทคนิคอื่นๆ เพิ่มเติมได้ที่ https://map.longdo.com/blog
  • เรียนเชิญนักพัฒนาเว็บทุกท่านเข้าร่วมกลุ่ม Longdo Map API Community กันได้ที่นี่เลยครับ 🙂 https://www.facebook.com/groups/708165893234850

พบกันในบทความถัดไปครับ