index.uts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. import PictureDrawable from "android.graphics.drawable.PictureDrawable";
  2. import ImageView from "android.widget.ImageView";
  3. import File from "java.io.File";
  4. import FileInputStream from "java.io.FileInputStream";
  5. import Color from "android.graphics.Color";
  6. import RenderOptions from "com.caverock.androidsvg.RenderOptions";
  7. import Base64 from "android.util.Base64";
  8. import Charset from "java.nio.charset.Charset";
  9. import StandardCharsets from "java.nio.charset.StandardCharsets";
  10. /**
  11. * CoolSvg Android 平台 SVG 渲染器
  12. * 支持多种 SVG 数据格式:
  13. * - base64 编码的数据 URL
  14. * - URL 编码的数据 URL
  15. * - 本地文件路径
  16. * - Android 资源文件
  17. */
  18. export class CoolSvg {
  19. /** 原生视图元素 */
  20. $element: UniNativeViewElement;
  21. /** Android ImageView 实例 */
  22. imageView: ImageView | null = null;
  23. /**
  24. * 构造函数
  25. * @param element uni-app x 原生视图元素
  26. */
  27. constructor(element: UniNativeViewElement) {
  28. this.$element = element;
  29. this.imageView = new ImageView(UTSAndroid.getAppContext()!);
  30. this.$element.bindAndroidView(this.imageView!);
  31. }
  32. /**
  33. * 加载并渲染 SVG
  34. * @param src SVG 数据源,支持以下格式:
  35. * - data:image/svg+xml;base64,<base64数据>
  36. * - data:image/svg+xml,<URL编码的SVG>
  37. * - 本地文件路径
  38. * @param color 填充颜色,用于替换 SVG 中 path 元素的 fill 属性
  39. */
  40. load(src: string, color: string) {
  41. // 空字符串检查
  42. if (src == "") {
  43. return;
  44. }
  45. try {
  46. if (src.startsWith("data:image/svg")) {
  47. // 处理数据 URL 格式的 SVG
  48. this.loadFromDataUrl(src, color);
  49. } else {
  50. // 处理本地文件或资源文件
  51. this.loadFromFile(src, color);
  52. }
  53. } catch (e) {
  54. // 打印异常信息用于调试
  55. e.printStackTrace();
  56. }
  57. }
  58. /**
  59. * 从数据 URL 加载 SVG
  60. * @param dataUrl 数据 URL 字符串
  61. * @param color 填充颜色
  62. */
  63. private loadFromDataUrl(dataUrl: string, color: string) {
  64. let svgString: string;
  65. if (dataUrl.startsWith("data:image/svg+xml;base64,")) {
  66. // 处理 base64 编码的 SVG
  67. const base64Prefix = "data:image/svg+xml;base64,";
  68. const base64Data = dataUrl.substring(base64Prefix.length);
  69. const decodedBytes = Base64.decode(base64Data, Base64.DEFAULT);
  70. svgString = String(decodedBytes, StandardCharsets.UTF_8);
  71. } else {
  72. // 处理 URL 编码的 SVG
  73. const urlPrefix = "data:image/svg+xml,";
  74. const encodedSvg = dataUrl.substring(urlPrefix.length);
  75. svgString = decodeURIComponent(encodedSvg) ?? '';
  76. }
  77. const svg = com.caverock.androidsvg.SVG.getFromString(svgString);
  78. this.render(svg, color);
  79. }
  80. /**
  81. * 从文件加载 SVG
  82. * @param src 文件路径
  83. * @param color 填充颜色
  84. */
  85. private loadFromFile(src: string, color: string) {
  86. // uni-app x 正式打包会将资源文件放在 Android asset 中
  87. const path = UTSAndroid.getResourcePath(src);
  88. if (path.startsWith("/android_asset")) {
  89. // 从 Android 资源文件中加载
  90. const assetPath = path.substring(15); // 移除 "/android_asset" 前缀
  91. const svg = com.caverock.androidsvg.SVG.getFromAsset(
  92. UTSAndroid.getAppContext()!.getAssets(),
  93. assetPath
  94. );
  95. this.render(svg, color);
  96. } else {
  97. // 从本地文件系统加载
  98. const file = new File(path);
  99. if (file.exists()) {
  100. const svg = com.caverock.androidsvg.SVG.getFromInputStream(
  101. new FileInputStream(file)
  102. );
  103. this.render(svg, color);
  104. }
  105. }
  106. }
  107. /**
  108. * 渲染 SVG 到 ImageView
  109. * @param svg AndroidSVG 对象
  110. * @param color 填充颜色,应用到所有 path 元素
  111. */
  112. private render(svg: com.caverock.androidsvg.SVG, color: string) {
  113. // 创建渲染选项,设置 CSS 样式来改变 SVG 的填充颜色
  114. const options = RenderOptions.create().css(`path { fill: ${color}; }`);
  115. // 将 SVG 渲染为 Picture,然后转换为 Drawable
  116. const drawable = new PictureDrawable(svg.renderToPicture(options));
  117. // 设置到 ImageView 中显示
  118. this.imageView?.setImageDrawable(drawable);
  119. }
  120. }