HarmonyOS鸿蒙Next中频繁改变web组件的高度会造成内容刷新掉帧卡顿的问题?

HarmonyOS鸿蒙Next中频繁改变web组件的高度会造成内容刷新掉帧卡顿的问题?

现在有个需求是根据web的缩放来改变web组件的高度,我的实现方式是类似于这样:

@Component
export struct myWeb {
  public controller: webview.WebviewController = new webview.WebviewController();
  onScaleChange: (oldScale: number, newScale: number) => void = () => {}

  build() {
    Web({
      src: $rawfile("readMail.html"),
      controller: this.controller
    })
      .zoomAccess(true)
      .onScaleChange((event) => {
        this.onScaleChange(event.oldScale, event.oldScale)
      })
      .horizontalScrollBarAccess(false)
      .verticalScrollBarAccess(false)
  }
}

// TestWeb.ets
  build() {
    Column() {
      myWeb({
        controller: this.webController,
        onScaleChange: (oldScale: number, newScale: number) => {
          this.webHeight = this.constWebHeight * oldScale / 100
        }
      })
    }
    .height(this.webHeight)
  }

这样在缩放的过程中,web组件的高度确实发生了改变,但是web组件的内容部分缩放会有些卡顿掉帧的样子。

起初我以为是改变一个组件的高度造成组件内部内容刷新导致的,但是随后我又进行了测试:

  Text("ReadMail Text")
    .width("100%")
    .height(this.textHeight)
    // 不断快速改变textHeight并不会造成内容:ReadMail Text的掉帧

所以我不知道为什么改变web组件的高度会导致内容卡顿掉帧,麻烦大佬们答疑解惑,谢谢!


更多关于HarmonyOS鸿蒙Next中频繁改变web组件的高度会造成内容刷新掉帧卡顿的问题?的实战教程也可以访问 https://www.itying.com/category-93-b0.html

4 回复

开发者你好:

Web组件渲染模式:Web组件支持两种渲染模式,异步渲染模式(默认)同步渲染模式

Web组件大小自适应页面内容布局:使用Web组件大小自适应页面内容布局模式时,能使Web组件的大小根据页面内容自适应变化。

onScaleChange:当前页面显示比例的变化时触发该回调。

【解决方案】

  • 由于高度更新过于频繁,触发了不必要的重渲染或布局计算。
  • 可以使用节流或防抖来限制更新频率,减少性能消耗。

代码如下:

import { webview } from '@kit.ArkWeb';

@Component
struct Demo {
  public controller: webview.WebviewController = new webview.WebviewController();
  onScaleChange: (oldScale: number, newScale: number) => void = () => {}

  build() {
    Web({
      src: $rawfile("Untitled-1.html"),
      controller: this.controller
    })
      .zoomAccess(true)
      .onScaleChange((event) => {
        this.onScaleChange(event.oldScale, event.oldScale)
      })
      .horizontalScrollBarAccess(false)
      .verticalScrollBarAccess(false)
  }
}

class Util {
  // 防抖 在一段时间内函数被多次触发,防抖让函数在一段时间后最终只执行一次
  static debounce(fun: (height: number) => void, delay?: number) {
    let timer: number;
    return (height: number) => {
      clearTimeout(timer);
      timer = setTimeout(() => {
        fun(height);
      }, delay ? delay : 100);
    };
  }

  // 节流 在规定的时间内,只执行一次
  throttle(fun: (height: number) => void, delay?: number) {
    let inThrottle: boolean;
    return (height: number) => {
      if (!inThrottle) {
        fun(height);
        inThrottle = true;
        setTimeout(() => inThrottle = false, delay ? delay : 1000);
      }
    };
  }
}

@Entry
@Component
struct Index {
  @State webHeight: number = 600; // 当前显示高度
  @State constWebHeight: number = 600; // 基础计算高度
  webController: webview.WebviewController = new webview.WebviewController();
  // 创建防抖函数实例(300ms延迟)
  debouncedSetHeight = Util.debounce((newHeight: number) => {
    this.webHeight = newHeight;
    console.info(`防抖后高度:${this.webHeight}`);
  }, 100)

  build() {
    Column() {
      Demo({
        controller: this.webController,
        onScaleChange: (oldScale: number, newScale: number) => {
          const targetHeight = this.constWebHeight * newScale / 100;
          this.debouncedSetHeight(targetHeight); // 触发防抖函数
        }
      })
    }
    .height(this.webHeight)
    .width('100%')
  }
}

【常见FAQ】

Q:使用Web组件页面时,在网页加载过程中,页面底部可能出现闪烁现象。

A:应用可以通过设置与网页背景色相同的Web组件的背景色,避免视觉闪烁。请参阅闪烁原因及优化方案,了解详情。

更多关于HarmonyOS鸿蒙Next中频繁改变web组件的高度会造成内容刷新掉帧卡顿的问题?的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


web组件需要干的活太多了,谁没事拖拽浏览器窗口玩呢?

在HarmonyOS鸿蒙Next中,频繁改变Web组件的高度可能导致渲染引擎频繁重新计算布局和绘制,从而引发掉帧和卡顿。这是因为每次高度变化都会触发布局重排和重绘,增加了渲染负担。优化方法包括减少不必要的布局变化、使用CSS动画替代JavaScript直接操作高度、或通过requestAnimationFrame来优化渲染时机。

在HarmonyOS Next中,Web组件高度频繁变化导致卡顿掉帧的主要原因在于Web组件的渲染机制与普通组件不同。以下是关键点分析:

  1. Web组件本质上是嵌入式浏览器实例,每次高度变化都会触发以下重计算:
  • 页面布局重排(Reflow)
  • 内容重绘(Repaint)
  • 合成层重组(Compositing)
  1. 性能差异原因:
  • Text组件是原生控件,高度变化只触发简单布局更新
  • Web组件需要完整的浏览器渲染管线处理,成本高10-100倍
  1. 优化建议方向: (1) 使用debounce/throttle控制回调频率(建议200ms间隔) (2) 改为transform缩放替代高度修改:
Web({...})
.scale({ x: scaleFactor, y: scaleFactor })

(3) 提前设置固定高度,通过CSS transform缩放内部内容

  1. 根本原因: 浏览器引擎需要重新计算所有DOM元素的布局位置,特别是当包含复杂CSS或JavaScript时,这个计算过程无法达到原生组件的优化程度。

这种性能差异是跨平台WebView组件的固有特性,最佳实践是尽量减少布局属性在动画期间的连续变化。

回到顶部