Share a Vig map applet that can display table information on the map.
The function has been realized to help renters compare the rental information on the map and select their favorite small base.
Project address
https://github.com/laboonly/w...
Function introduction
This applet displays the location of each rental house, the route planning to the company and detailed information on the map according to the rental house information in the form. Help students rent more three-dimensional comparison of the advantages and disadvantages of each rental house, and find out their favorite house.
instructions
Please get the key of Gaode api first Gaode map apikey acquisition , fill in Src / map For the securityCode and apiKey of TSX, after starting the applet, select the column of the corresponding table of name, address, price and contact information, and fill in the map Center (company).
Let's share the development process
development process
Just looking for a house, I thought it would be nice if I could use the Vig table applet to manage the rental information and realize the map widget that I need to find the best house. By the way, I would like to introduce the development of Vig applet and Gaode map.
Planning requirements
I hope that the applet can display different punctuation points on the map according to the address in the table. At the same time, click the punctuation to display the details of the punctuation and the distance from each rental house to the company.
preparation
First, according to the official documents Quick start development | wig watch Developer Center , create and install the applet.
The second is that the development of Gaode map needs to register the account number and apply for key in Gaode Developer Center, Preparation - Introduction - Tutorial - map JS API | Gaode map API.
Step 1: load the map
Gaode JSAPI, updated v2 0 version. After some attempts, it was found that it could not be loaded successfully. After consulting Vig's R & D classmates, it was known that Vig may have problems with iframe support, so it decided not to apply to the new version of api and use the api of the previous V.14 version.
However, the api loading of v.14 version does not support npm, so I learned from the react amap open source framework that used this version of api before, and the part about map loading. Source code link , the general idea is to create script tag loading with JS. First, create utils / apiloader under the framework of the applet JS file. Copy the code in the link above. I used mapStyle here Custom theme of Gaode , you can choose your favorite map theme or configure it yourself
// Partial code const DEFAULT_CONFIG = { v: '1.4.0', // Version number hostAndPath: 'webapi.amap.com/maps', // Gaode api loading address key: '', // Gaode apikey callback: '_amap_init_callback', // Callback function useAmapUI: true // Whether to use Gaode UI } // Get script link getScriptSrc(cfg) { return `${this.protocol}//${cfg.hostAndPath} ?v=${cfg.v}&key=${cfg.key}&callback=${cfg.callback}`; } // Create script js buildScriptTag(src) { const script = document.createElement('script'); script.type = 'text/javascript'; script.async = true; // Asynchronous execution script.defer = true; // Execute after the page is loaded script.src = src; return script; }
Next, we create a map in the applet project src Tsx file, introduce APILoader, and create MapComponent function component. Fill in the map configuration parameters. Note that the width and height of the DOM attached to the map should be set
import React, { useEffect, useState } from 'react'; import { Setting } from './setting'; import APILoader from './utils/APILoader'; // Map security key const securityCode = 'Application of Gaode Developer Center key Attached security key'; // Gaode map api key const apiKey = 'Applied by Gaode Developer Center key'; //Set map security key window['_AMapSecurityConfig'] = { securityJsCode: securityCode, } export const MapComponent: React.FC = () => { // When the component is initialized, the sdk map instance is loaded useEffect(() => { new APILoader({ key: apiKey, version: null, protocol: 'https' }).load().then(() => { const lnglat = new window.AMap.LngLat(114.031040, 22.624386); const amap = new window.AMap.Map('container', { zoom: 12,//level center: lnglat,//Center point coordinates viewMode: '3D',//Use 3D view mapStyle: 'amap://styles/b379277160c9c3ce520627ad2e4bd22c' }); window.amap = amap; }, []); return ( <div style={{ display: 'flex', height: '100%' }}> <div style={{ flexGrow: 1, overflow: 'auto', padding: '0 8px'}}> <div id="container" style={{ width: '100%', height: '100%' }}> </div> <Setting /> </div> ); };
Modify applet index The default code for TSX
import { initializeWidget } from '@vikadata/widget-sdk'; import { MapComponent } from './map'; initializeWidget(MapComponent, process.env.WIDGET_PACKAGE_ID!);
Next, we open the web page of Vig applet development to see that the map has been loaded.
After the map is loaded, we need to create map punctuation according to the address in the table.
First, create the name, address, advantages and disadvantages, price, contact information and other columns in the wig table and fill in your own data.
Here we need to use two plug-ins, the map coding plug-in geocoder,Gaode official UI Library , under utils, create new Commons js. Implement loading plug-in code. The same idea is to load the subsequent route planning plug-in.
// Load Gaode map plug-in function loadAmapUI() { return new Promise<object>(resolve => { window.AMapUI.loadUI(['overlay/SimpleMarker'], (SimpleMarker: any) => { resolve(SimpleMarker); }) }) } / Load Gaode map coding plug-in function loadGeocoder() { return new Promise<object>(resolve => { window.AMap.plugin('AMap.Geocoder', () => { const geocoder = new window.AMap.Geocoder({ // City specifies the city for code query, and supports the input of city name, adcode and citycode city: 'whole country' }); resolve(geocoder); }); }); }
Because the loading of these plug-ins and Gaode map api is asynchronous, we separate these functions from the functions on the map, divide the previous map mount elements into small components of mapcontent, create components/mapcontent in src, and modify src / setting according to the official api of Vig applet tsx. Then useCloudStorage is used to obtain the user set name, address, etc., and the id of the corresponding column. Then use record Getcellvalue to get the corresponding value. Next, according to this value, the geocoder plug-in can query the coordinate value of the corresponding point according to the address, and finally use Gaode AMapUI Create punctuation for the corresponding address.
mapcontent/index.tsx
// The following is the complete source code of part of the code. Please check it in github import React, { useState, useEffect } from 'react'; import { useCloudStorage, useRecords } from '@vikadata/widget-sdk'; import { getLocationAsync, creatTransfer } from '../../utils/common'; export const MapContent: React.FC<mapContentProps> = ({ pluginStatus }) => { // Get table view ID const [viewId] = useCloudStorage<string>('selectedViewId'); // Get information for all rows const records = useRecords(viewId); // Processed table information const [recordsData, setRecordsdata] = useState<any>(); // name const [titleId] = useCloudStorage<string>('selectedtitleId'); // address const [addressId] = useCloudStorage<string>('selectedAddressId'); // Advantages and disadvantages const [houseInfoId] = useCloudStorage<string>('selectedHouseInfoId'); // Price const [priceId] = useCloudStorage<string>('selectPrice'); // contact information const [contactId] = useCloudStorage<string>('selectContact'); // Map center address const [mapCenter] = useCloudStorage<string>('mapCenter'); // Address processing useEffect(function getAddressList() { // Get all addresses of the form const recordsData: any[] = records .map(record => { return { title: record.getCellValue(titleId), address: record.getCellValue(addressId), info: record.getCellValue(houseInfoId), price: record.getCellValue(priceId), contact: record.getCellValue(contactId) } }); setRecordsdata(recordsData); },[records, titleId, addressId, houseInfoId, priceId, contactId]); // Set all map points according to the table useEffect(function drawAddress() { console.log('pluginStatus', pluginStatus); if (!pluginStatus || !recordsData || !mapCenterLocation) { return; } markAddress(recordsData, markersLayer, mapCenterLocation, informationRef); }, [recordsData, mapCenterLocation, pluginStatus]); /* Create marker points record: Punctuation information markerConfig: Punctuation parameter configuration transfer: Create path object informationRef: Information form DOM reference */ function creatMarker( record: any, markerConfig: markConfig, mapCenterLocation?: locationType, informationRef?: any, ) { const marker = new window.SimpleMarker({ ...markerConfig, //... Other Marker options, Excluding content map: window.amap, clickable: true, position: [record.location.lng, record.location.lat] }); if(mapCenterLocation) { marker.on('click', () => { setHouseinfo(record); const infoWindow = new window.AMap.InfoWindow({ content: informationRef.current.innerHTML, //Pass in a dom object or an html string offset: new window.AMap.Pixel(0, -40), closeWhenClickMap: true, // Click map to close autoMove: true }); creatTransfer([mapCenterLocation.lng, mapCenterLocation.lat], [record.location.lng, record.location.lat]); infoWindow.open(window.amap, [record.location.lng, record.location.lat]); }); } return marker; } /* Add marker points according to address search recordsData: Tabular data markersLayer: Previously created marker layer setHouseinfo: Set punctuation information function mapCenterLocation: Center point coordinates informationRef: Information window DOM */ async function markAddress( recordsData: Array<any>, markersLayer: Array<any>, mapCenterLocation: locationType, informationRef: any, ) { if(markersLayer) { window.amap.remove(markersLayer); } const asyncRecords = recordsData.map(record => getLocationAsync(record)); const Records = await Promise.all(asyncRecords); const markers = Records.map((record: any) => { return creatMarker(record, homeMarkerConfig, mapCenterLocation, informationRef); }); setMakerslayer(markers); } return ( <div style={{ width: '100%', height: '100%' }}> <div id="container" style={{ width: '100%', height: '100%' }}> </div> </div> ); });
In addition, we need to be in setting Set the corresponding columns of name, address, etc. in TSX. Save through useCloudStorage. Use the official FieldPicker component of the applet to select the corresponding field to obtain the ID.
// The following is the complete source code of part of the code. Please check it in github export const Setting: React.FC = () => { const [isSettingOpened] = useSettingsButton(); // name const [titleId, settitleId] = useCloudStorage<string>('selectedtitleId'); // address const [addressId, setAddressId] = useCloudStorage<string>('selectedAddressId'); // Advantages and disadvantages const [houseInfoId, setHouseInfoId] = useCloudStorage<string>('selectedHouseInfoId'); // Price const [priceId, setPriceId] = useCloudStorage<string>('selectPrice'); // contact information const [contactId, setContactId] = useCloudStorage<string>('selectContact'); return isSettingOpened ? ( <div style={{ flexShrink: 0, width: '300px', borderLeft: 'solid 1px gainsboro'}}> <h1 style={{ paddingLeft: "5px", marginBottom: 0 }}>set up</h1> <div style={{ display: 'flex', height: '100%' }}> <div style={{ flexGrow: 1, overflow: 'auto'}}> <Box padding="30px 10px 60px 10px" borderBottom="2px solid lightgrey" > <FormItem label="View" > <ViewPicker viewId={viewId} onChange={option => setViewId(option.value)} /> </FormItem> <FormItem label="name"> <FieldPicker viewId={viewId} fieldId={titleId} onChange={option => settitleId(option.value)} /> </FormItem> <FormItem label="address"> <FieldPicker viewId={viewId} fieldId={addressId} onChange={option => setAddressId(option.value)} /> </FormItem> <FormItem label="Advantages and disadvantages"> <FieldPicker viewId={viewId} fieldId={houseInfoId} onChange={option => setHouseInfoId(option.value)} /> </FormItem> <FormItem label="Price"> <FieldPicker viewId={viewId} fieldId={priceId} onChange={option => setPriceId(option.value)} /> </FormItem> <FormItem label="contact information"> <FieldPicker viewId={viewId} fieldId={contactId} onChange={option => setContactId(option.value)} /> </FormItem> <FormItem label="Map Center"> <TextInput style={{ width: '100%!important' }} size="small" value={inputCenter} onChange={ e => setInputcenter(e.target.value)} /> <Button style={{ marginTop: 8}} color="primary" size="small" onClick={confirmCenter}> determine </Button> </FormItem> </Box> </div> </div> </div> ) : null; });
Here, we have basically completed the functions of obtaining values from the table and then realizing punctuation on the map. Subsequent detailed information display and route planning can also be used
The corresponding plug-in is completed. I have uploaded the source code to https://github.com/laboonly/w... Welcome, Star ⭐ ️.
Follow up plan
- Make this applet more extensible. Users can freely choose functions such as punctuation detail display
- Add more map features