HarmonyOS鸿蒙Next中怎么展示SVG格式图片

HarmonyOS鸿蒙Next中怎么展示SVG格式图片 鸿蒙怎么展示复杂的SVG,用什么办法比较好。

类似接口返回这样的,图片资源是从接口获取的

<svg width="84" height="88" xmlns="http://www.w3.org/2000/svg">
     <circle cx="40" cy="40" r="30" stroke="black" fill="red"/>
</svg>

这样的图片。我直接用Image(url) 展示不出来。

然后我用Web展示的,可以展示出来 但是感觉性能有点慢,有没有其他更好的方法。

if (!/viewBox/.test(svgStr)) {
  svgStr = svgStr.replace(
    /<svg\s+/,
    '<svg viewBox="0 0 84 88" '
  );
}
svgStr = svgStr.replace(
  /<svg([^>]*)width=".*?"([^>]*)height=".*?"/,
  '<svg$1 width="300"$2 height="300"'
);
const encodedSvg = encodeURIComponent(svgStr)
const  dataUrl = `data:image/svg+xml;charset=utf-8,${encodedSvg}`

更多关于HarmonyOS鸿蒙Next中怎么展示SVG格式图片的实战教程也可以访问 https://www.itying.com/category-93-b0.html

3 回复

【背景知识】

  • Image组件可显示矢量图(SVG格式的图片),SVG标签文档请参考SVG标签说明。如果SVG图片没有原始大小,需要给Image组件设置宽高,否则不显示。SVG图片不支持通过image标签引用svg格式和gif格式的本地其他图片。
  • 加载SVG图片目前可行的方法有很多,例如下载为SVG文件,然后通过文件读取;或者解析为Uint8Array,然后转为PixelMap进行加载,目前转为PixelMap方式可行性更高。

【解决方案】

首先可以使用TextEncoder类的encodeInto方法,将SVG字符串转化为Uint8Array类型,然后使用createImageSource通过buffer创建ImageSource实例,最后使用createPixelMap返回结果,参考代码如下:

import { image } from '@kit.ImageKit';
import { util } from '@kit.ArkTS';

@Entry
@Component
struct Index {
  @State pixelMap: image.PixelMap | undefined = undefined;
  // 将以下内容替换成从三方库得到的SVG字符串
  svgContent = '';

  async uint8ArrayToPixelMap(svg: string): Promise<image.PixelMap> {
    let encoder = new util.TextEncoder();
    const uint8Array = encoder.encodeInto(svg);
    const iconArray: ArrayBuffer = uint8Array.buffer.slice(0);
    let source = image.createImageSource(iconArray);
    const pixelMap = await source.createPixelMap();
    source.release();
    return pixelMap;
  }

  build() {
    Column() {
      Button('点击根据字符串加载SVG图片')
        .onClick(() => {
          this.uint8ArrayToPixelMap(this.svgContent).then((data: PixelMap) => {
            this.pixelMap = data;
          })
        })
        .margin({ top: 30, bottom: 30 })
      Image(this.pixelMap)
        .width('50%').height('50%')
        .alignRules({
          center: { anchor: '__container__', align: VerticalAlign.Center },
          middle: { anchor: '__container__', align: HorizontalAlign.Center }
        })
        .margin({ top: 30, bottom: 30 })
    }
    .height('100%')
    .width('100%')
  }
}

更多关于HarmonyOS鸿蒙Next中怎么展示SVG格式图片的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html


在HarmonyOS Next中,展示SVG图片需要使用Image组件,并设置src属性为SVG文件的资源路径。SVG文件需放在项目的resources/base/media/目录下。系统会自动解析并渲染SVG矢量图形。

在HarmonyOS Next中,直接使用Image组件加载SVG字符串确实无法显示。你遇到的性能问题,是因为Web组件渲染开销较大。针对从接口获取SVG字符串的场景,推荐以下两种更优方案:

方案一:使用 SvgImage 组件(推荐) 这是ArkUI为SVG提供的原生组件,性能最佳。

  1. 安装图形库:在 oh-package.json5 中声明依赖 "@ohos/graphics"
  2. 转换与渲染:将获取到的SVG字符串转换为 PixelMap,再交给 SvgImage 展示。
    import { SvgImage } from '@ohos/graphics';
    // 假设 svgString 是从接口获取的SVG文本
    let svgImageController: SvgImage.SvgImageController = new SvgImage.SvgImageController();
    // 创建SvgImage对象并传入SVG字符串
    let svgImage: SvgImage.SvgImage = svgImageController.createSvgImage(svgString);
    // 将SvgImage转换为PixelMap
    let pixelMap: image.PixelMap = svgImage.createPixelMap();
    // 在UI中使用Image组件显示
    Image(pixelMap)
        .width('100%')
        .height('100%')
    
    此方案直接利用系统底层渲染引擎,避免了WebView的额外开销。

方案二:转换为Base64 Data URL 如果 SvgImage 暂时无法满足复杂SVG(如包含特定滤镜或动画),可沿用你的转换思路,但需确保格式正确。

  1. 确保SVG格式完整:接口返回的SVG必须包含有效的XML命名空间(如你示例中的 xmlns="http://www.w3.org/2000/svg")。
  2. 进行URL编码:对你的代码稍作优化,确保特殊字符被正确处理。
    // 对SVG字符串进行编码,注意处理换行和特殊字符
    let encodedSvg = encodeURIComponent(svgStr.replace(/\s+/g, ' ').trim());
    let dataUrl = `data:image/svg+xml;charset=utf-8,${encodedSvg}`;
    
  3. 使用Image组件加载
    Image(dataUrl)
        .width('100%')
        .height('100%')
    
    这种方式比Web组件轻量,但性能仍次于原生 SvgImage 方案。

总结

  • 首选 SvgImage 组件:它是HarmonyOS Next为SVG渲染提供的原生支持,性能最优,兼容性由系统保证。
  • 备选 Data URL:在 SvgImage 无法处理的边缘情况下使用,注意确保字符串格式规范。
  • 避免使用Web组件:仅当SVG包含大量交互或动画逻辑时才考虑,静态展示不推荐。

根据你的描述,接口返回的是标准SVG图形(如示例中的圆形),SvgImage 方案完全适用且能解决性能问题

回到顶部