HarmonyOS 鸿蒙Next componentSnapshot无法对全局builder截图

发布于 1周前 作者 htzhanglong 来自 鸿蒙OS

HarmonyOS 鸿蒙Next componentSnapshot无法对全局builder截图

遇到的问题

我们APP的地图上的marker的样式比较多,需要自定义样式。在Android的地图上,我们是自定义个一个View然后转成bitmap,最后传给地图SDK。鸿蒙地图的marker支持类似bitmap的pixelmap, 所以我们期望的就是自定义marker的样式的组件,然后把组件转换成pixmel.

目前的解决办法以及缺陷

自定义一个builder函数,通过componentSnapshot把builder函数转成pixelmap,这个方法是可行的。 但是这样就引入了另一个问题,componentSnapshot只能对component内部的builder函数进行截图,无法对全局builder函数进行截图,这样就就会把marker的代码和component的代码耦合在一起。 

6 回复

我们在用高德地图,遇到同样的问题,猜测高德里面也调用的componentSnapshot方法。

我只解决了耦合问题:一个mapController类管理地图,生成mark的时候,用外部传入的一个builder方法。这个buider方法需要在某个组件实现并传入,实现builder的时候还可以直接调用单独封装的自定义组件。

但是实测每次绘制要300-500ms,我们动态内容很多,每次可能要绘制几十上百个marker,顺序绘制的话要好几秒,还是有很大问题。不知怎么解决,目前只想到用并发绘制能优化下,但即使并发能优化到1秒内,也远远不够啊。。


// MapController:

stationMarkerBuilder?: (station:MapStationListBean) => voidlet pixmap = await componentSnapshot.createFromBuilder(()=>{if (this.stationMarkerBuilder)this.stationMarkerBuilder(item)})

// MapPage: this.mapController.stationMarkerBuilder = (station) => { this.stationBuilder(station) } … @Builder stationBuilder(station:MapStationListBean) { MapStationMarkerView({num:station.stationNum}) }<button style="position: absolute; padding: 4px 8px 0px; cursor: pointer; top: 8px; right: 8px; font-size: 14px;">复制</button>

异步并发试了,可以用。效果勉强可以吧。

拆代码方面,可以在上面代码的基础上,把单独封装marker对象,把业务数据、marker配置、builder方法都放进去,生成的图片也存在这里,这样有更多优化空间。

export class LineMapStationMarkerObj {

stationBean:MapStationListBean option?:MarkerOptions icon?:BitmapDescriptor

stationMarkerBuilder?: (station:MapStationListBean) => void

constructor(station:MapStationListBean) { this.stationBean = station }

async updateOption() {

let latitude = Number(this.stationBean.latitude)
let longitude = Number(this.stationBean.longitude)
if (latitude &amp;&amp; longitude) {
  let option: MarkerOptions = new MarkerOptions();

  if (!this.icon) {
    console.time('componentSnapshotStation')
    let pixmap = await componentSnapshot.createFromBuilder(() =&gt; {
      if (this.stationMarkerBuilder) this.stationMarkerBuilder(this.stationBean)
    }) //, 320, true, {scale : 2, waitUntilRenderFinished : true})
    console.timeEnd('componentSnapshotStation')
    //
    this.icon = BitmapDescriptorFactory.fromPixelMapSync(pixmap)
  }

  if (this.icon) {
    option.setIcon(this.icon);
  }
  option.setDraggable(false);
  option.setPosition(new LatLng(latitude, longitude));
  option.setAnchor(0.5, 1);
  this.option = option
}

} }

// MapController: // 重新绘制站点marker async redrawStationMarkers(data:MapStationListBean[]) { this.stationList = data if (!this.aMap) { return } // 清除之前的 this.stationMarkers?.forEach((marker)=>{ this.aMap?.removeOverlay(marker.getId()) })

    // 整理数据、marker设置
let stationMarkerObjs : LineMapStationMarkerObj[] = []
let promiseList : Promise&lt;void&gt;[] = [] // 异步任务

data.forEach((item) =&gt; {
  let markerObj = new LineMapStationMarkerObj(item)
  markerObj.stationMarkerBuilder = this.stationMarkerBuilder
  stationMarkerObjs.push(markerObj)
  // 添加异步任务
  promiseList.push(markerObj.updateOption())
})
this.stationMarkerObjs = stationMarkerObjs

// 并发异步获取option
Promise.all(promiseList).then(()=&gt;{
  let optionsList :ArrayList&lt;MarkerOptions&gt; = new ArrayList&lt;MarkerOptions&gt;()
  this.stationMarkerObjs?.forEach((markerObj) =&gt; {
    optionsList.add(markerObj.option)
  })
  this.stationMarkers = this.aMap?.addMarkers(optionsList)
})

}

开发者您好,描述提供的定位问题的信息有限,有复现问题的简化Demo吗。

就是componentSnapshot不支持传入全局builder

有解决办法吗 哥 被离屏获取截图整吐了

HarmonyOS 中 componentSnapshot 通常用于捕获组件的截图,而非全局 Builder。如果你需要捕获全局视图(如整个页面或应用界面),这通常不是通过组件的截图功能直接实现的。

对于全局截图,你可能需要考虑使用系统级别的API或工具,如屏幕录制API的变种(但需注意这可能受限于安全和隐私政策)。此外,开发过程中可以通过开发者选项中的“显示布局边界”等辅助功能来视觉检查界面布局,但非直接截图。

如果问题依旧没法解决请加我微信,我的微信是itying888。

回到顶部