kikitte/MVTImageryProvider

我尝试通过pickFeatures方法获取矢量元素信息,但是该方法返回的Promise状态总是rejected,我找不到问题的所在,求助。

wh1246935943 opened this issue · 4 comments

我调用pickFeatures()想获取鼠标点击的元素的矢量信息,用于后期的操作,比如更换颜色。从我阅读源码猜测是用这个方法。
用cesium的api获取需取该方法需要的参数,如下:

function getApproximateZoomLevel() {
    var cameraHeight = state.mapInstance.viewer.camera.positionCartographic.height;
    var approximateZoomLevel = Math.log2(591657550.500000 / cameraHeight);
    console.log('Approximate Zoom Level: ', approximateZoomLevel);
    return approximateZoomLevel
  }
state.mapInstance.viewer.screenSpaceEventHandler.setInputAction(function onLeftClick(movement) {
      var cartesian = state.mapInstance.viewer.camera.pickEllipsoid(movement.position, state.mapInstance.viewer.scene.globe.ellipsoid);
      if (cartesian) {
          var cartographic = Cartographic.fromCartesian(cartesian);
          var longitude = Math.toDegrees(cartographic.longitude);
          var latitude = Math.toDegrees(cartographic.latitude);
          var height = cartographic.height;
          console.log('Clicked XYZ: ', cartesian);
          console.log('Clicked Longitude: ', longitude);
          console.log('Clicked Latitude: ', latitude);
          console.log('Clicked Height: ', height);
          
          const info = state.pbfProvider.pickFeatures(cartesian?.x, cartesian?.y, getApproximateZoomLevel(), longitude, latitude);
          console.log(info)
      }
    }, ScreenSpaceEventType.LEFT_CLICK);

但是这个方法总是返回Promise rejected,我想请问的是,我调用该方法传入的参数是否正确?对于这个报错我现在找不到问题的所在,请您帮我看下应该怎么处理。

promise返回的是什么呢,控制台输出的代码改一下看看

info.then(res => console.log(res))

promise返回的是什么呢,控制台输出的代码改一下看看

info.then(res => console.log(res))

info.then(res => console.log('res:::', res)).catch((err) => console.log('err:::', err))
没有进then,catch中err输出undefined,非常感谢您的回复,这个问题我通过另一个方式曲线救国了。

有两种方式,
第一种: 直接通过MVTImageryProvider渲染完整的style

new MVTImageryProvider({
        style,
        showCanvas: false
});

然后使用:

const featuresPromise = viewer.imageryLayers.pickImageryLayerFeatures(pickRay as Ray, viewer.scene);
Promise.resolve(featuresPromise).then(function(features) {
       console.log('features:::', features)
});

第二种:先通过http拿到style.json的json数据,再以layers为依据,将数据构造成多个style,再调用MVTImageryProvider渲染

const { data } = await axios.get<StyleSpecification>(style);
const styles: StyleSpecification[] = []
this.layersSpecification = data.layers;
        data.layers.forEach((layer) => {
        const newStyleItem = cloneDeep(data);
        newStyleItem.layers = [layer];
        newStyleItem.sources = {[layer.source]: data.sources[layer.source]};
        styles.push(newStyleItem)
});

const providers = await this.createProvider(styles);

createProvider = (styles: StyleSpecification[]): Promise<MVTImageryProvider[]> => {
    const pList: MVTImageryProvider[] = [];
    return new Promise<MVTImageryProvider[]>(async (resolve, reject) => {
      const list = styles.map((style) => {
        const p = new MVTImageryProvider({ style });
        pList.push(p)
        return p.readyPromise
      })
      await Promise.all(list);
      resolve(pList)
    })
};

providers.forEach(provider => {
      const layer = viewer.imageryLayers.addImageryProvider(provider as unknown as ImageryProvider);
});

最终我选择了第二种方案,因为第一种再修改style.json中layers的某一项后,要重新渲染所有的瓦片,实际的渲染效率很低,第二种的话,因为每一个都是一个图层,修改后可以单独渲染这一个图层,目前我得数据量小,还没发现有性能问题。

但是目前我有一个最头疼的问题,再请教下您(这个问题再第一种方案中也一样存在):当首次渲染完成后,修改这个图层对应的style后,重新渲染出来的栅格瓦片,分辨率不正常(太模糊,好似没有适配到当前缩放的级别),且有很大概率部分瓦片不会渲染出来(地球上没能正常展示出来),如下图:
image

瓦片显示不完整的这个问题我也有遇到,但是频率不是很高,我感觉可能是资源释放和缓存的问题,你在移除原来图层的时候有调用provider.destroy()方法吗。
层级显示不正确这个问题暂时还没遇到过,得在mapboxRender里面调试,查看具体传入的瓦片数据。您如果有能力的话,可以自己试试,俺这段时间应该搞不了太多。。

瓦片显示不完整的这个问题我也有遇到,但是频率不是很高,我感觉可能是资源释放和缓存的问题,你在移除原来图层的时候有调用provider.destroy()方法吗。 层级显示不正确这个问题暂时还没遇到过,得在mapboxRender里面调试,查看具体传入的瓦片数据。您如果有能力的话,可以自己试试,俺这段时间应该搞不了太多。。

好的,非常感谢