乐趣区

关于react.js:维格vika小程序分享地图信息展示

分享一个能够在地图上展现表格信息的维格地图小程序。

已实现性能帮忙租房者在租房的时候在地图上进行租房信息比照选出本人心仪的小根据地。

我的项目地址

https://github.com/laboonly/w…

性能介绍

本小程序依据表格外面的出租房信息在地图上显示各个出租房的地位,到公司的路线布局,以及详细信息。帮忙租房的同学更加平面的比照各个出租房的优缺点,找出本人心仪的房子。

应用阐明

请先获取高德 api 的 key 高德地图 apikey 获取,填入 src/map.tsx 的 securityCode 和 apiKey,启动小程序之后抉择,名称,地址,价格,联系方式对应表格的列,以及填入地图核心(公司)。

上面分享一下开发过程

开发过程

正好在寻找房子的我,想到如果能用维格表小程序管理租房信息可能实现我找到最优房子的需要的地图小组件就好了, 顺便介绍一下维格小程序以及高德地图相干方面的开发。

打算需要

需要整顿,我冀望的是小程序可能在地图上依据表格中的地址展现不同的标点,同时点击标点之后展现标点的详细信息,以及各个出租房到公司的间隔。

筹备工作

首先依据官网文档疾速上手开发 | 维格表开发者核心,创立装置好小程序。
第二个是高德地图开发须要在高德开发者核心,注册号账号并且申请 key, 筹备 - 入门 - 教程 - 地图 JS API | 高德地图 API。

第一步加载地图

高德 JSAPI,更新了 V2.0 版本,一番尝试之后发现总是没方法加载胜利,在征询了维格的研发同学之后,才晓得可能是因为维格对 iframe 反对有问题,于是决定不实用新版本的 api 应用之前 V.14 版本的 api。

然而 v.14 版本的 api 加载不反对 npm,于是我借鉴了之前应用此版本 api 的 react-amap 开源框架,对于地图加载的局部。源码链接,大略思路就是用 JS 创立 script 标签加载。首先在小程序的框架下创立 utils/ApiLoader.js 文件。复制下面链接中的代码。这里的地图 mapStyle 我应用了高德的自定义主题,你能够抉择你喜爱的地图主题,或者本人配置.

// 局部代码

  const DEFAULT_CONFIG = {
    v:‘1.4.0’, // 版本号
    hostAndPath:‘webapi.amap.com/maps’, // 高德 api 加载地址
    key:‘’, // 高德 apikey
    callback:‘_amap_init_callback’, // 回调函数
    useAmapUI: true // 是否应用高德 UI
  }

// 获取脚本链接
  getScriptSrc(cfg) {return `${this.protocol}//${cfg.hostAndPath}
  ?v=${cfg.v}&key=${cfg.key}&callback=${cfg.callback}`;
  }

// 创立脚本 js
  buildScriptTag(src) {const script = document.createElement(‘script’);
    script.type =‘text/javascript’;
    script.async = true; // 异步执行
    script.defer = true; // 页面加载完之后执行
    script.src = src;
    return script;
  }

接下来咱们在小程序工程 src 中创立 map.tsx 文件,引入 APILoader,并且创立 MapComponent 函数组件。填入地图配置参数,这里要留神地图挂载的 DOM 要设置宽高.

import React, {useEffect, useState} from‘react’;
import {Setting} from‘./setting’;
import APILoader from‘./utils/APILoader’;


// 地图平安密钥
const securityCode =‘高德开发者核心申请 key 附带的平安密钥’;
// 高德地图 api key
const apiKey =‘高德开发者核心申请的 key’;

// 设置地图平安密钥
window[‘_AMapSecurityConfig’] = {securityJsCode: securityCode,}

export const MapComponent: React.FC = () => {
    // 组件初始化时,加载 sdk 地图实例
  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,// 级别
        center: lnglat,// 中心点坐标
        viewMode:‘3D’,// 应用 3D 视图
        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>
  );
};

批改小程序 index.tsx 的默认代码.

import {initializeWidget} from '@vikadata/widget-sdk';
import {MapComponent} from './map';

initializeWidget(MapComponent, process.env.WIDGET_PACKAGE_ID!);

接下来咱们关上维格小程序开发的网页就能够看到地图曾经加载好了。

地图加载好了之后,接下来咱们须要依据表格中的地址创立好地图标点。
首先在维格表中创立好名称,地址,优缺点,价格,联系方式等列,填入本人的数据。

这里咱们须要应用到两个插件,地图编码插件 geocoder, 高德官网 UI 库,在 utils 上面新建 commons.js。实现加载插件代码。同样思路的还有后续的路线布局插件加载。


// 加载高德地图地图插件
function loadAmapUI() {
  return new Promise<object>(resolve => {window.AMapUI.loadUI(['overlay/SimpleMarker'], (SimpleMarker: any) => {resolve(SimpleMarker);
    })
  })
}

/ 加载高德地图地图编码插件
function loadGeocoder() {
  return new Promise<object>(resolve => {window.AMap.plugin('AMap.Geocoder', () => {
      const geocoder = new window.AMap.Geocoder({
        // city 指定进行编码查问的城市,反对传入城市名、adcode 和 citycode
        city: '全国'
      });
      resolve(geocoder);
    });
  });
}

因为这些插件以及高德地图 api 的加载是异步的所以咱们将这些性能与地图上的性能离开, 将之前的地图挂载元素分成 mapcontent 的小组件,在 src 中创立 components/mapcontent, 并且依据维格小程序官网 api 批改 src/seting.tsx. 而后应用 useCloudStorage 来获取用户设置名称地址等,对应的列的 id。而后应用 record.getCellValue 来获取对应的值。接下来依据这个值通过下面提失去 geocoder 插件依据地址查问对应点的坐标值,最初应用高德 AMapUI 创立对应地址的标点。

mapcontent/index.tsx

// 以下是局部代码残缺源码请在 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}) => {
  // 获取表格视图 ID
  const [viewId] = useCloudStorage<string>('selectedViewId');
  // 获取所有行的信息
  const records = useRecords(viewId);
  // 解决完的表格信息
  const [recordsData, setRecordsdata] = useState<any>();
  // 名称
  const [titleId] = useCloudStorage<string>('selectedtitleId');
  // 地址
  const [addressId] = useCloudStorage<string>('selectedAddressId');
  // 优缺点
  const [houseInfoId] = useCloudStorage<string>('selectedHouseInfoId');
  // 价格
  const [priceId] = useCloudStorage<string>('selectPrice');
  // 联系方式
  const [contactId] = useCloudStorage<string>('selectContact');
  // 地图核心地址
  const [mapCenter] = useCloudStorage<string>('mapCenter');

  // 地址解决
  useEffect(function getAddressList() {
    // 获取表格所有地址
    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]);

  // 依据表格设置所有地图点
  useEffect(function drawAddress() {console.log('pluginStatus', pluginStatus);
    if (!pluginStatus || !recordsData  || !mapCenterLocation) {return;}
    markAddress(recordsData, markersLayer, mapCenterLocation, informationRef);
  }, [recordsData, mapCenterLocation, pluginStatus]);

  /* 创立标记点 
  record: 标点信息
  markerConfig: 标点参数配置
  transfer: 创立门路对象
  informationRef: 信息窗体 DOM 援用
  */
  function creatMarker(
    record: any, 
    markerConfig: markConfig,
    mapCenterLocation?: locationType,
    informationRef?: any,
  ) {

    const marker =  new window.SimpleMarker({
      ...markerConfig,
      //... 其余 Marker 选项...,不包含 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,  // 传入 dom 对象,或者 html 字符串
            offset: new window.AMap.Pixel(0, -40),
            closeWhenClickMap: true, // 点击地图敞开
            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;
  }

  /* 依据地址搜寻减少 marker 点 
  recordsData: 表格数据
  markersLayer: 之前曾经创立的 marker 图层
  setHouseinfo: 设置标点信息函数
  mapCenterLocation: 中心点坐标
  informationRef: 信息窗口 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>
  );

});

另外咱们须要在 setting.tsx 外面设置名称,地址等信念对应的列。通过 useCloudStorage 保留。应用小程序官网的 FieldPicker 组件抉择对应的字段获取 ID。

// 以下是局部代码残缺源码请在 github 查看

export const Setting: React.FC = () => {const [isSettingOpened] = useSettingsButton();

  // 名称
  const [titleId, settitleId] = useCloudStorage<string>('selectedtitleId');
  // 地址
  const [addressId, setAddressId] = useCloudStorage<string>('selectedAddressId');
  // 优缺点
  const [houseInfoId, setHouseInfoId] = useCloudStorage<string>('selectedHouseInfoId');
  // 价格
  const [priceId, setPriceId] = useCloudStorage<string>('selectPrice');
  // 联系方式
  const [contactId, setContactId] = useCloudStorage<string>('selectContact');

  return isSettingOpened ? (<div style={{ flexShrink: 0, width: '300px', borderLeft: 'solid 1px gainsboro'}}>
      <h1 style={{paddingLeft: "5px", marginBottom: 0}}> 设置 </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="名称">
            <FieldPicker viewId={viewId} fieldId={titleId} onChange={option => settitleId(option.value)} />
          </FormItem>
          <FormItem label="地址">
            <FieldPicker viewId={viewId} fieldId={addressId} onChange={option => setAddressId(option.value)} />
          </FormItem>
          <FormItem label="优缺点">
            <FieldPicker viewId={viewId} fieldId={houseInfoId} onChange={option => setHouseInfoId(option.value)} />
          </FormItem>
          <FormItem label="价格">
            <FieldPicker viewId={viewId} fieldId={priceId} onChange={option => setPriceId(option.value)} />
          </FormItem>
          <FormItem label="联系方式">
            <FieldPicker viewId={viewId} fieldId={contactId} onChange={option => setContactId(option.value)} />
          </FormItem>
          <FormItem label="地图核心">
            <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}>
              确定
            </Button>
          </FormItem>
        </Box>
        </div>
      </div>
    </div>
  ) : null;

});

到这里咱们基本上实现了从表格中获取值而后在地图上实现标点等性能,后续的详细信息展现以及路线布局也能够应用
相应的插件实现。我曾经将源码上传至 https://github.com/laboonly/w… 欢送 Star⭐️.

后续打算

  1. 将此小程序变得更加有拓展性。让用户能够自由选择标点详细信息展现等性能
  2. 增加更多地图功能
退出移动版