# Image组件加载SVG图片异常的常见问题

#### 问题现象

在使用Image组件加载SVG图片时，通常源于SVG图片本身的特性、Image组件的配置方式或HarmonyOS对SVG规范的支持范围等，导致SVG加载异常，具体表现包括：

场景一：图片区域空白，完全无法显示。

场景二：图片加载不全，显示部分区域。

场景三：图片被拉伸或压缩，导致宽高比失调。

场景四：图片填充颜色失败，图片没有变化。

#### 背景知识

*   Image：Image为图片组件，常用于在应用中显示图片。Image支持加载PixelMap、ResourceStr和DrawableDescriptor类型的数据源，支持png、jpg、jpeg、bmp、svg、webp、gif和heif类型的图片格式，不支持apng和svga格式。
*   SVG：SVG（Scalable Vector Graphics）是可缩放矢量图形，它是一种基于XML（可扩展标记语言）的图形格式，用于描述二维图形和图像。和其他基于像素的图像格式不同，SVG没有单位的概念，它是以文本形式存储的，其优势在于缩放无损失真，适合多分辨率设备。

#### 解决方案

场景一：宽高属性未设置。

HarmonyOS从API version 10开始支持SVG标签，使用的为SVG1.1规范的部分功能，具体参考SVG标签说明。SVG文件可添加xml声明，应以<?xml开头，并且SVG标签内需设置width，height。例如，若SVG标签内未设置宽高并且Image组件未设置宽高尺寸，SVG图片会因缺少参考尺寸而无法正确布局，导致显示不出来。

示例代码如下：

```
@Entry
@Component
struct Index {
  build() {
    Column({ space: 30 }) {
      Text('预期图片');
      Column() {
        // 本地资源，需自行替换
        Image($rawfile('notdisplayed.svg'))
          // 注意：由于SVG标签内未设置width、height,此时需要给Image组件设置宽高尺寸。
          .width('200')
          .height('200');
      }
      .width('250')
      .height('250')
      .border({ width: 1 });

      Text('加载失败图片');
      Column() {
        // 本地资源，需自行替换
        Image($rawfile('notdisplayed.svg'));
      }
      .width('250')
      .height('250')
      .border({ width: 1 });
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}
```

使用下方SVG图片需要新建xxx.svg文件并粘贴代码保存至resources/rawfile目录下。SVG代码如下：

```
<svg xmlns="" viewBox="0 0 200 200">
    <!-- 中心圆形 -->
    <circle cx="100" cy="100" r="40" fill="#0a59f7" opacity="0.9"/>
    <!-- 装饰三角形 -->
    <polygon points="100,20 120,60 80,60" fill="rgba(255, 117, 218, 1)" opacity="0.7"/>
</svg>
```

运行效果如下：

场景二：标签支持范围限制。

目前HarmonyOS支持的SVG标签范围有限，具体可以查看当前支持的标签列表，当使用不支持的标签或标签不支持参数时，会出现SVG图片加载异常。可以通过简化实现代码，只保留基本形状代码，并逐渐复杂化排查引起图片加载异常的特性。例如，SVG目前不支持Text标签，在图片加载时将无法显示SVG里的文字（暂时可以将SVG转成其他格式图片加载）。

示例代码如下：

```
@Entry
@Component
struct Page {
  build() {
    Column({ space: 30 }) {
      Text('预期图片');
      Column() {
        // 本地资源，需自行替换
        Image($r('app.media.picture'))
          .width('150')
          .height('150');
      }
      .width('250')
      .height('250')
      .border({ width: 1 });

      Text('加载失败图片');
      Column() {
        // 本地资源，需自行替换
        Image($rawfile('iconText.svg'));
      }
      .width('250')
      .height('250')
      .border({ width: 1 });
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}
```

使用下方SVG图片需要新建xxx.svg文件并粘贴代码保存至resources/rawfile目录下。SVG代码如下：

```
<svg width="800" height="800" xmlns="" style="background:#f0f0f0">
    <!-- 渐变背景 -->
    <defs>
        <radialGradient id="radial-gradient" cx="50%" cy="50%" r="50%" fx="50%" fy="50%">
            <stop offset="0%" stop-color="#0a59f7"/>
        </radialGradient>
    </defs>
    <!-- 中心圆形 -->
    <circle cx="400" cy="300" r="180" fill="url(#radial-gradient)"/>
    <!-- 添加在圆形中心的文字 -->
    <text x="400" y="300"
          text-anchor="middle"
          dominant-baseline="middle"
          font-family="Arial, sans-serif"
          font-size="28"
          font-weight="bold"
          fill="white">
        这是带文字的SVG
    </text>
    <!-- 装饰元素 -->
    <polygon points="350,150 450,150 400,80" fill="rgba(255, 117, 218, 1)" opacity="0.8"/>
</svg>
```

运行效果如下：

场景三：objectFit参数配置。

SVG图片最终显示效果受Image组件的objectFit参数值影响，为了确保SVG图形完整且正确的显示，开发者需要根据实际显示效果正确配置ImageFit参数。例如，给objectFit设置为ImageFit.Fill那么图片会为了充满显示边界不保持宽高比进行放大缩小，使得图片被压缩变形。

示例代码如下：

```
@Entry
@Component
struct PageOne {
  build() {
    Column({ space: 30 }) {
      Text('预期图片');
      Column() {
        // 本地资源，需自行替换
        Image($rawfile('display.svg'))
          .width('100')
          .height('200');
      }
      .width('200')
      .height('200')
      .border({ width: 1 });

      Text('受到objectFit影响的图片');
      Column() {
        // 本地资源，需自行替换
        Image($rawfile('display.svg'))
          .width('100')
          .height('200')
          .objectFit(ImageFit.Fill);
      }
      .width('200')
      .height('200')
      .border({ width: 1 });
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center);
  }
}
```

使用下方SVG图片需要新建xxx.svg文件并粘贴代码保存至resources/rawfile目录下。SVG代码如下：

```
<svg width="150" height="150" xmlns="" viewBox="0 0 200 200">
    <!-- 中心圆形 -->
    <circle cx="100" cy="100" r="40" fill="#0a59f7" opacity="0.9"/>
    <!-- 装饰三角形 -->
    <polygon points="100,20 120,60 80,60" fill="rgba(255, 117, 218, 1)" opacity="0.7"/>
</svg>
```

运行效果如下：

场景四：解析能力增强功能的差异。

使用SVG标签解析能力增强，从API21开始，将Image组件的supportSvg2属性设置为true时，将启用SVG标签解析能力增强功能。启用增强的解析处理能力后，将会影响部分SVG元素和属性。例如，Image组件的fillColor属性不对SVG图源中fill = 'none'的元素填充颜色。建议开发者在SVG标签解析能力增强中确认差异后使用。对于新项目，推荐默认启用以利用最新优化。

#### 总结

Image组件加载SVG图片异常多源于SVG规范兼容性、尺寸配置或属性设置不当。其解决方案的核心在于：确保SVG文件符合规范、合理配置Image组件属性、规避未支持标签，并利用新API的增强功能。开发者应遵循渐进式调试原则，先简化SVG内容再逐步复杂化，同时参考官方文档更新支持状态。