[Vig vika applet sharing] map information display

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


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.


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.


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}

// 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%' }}>
        <Setting />

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) => {

/ 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'

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.


// 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)
  },[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) {
    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({
      //... Other Marker options, Excluding content
      map: window.amap,
      clickable: true,
      position: [record.location.lng, record.location.lat]
    if(mapCenterLocation) {
      marker.on('click', () => {
        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) {

    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);


  return (
    <div style={{ width: '100%', height: '100%' }}>
      <div id="container" style={{ width: '100%', height: '100%' }}>


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'}}>
          padding="30px 10px 60px 10px"
          borderBottom="2px solid lightgrey"
          <FormItem label="View" >
            <ViewPicker   viewId={viewId} onChange={option => setViewId(option.value)} />
          <FormItem label="name">
            <FieldPicker viewId={viewId} fieldId={titleId} onChange={option => settitleId(option.value)} />
          <FormItem label="address">
            <FieldPicker viewId={viewId} fieldId={addressId} onChange={option => setAddressId(option.value)} />
          <FormItem label="Advantages and disadvantages">
            <FieldPicker viewId={viewId} fieldId={houseInfoId} onChange={option => setHouseInfoId(option.value)} />
          <FormItem label="Price">
            <FieldPicker viewId={viewId} fieldId={priceId} onChange={option => setPriceId(option.value)} />
          <FormItem label="contact information">
            <FieldPicker viewId={viewId} fieldId={contactId} onChange={option => setContactId(option.value)} />
          <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}>
  ) : 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

  1. Make this applet more extensible. Users can freely choose functions such as punctuation detail display
  2. Add more map features

Keywords: Javascript React

Added by chris.zeman on Sat, 05 Mar 2022 03:45:33 +0200