Vue uses Gaode map, the marker is less than 1000, and the exploration of the sliding jam problem (solved)

Problem Description

Vue uses Gaode map point markers. At the beginning, Marker was used, but when the number exceeds 300, sliding will freeze. According to the document, the Marker type is recommended to be used when the amount of data is less than 500, and it should not be stuck. Later, I started to explore this bug for two days.

1. Change to LabelMarker

Since the Marker type is not good, after reading the document, LabelMarker supports more point markers, then replace it with LabelMarker, and then release it with confidence, but the result is still not working.

2. Communicate with the official to seek a solution

I wrote the code according to the document, but it didn’t work. I could only communicate with the official work order. I posted the initialization code used in the project to the official. After reading it, the official said it was no problem. I gave a js demo and ran it. , really not stuck. Post the demo code

Labelmarker_Test.html

<!doctype html>
<html>

<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width">
    <link rel="stylesheet" href="https://a.amap.com/jsapi_demos/static/demo-center/css/demo-center.css" />
    <title>地图显示</title>
    <style>
        html,
        body,
        #container {
      
      
            width: 100%;
            height: 100%;
        }
    </style>
</head>

<body>
    <div id="container"></div>
    <!-- 加载地图JSAPI脚本 -->
    <script src="https://webapi.amap.com/maps?v=2.0&key=自己的key"></script>
    <script src="/data.js"></script>

    <script>
        var map = new AMap.Map('container', {
      
      
            viewMode: '2D', // 默认使用 2D 模式,如果希望使用带有俯仰角的 3D 模式,请设置 viewMode: '3D',
            zoom: 11, //初始化地图层级
            center: [116.397428, 39.90923] //初始化地图中心点
        });
        let markers = [];
        for (var i = 0; i < data.length; i++) {
      
      
            var marker;
            let item = data[i];
            // console.log("地图marker", item);
            let imageUrl = 'https://a.amap.com/jsapi_demos/static/demo-center/marker/express2.png';
            var icon = {
      
      
                // 图标类型,现阶段只支持 image 类型
                type: "image",
                // 图片 url
                image: imageUrl,
                // 图片尺寸
                size: [44, 50],
                // 图片相对 position 的锚点,默认为 bottom-center
                anchor: "center",
            };

            var text = {
      
      
                // 要展示的文字内容
                content: item.orgName,
                // 文字方向,有 icon 时为围绕文字的方向,没有 icon 时,则为相对 position 的位置
                direction: "top",
                // 在 direction 基础上的偏移量
                offset: [0, 0],
                // 文字样式
                style: {
      
      
                    // 字体大小
                    fontSize: 12,
                    // 字体颜色
                    fillColor: "#000000",
                    //backgroundColor: "#ffffff",
                },
            };

            if (item.latitude && item.longitude) {
      
      
                let positionV = [item.longitude, item.latitude];
                marker = new AMap.LabelMarker({
      
      
                    name: "标注2", // 此属性非绘制文字内容,仅最为标识使用
                    position: positionV,
                    zIndex: i,
                    opacity: 1,
                    // 将第一步创建的 icon 对象传给 icon 属性
                    icon: icon,
                    // 将第二步创建的 text 对象传给 text 属性
                    text: text,
                    zooms: [3, 20],
                    allowCollision: false,
                });
            }
         
            var onMarkerClick = function (e) {
      
      
                console.log("marker 点击");
                that.hospital = item;
                that.sheetShow = true;
            };
            marker.on("click", onMarkerClick); //绑定click事件

            markers.push(marker);
        }

        var labelsLayer = new AMap.LabelsLayer({
      
      
            zooms: [3, 20],
            zIndex: 1000,
            // 该层内标注是否避让
            collision: true,
            // 设置 allowCollision:true,可以让标注避让用户的标注
            allowCollision: true,
        });
        labelsLayer.add(markers);
        map.add(labelsLayer);
    </script>
</body>

</html>

data.js

const data = [
    {
    
     unifiedOrgCode: "320211PD3854", orgName: "门诊部", branchCode: null, branchName: null, orgLevel: null, orgGrade: null, provinceCode: null, cityCode: null, orgAddress: "太湖新城金融街11号", latitude: 31.488750, longitude: 120.304928, introduction: null, orgUrl: "https://www.wxhealth.net:8241/File/GetFile/76c0c8d6be03c2e1", reserveNote: null, orgTraffic: null, feature: null, ticketDetial: null, isReservation: 1, appointDays: 7, canAppointToday: 1, doctorAppointDays: null, showOrder: null, accessType: null, h5Info: null, distance: "0.10", contactPhone: null, characteristics: null, orgType: "clinic", districtCode: "3201", economicType: 2 }, {
    
     unifiedOrgCode: "320211PD78", orgName: "同仁大药房", branchCode: null, branchName: null, orgLevel: null, orgGrade: null, provinceCode: null, cityCode: null, orgAddress: "区观山路38号", latitude: 31.491185, longitude: 120.302667, introduction: null, orgUrl: "https://www.wxhealth.net:8241/be03c2e1", reserveNote: null, orgTraffic: null, feature: null, ticketDetial: null, isReservation: 1, appointDays: 7, canAppointToday: 1, doctorAppointDays: null, showOrder: null, accessType: null, h5Info: null, distance: "0.40", contactPhone: null, characteristics: null, orgType: "clinic", districtCode: "320211", economicType: 2 },
]

There is a lot of data, I only post the data structure here. If you want to simulate data, you can use loop traversal and then dynamically modify the latitude and longitude, such as

 demoData.forEach((element) => {
    
    
         //TODO 增加多条数据,测试是否卡顿
            let latTest = element.latitude;
            let lonTest = element.longitude;
            for (let i = 0; i < 50; i++) {
    
    
              element.latitude = latTest + 0.00001 * i;
              element.longitude = lonTest + 0.00001 * i;
              mapData.push(element);
            }
          });

Is it only Vue that freezes?

I tried the js demo given by the official, and it does not get stuck when there is a lot of data, so I wonder if it is a problem with vue. I try not to initialize Vue, and use js in vue to initialize the index under public
. add <head>in html

  <script src="https://webapi.amap.com/maps?v=2.0&key=自己的key"></script> 

Then use it in the corresponding Vue

 var map = new AMap.Map('container', {
            viewMode: '2D', // 默认使用 2D 模式,如果希望使用带有俯仰角的 3D 模式,请设置 viewMode: '3D',
            zoom: 11, //初始化地图层级
            center: [116.397428, 39.90923] //初始化地图中心点
        });

But it still doesn't work, it still freezes

A palliative, not a permanent solution

Since it is technically difficult to implement, what about modifying the requirements? For example, for a large amount of data, I divide it into N groups, such as four groups, and then monitor the map zoom event. In a certain range, only the first group is displayed, and in another range, Display the second group. The data displayed in each group is relatively small, so there will be no lag.

accidentally found bug

It can only be solved technically. According to the official code, delete the code in the project bit by bit to see which piece of code caused the freeze. After various attempts, I finally locked a variable. This variable is in the data The localMap, I set this.localMap=map after the map is initialized. There is no problem with this logic, so I didn't care about it at first, but it was indeed caused by this code, so I reported it to the official, and the official reply
insert image description here
:
insert image description here

All map-related instances should not be placed in the responsive data of vue. The response data will hijack attributes, and map attributes will be modified. In addition, the hijacked attributes may be related to rendering, which will increase a lot of response calculations, which will be very stuck;

Got it, it’s just that you can’t assign any field in the data in the instance related to the map, otherwise it will be very stuck

How to get a map instance

My current requirement is to add an icon on the top of my map control to set the center position and use the setCenter method. This needs to use the current map object, so I want to use the fields in the data to associate with the map, but This will cause lag. Is there any way to get the object of the map and operate it in the outer layer? ? ? ?

Since it is not possible to assign a value to the outer field in the map instance code, the first method that comes to mind is to return the map object and then use the field to receive it, but it still does not work. Another way is to pass in the map object to assign a value through the method , or not, so continue to communicate with the official, the reply is

After the map is loaded, mount the AMap on the window, and then get it directly from the window.

Then how can I get it? I tried several methods, but I couldn’t find how to get the setCenter method of AMap. Finally, I searched on Baidu, and I can get an instance like this, associate map with window, window.map=new AMap.Map(“container ", {...}); Then operate on the map through window.map in the outer layer

  window.map.setCenter([120.318321, 31.497963]);
 initAMap() {
    
    
      
    
      AMapLoader.load({
    
    
        key: "自己的key", //设置您的key
        version: "2.0",
        plugins: ["AMap.ToolBar", "AMap.Driving"],
        AMapUI: {
    
    
          version: "1.1",
          plugins: [],
        },
        Loca: {
    
    
          version: "2.0",
        },
      })
        .then((AMap) => {
    
    
           window.map = new AMap.Map("container", {
    
    
            viewMode: "3D",
            zoom: 10,
            zooms: [2, 22],
            center: [120.318791, 31.497993],
          });
          let markers = [];
          let demoData = dataInJs();
          let mapData = [];

          demoData.forEach((element) => {
    
    
            // //TODO 增加多条数据,测试是否卡顿,正式发布删除
            let latTest = element.latitude;
            let lonTest = element.longitude;
            for (let i = 0; i < 10; i++) {
    
    
              element.latitude = latTest + 0.00001 * i;
              element.longitude = lonTest + 0.00001 * i;
              mapData.push(element);
            }
          });

          console.log("mapData", mapData);
          for (var i = 0; i < mapData.length; i++) {
    
    
            var marker;
            let item = mapData[i];
            let imageUrl =
              "https://a.amap.com/jsapi_demos/static/demo-center/marker/express2.png";

            var icon = {
    
    
              // 图标类型,现阶段只支持 image 类型
              type: "image",
              // 图片 url
              image: imageUrl,
              // 图片尺寸
              size: [44, 50],
              // 图片相对 position 的锚点,默认为 bottom-center
              anchor: "center",
            };

            var text = {
    
    
              // 要展示的文字内容
              content: item.orgName,
              // 文字方向,有 icon 时为围绕文字的方向,没有 icon 时,则为相对 position 的位置
              direction: "top",
              // 在 direction 基础上的偏移量
              offset: [0, 0],
              // 文字样式
              style: {
    
    
                // 字体大小
                fontSize: 12,
                // 字体颜色
                fillColor: "#000000",
              },
            };

            if (item.latitude && item.longitude) {
    
    
              let positionV = [item.longitude, item.latitude];
              marker = new AMap.LabelMarker({
    
    
                name: "标注2", // 此属性非绘制文字内容,仅最为标识使用
                position: positionV,
                zIndex: i,
                opacity: 1,
                // 将第一步创建的 icon 对象传给 icon 属性
                icon: icon,
                // 将第二步创建的 text 对象传给 text 属性
                text: text,
                zooms: [3, 20],
                allowCollision: false,
              });
            }

            var onMarkerClick = function (ee) {
    
    
              console.log("marker 点击" + ee);
            };
            marker.on("click", onMarkerClick); //绑定click事件

            markers.push(marker);
          }

          var labelsLayer = new AMap.LabelsLayer({
    
    
            zooms: [3, 20],
            zIndex: 1000,
            // 该层内标注是否避让
            collision: true,
            // 设置 allowCollision:true,可以让标注避让用户的标注
            allowCollision: true,
          });
          labelsLayer.add(markers);
            window.map.add(labelsLayer);
          //  this.setLocalMap(map);
          setTimeout(() => {
    
    
            console.log("定位");
             this.testMap();
          }, 1000);
         
        })
        .catch((e) => {
    
    
          console.log(e);
        });

      //return map;
    },

Summarize

Just use the official document for the annotation. If it is still stuck, check whether there is an operation on the fields in the data when the map is instantiated, such as this.localMap=map and the like. If you want to get a map instance for the outer layer to operate on the map, you can give window.map, and then get it, and associate the map instance with the window, so that it will not freeze

Guess you like

Origin blog.csdn.net/jifashihan/article/details/128231939