首页 / 浏览问题 / WebGIS / 问题详情
更新地图上图标位置速度过快,浏览器后台警告且更新频率下降
9EXP 2023年03月01日

使用产品:SuperMap REST 地图服务底图

操作系统:win10 x64 edge

问题描述以及问题重现步骤:

1. 地图上加载一个图标

2. 一秒钟移动20次位置,持续一段时间

3. 浏览器后台频繁提示

Canvas2D: Multiple readback operations using getImageData are faster with the willReadFrequently attribute set to true. See: https://html.spec.whatwg.org/multipage/canvas.html#concept-canvas-will-read-frequently

4. 连续移动几秒后,图标移动频率降低到大约1次/秒,重新缩放地图,则再次恢复移动速度到 20次/秒

有没有办法取消掉后台这个警告?以及解决一秒内多次移动的问题


问题补充:

请求的是这个地址:

'https://iserver.supermap.io/iserver/services/map-china400/rest/maps/China'
  const url = (window.isLocal ? window.server : 'https://iserver.supermap.io') + '/iserver/services/map-china400/rest/maps/China'

  window.map = new ol.Map({
    target: 'map2d-box',
    controls: ol.control.defaults(
      {
        attributionOptions: {
          collapsed: false
        }
      }),

    view: new ol.View({
      center: ol.proj.fromLonLat([113.5, 32.5]),
      zoom: 3.1,
      projection: 'EPSG:3857',
      multiWorld: true
    })
  })

1秒钟移动20次指的是:我这边有个物体移动轨迹,一秒钟给20个位置坐标,然后我把这个物体用图标表示在地图上。移动物体图标代码:

setInterval(() => {
    
    const feature = layer.getSource().getFeatureById(id)// 这个是那个物体的feature

    feature.getGeometry().setCoordinates(fromLonLat(location)) // 这个是物体的新的位置

}, 50);

我不知道我表述清楚没有,有些词我不明白是啥意思,我直接给你上代码吧

库我用的是iclient-ol, 开发的时候参照 openlayers.org


和这个问题不相关的疑问:

链接: openlayers 在地图上绘制矩形框,非鼠标框选

1个回答

您好,您是使用具体哪个iClient加载rest地图服务有问题,还是iserver地图服务内置的哪个预览有这个问题。

1秒钟移动20次您具体指的是什么样的实际应用场景,

鼠标快速拖动地图范围、代码移动地图范围、未切缓存的地图服务使用数据服务修改数据集中的数据点位、

和rest地图服务无关,使用iClient前端代码动态添加的点对象修改点位位置或者是什么其他情况呢?

需要您准确具体的描述下您的问题才好帮您排查。
于丁
1
9,538EXP 2023年03月01日
我补充下问题

您好,首先您说的这个问题的使用情况,我建议您是将需要做这种类似动态更新,动态轨迹的数据,

专门new一个数据源(ol.source.Vector)添加一个独立的图层(ol.layer.Vector),把你的动态数据和静态数据分开使用(静态数据一般数据量很大),

可以提高效率和稳定性。

关于你说的卡顿和报错情况我这边没有出现,你定位下具体是在定时器里用哪行代码才会出现

我这边测试了1秒20次(间隔50),1秒100次(间隔10)没有问题,你可以参考一下:


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title data-i18n="resources.title_AnimationFeature"></title>
<script type="text/javascript" src="../js/include-web.js"></script>
<script type="text/javascript" src="../../dist/ol/include-ol.js"></script>
</head>
<body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%; position: absolute;top: 0;">
<div id="map" style="width: 100%;height:100%"></div>
<script type="text/javascript">
    var url = (window.isLocal ? window.server : "https://iserver.supermap.io")+"/iserver/services/map-china400/rest/maps/China_4326";
    new ol.supermap.MapService(url).getMapInfo(function (serviceResult) {
        var mapJSONObj = serviceResult.result;
        var map = new ol.Map({
            target: 'map',
            controls: ol.control.defaults({attributionOptions: {collapsed: false}})
                .extend([new ol.supermap.control.Logo()]),
            view: new ol.View({
                center: [0, 0],
                zoom: 2,
                projection: 'EPSG:4326',
                multiWorld: true
            })
        });
        var options = ol.source.TileSuperMapRest.optionsFromMapJSON(url, mapJSONObj);
        var layer = new ol.layer.Tile({
            source: new ol.source.TileSuperMapRest(options)
        });
        map.addLayer(layer);

        function addRandomFeature() {
            var features = source.getFeatureById(0)
            //这个是那个物体的feature
            var Coordinate=feature.getGeometry().getCoordinates();
            Coordinate[0]=Coordinate[0]+5;
            if(Coordinate[0]>180)
            {Coordinate[0]=-180}
            //Coordinate[1]=Coordinate[1]+0.5
            feature.getGeometry().setCoordinates(Coordinate)
            //这个是物体的新的位置   
        }

        var source = new ol.source.Vector({
            wrapX: false
        });

        var vector = new ol.layer.Vector({
            source: source
        });
        map.addLayer(vector);
            var feature = new ol.Feature(new ol.geom.Point([-180, 0]));
            feature.setId(0);
            source.addFeature(feature);
        window.setInterval(addRandomFeature, 10);
    });
</script>
</body>
</html>

 您试试这个?我给点设置了样式,添加了图标,现在用的iclient for openlayers 库在哪里找?


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title data-i18n="resources.title_AnimationFeature"></title>
<script type="text/javascript" src="../js/include-web.js"></script>
<script type="text/javascript" src="../../dist/ol/include-ol.js"></script>
</head>
<body style=" margin: 0;overflow: hidden;background: #fff;width: 100%;height:100%; position: absolute;top: 0;">
<div id="map" style="width: 100%;height:100%"></div>
<script type="text/javascript">
    var url = (window.isLocal ? window.server : "https://iserver.supermap.io")+"/iserver/services/map-china400/rest/maps/China_4326";
    new ol.supermap.MapService(url).getMapInfo(function (serviceResult) {
        var mapJSONObj = serviceResult.result;
        var map = new ol.Map({
            target: 'map',
            controls: ol.control.defaults({attributionOptions: {collapsed: false}})
                .extend([new ol.supermap.control.Logo()]),
            view: new ol.View({
                center: [0, 0],
                zoom: 2,
                projection: 'EPSG:4326',
                multiWorld: true
            })
        });
        var options = ol.source.TileSuperMapRest.optionsFromMapJSON(url, mapJSONObj);
        var layer = new ol.layer.Tile({
            source: new ol.source.TileSuperMapRest(options)
        });
        map.addLayer(layer);

        function addRandomFeature() {
            var features = source.getFeatureById(0)
            //这个是那个物体的feature
            var Coordinate=feature.getGeometry().getCoordinates();
            Coordinate[0]=Coordinate[0]+1;
            if(Coordinate[0]>180)
            {Coordinate[0]=-180}
            //Coordinate[1]=Coordinate[1]+0.5
            feature.getGeometry().setCoordinates(Coordinate)
            //这个是物体的新的位置   
        }

        var source = new ol.source.Vector({
            wrapX: false
        });

        var vector = new ol.layer.Vector({
            source: source
        });
        map.addLayer(vector);
        var feature = new ol.Feature(new ol.geom.Point([-180, 0]));
        feature.setStyle(
            new ol.style.Style({
              image: new ol.style.Icon({
                src: 'https://img1.baidu.com/it/u=2368688822,253577201&fm=253&fmt=auto&app=138&f=PNG?w=500&h=500',
                scale: 0.05,
                opacity: 1,
                color: '#00FF00'
              })
            })
        )
        feature.setId(0);
        source.addFeature(feature);
        window.setInterval(addRandomFeature, 50);
    });
</script>
</body>
</html>

我这边完全使用你的代码也没有这个现象,建议你排查下浏览器或者换其他电脑看看有没有这个现象。

我这边测试用的浏览器是Chrome和火狐开发板。

新的iClient的话,现在是11i版本:

https://iclient.supermap.io/web/download/download.html

好的,我这边他只能移动一段时间,大概5秒左右,然后他就开始卡顿了
可恶,就我电脑有问题!

surprisesurprisesurprise

你电脑上的话,你看看和浏览器品种有没有关系,浏览器的缩放比例,windows的缩放比例、像素,屏幕。

那你知道这个为啥这么写吗?

var polygon = new ol.geom.Polygon([coords]); // 矩形构造方法,不知道这里为啥又套了一层数组,去掉这层数组则无法显示矩形
如果这么写的话,按照上面的例子,传入的内容为[ [ [110,20],[112,22],[114,25],[116,28],[111,40],[110,20] ] ]岂不是没有按照一般人的思路来,为什么多套一层?


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title data-i18n="resources.title_tiledMapLayer3857"></title>
<script type="text/javascript" src="../js/include-web.js"></script>
<script type="text/javascript" src="../../dist/ol/include-ol.js"></script>
</head>
<body style="margin: 0; overflow: hidden; background: #fff; width: 100%; height: 100%; position: absolute; top: 0">
<div id="map" style="width: 100%; height: 100%"></div>
<script type="text/javascript">
      var map,
        url =
          (window.isLocal ? window.server : 'https://iserver.supermap.io') +
          '/iserver/services/map-china400/rest/maps/China';
      // 方式一:1.调用 ol.supermap.initMap,根据 SuperMap iServer 地图服务的地图信息,创建地图和底图
    //   ol.supermap.initMap(url, {
    //     mapOptions: {
    //       controls: ol.control
    //         .defaults({ attributionOptions: { collapsed: false } })
    //         .extend([new ol.supermap.control.Logo()])
    //     }
    //   });
      
      /* 方式二:1.调用 ol.supermap.MapService,获取 SuperMap iServer 地图服务的地图信息
                2.调用 ol.supermap.viewOptionsFromMapJSON 获取地图视图参数
                3.调用 ol.Map 创建地图
                4.调用 ol.layer.Tile 与 ol.source.TileSuperMapRest 创建底图
      */
      new ol.supermap.MapService(url).getMapInfo(function (serviceResult) {
        const mapObj = serviceResult.result;
        map = new ol.Map({
          target: 'map',
          controls: ol.control
            .defaults({ attributionOptions: { collapsed: false } })
            .extend([new ol.supermap.control.Logo()]),
          view: new ol.View(ol.supermap.viewOptionsFromMapJSON(mapObj))
        });
        var layer = new ol.layer.Tile({
          source: new ol.source.TileSuperMapRest(ol.source.TileSuperMapRest.optionsFromMapJSON(url, mapObj, true))
        });
        map.addLayer(layer);
        map.addControl(new ol.supermap.control.ScaleLine());
        
        
        var coords = [[110,20],[112,22],[114,25],[116,28],[111,40],[110,20]]; // 矩形坐标数组
        
        var vectorLayer = new ol.layer.Vector();
        var vectorSource = new ol.source.Vector();
        var polygon = new ol.geom.Polygon([coords]); // 矩形构造方法,不知道这里为啥又套了一层数组,去掉这层数组则无法显示矩形
        polygon.applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857')); // 4326 对应的是经纬度坐标系,3857叫墨卡托?反正不是经纬度,需要做个转换
        vectorSource.addFeature(new ol.Feature(polygon)); // 形成Feature,并添加到source
        vectorLayer.setSource(vectorSource); // layer设置source
        map.addLayer(vectorLayer); // 将layer加入地图
      });
    </script>
</body>
</html>

因为 Polygon 可以做多对象复合多边形呢wink


<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<title data-i18n="resources.title_tiledMapLayer3857"></title>
<script type="text/javascript" src="../js/include-web.js"></script>
<script type="text/javascript" src="../../dist/ol/include-ol.js"></script>
</head>
<body style="margin: 0; overflow: hidden; background: #fff; width: 100%; height: 100%; position: absolute; top: 0">
<div id="map" style="width: 100%; height: 100%"></div>
<script type="text/javascript">
      var map,
        url =
          (window.isLocal ? window.server : 'https://iserver.supermap.io') +
          '/iserver/services/map-china400/rest/maps/China';
      // 方式一:1.调用 ol.supermap.initMap,根据 SuperMap iServer 地图服务的地图信息,创建地图和底图
    //   ol.supermap.initMap(url, {
    //     mapOptions: {
    //       controls: ol.control
    //         .defaults({ attributionOptions: { collapsed: false } })
    //         .extend([new ol.supermap.control.Logo()])
    //     }
    //   });
      
      /* 方式二:1.调用 ol.supermap.MapService,获取 SuperMap iServer 地图服务的地图信息
                2.调用 ol.supermap.viewOptionsFromMapJSON 获取地图视图参数
                3.调用 ol.Map 创建地图
                4.调用 ol.layer.Tile 与 ol.source.TileSuperMapRest 创建底图
      */
      new ol.supermap.MapService(url).getMapInfo(function (serviceResult) {
        const mapObj = serviceResult.result;
        map = new ol.Map({
          target: 'map',
          controls: ol.control
            .defaults({ attributionOptions: { collapsed: false } })
            .extend([new ol.supermap.control.Logo()]),
          view: new ol.View(ol.supermap.viewOptionsFromMapJSON(mapObj))
        });
        var layer = new ol.layer.Tile({
          source: new ol.source.TileSuperMapRest(ol.source.TileSuperMapRest.optionsFromMapJSON(url, mapObj, true))
        });
        map.addLayer(layer);
        map.addControl(new ol.supermap.control.ScaleLine());
        
        
        var coords1 = [[110,20],[116,28],[111,40]]; // 矩形坐标数组
        var coords2 = [[110,40],[116,48],[111,60]]; // 矩形坐标数组
              
        var vectorLayer = new ol.layer.Vector();
        var vectorSource = new ol.source.Vector();
        var polygon = new ol.geom.Polygon([coords1,coords2]); // 矩形构造方法,不知道这里为啥又套了一层数组,去掉这层数组则无法显示矩形
        polygon.applyTransform(ol.proj.getTransform('EPSG:4326', 'EPSG:3857')); // 4326 对应的是经纬度坐标系,3857叫墨卡托?反正不是经纬度,需要做个转换
        vectorSource.addFeature(new ol.Feature(polygon)); // 形成Feature,并添加到source
        vectorLayer.setSource(vectorSource); // layer设置source
        map.addLayer(vectorLayer); // 将layer加入地图
      });
    </script>
</body>
</html>

一个polygon,可以画好几个多边形?
嗯,复合对象。
...