HarmonyOS 鸿蒙Next componentSnapshot无法对全局builder截图
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的代码耦合在一起。
我们在用高德地图,遇到同样的问题,猜测高德里面也调用的componentSnapshot方法。
我只解决了耦合问题:一个mapController类管理地图,生成mark的时候,用外部传入的一个builder方法。这个buider方法需要在某个组件实现并传入,实现builder的时候还可以直接调用单独封装的自定义组件。
但是实测每次绘制要300-500ms,我们动态内容很多,每次可能要绘制几十上百个marker,顺序绘制的话要好几秒,还是有很大问题。不知怎么解决,目前只想到用并发绘制能优化下,但即使并发能优化到1秒内,也远远不够啊。。
// MapController:
stationMarkerBuilder?: (station:MapStationListBean) => void
…
let 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 && longitude) {
let option: MarkerOptions = new MarkerOptions();
if (!this.icon) {
console.time('componentSnapshotStation')
let pixmap = await componentSnapshot.createFromBuilder(() => {
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<void>[] = [] // 异步任务
data.forEach((item) => {
let markerObj = new LineMapStationMarkerObj(item)
markerObj.stationMarkerBuilder = this.stationMarkerBuilder
stationMarkerObjs.push(markerObj)
// 添加异步任务
promiseList.push(markerObj.updateOption())
})
this.stationMarkerObjs = stationMarkerObjs
// 并发异步获取option
Promise.all(promiseList).then(()=>{
let optionsList :ArrayList<MarkerOptions> = new ArrayList<MarkerOptions>()
this.stationMarkerObjs?.forEach((markerObj) => {
optionsList.add(markerObj.option)
})
this.stationMarkers = this.aMap?.addMarkers(optionsList)
})
}
开发者您好,描述提供的定位问题的信息有限,有复现问题的简化Demo吗。
就是componentSnapshot不支持传入全局builder
有解决办法吗 哥 被离屏获取截图整吐了
HarmonyOS 中 componentSnapshot
通常用于捕获组件的截图,而非全局 Builder
。如果你需要捕获全局视图(如整个页面或应用界面),这通常不是通过组件的截图功能直接实现的。
对于全局截图,你可能需要考虑使用系统级别的API或工具,如屏幕录制API的变种(但需注意这可能受限于安全和隐私政策)。此外,开发过程中可以通过开发者选项中的“显示布局边界”等辅助功能来视觉检查界面布局,但非直接截图。
如果问题依旧没法解决请加我微信,我的微信是itying888。