OpenHarmony图片处理——XmlGraphicsBatik

2024-09-20 17:14:54 浏览数 (2)

简介

XmlGraphicsBatik项目用于处理可缩放矢量图形(SVG)格式的图像,例如显示、生成、解析或者操作图像。

支持SVG图像的显示,可显示静态及动态SVG图像;

支持快捷生成SVG图像文件;

支持操作SVG图像进行颜色、样式、内容的修改;

支持将SVG图像的xml文本解析为可操作对象。

下载安装

代码语言:ts复制
ohpm install @ohos/xmlgraphicsbatik 

使用说明

对SVG图像进行生成、操作、解析等操作均依赖于SVGManager管理类

使用本库需要预先在MainAbility.ts 中预制文件路径: GlobalContext.getContext().setObject("filesDir", this.context.filesDir);

代码语言:ts复制
import {SVGManager} from '@ohos/XmlGraphicsBatik';

private svgManager: SVGManager = SVGManager.getInstance();

1. 显示SVG图像

代码语言:ts复制
// Iamge组件支持显示media资源文件 及 工程目录中的SVG图片
Image($r('app.media.svgSample'))
  .width(150)
  .height(150)

Image('file://'   this.filePath   '/svg.svg')
  .width(150)
  .height(150)

2. 生成SVG图像文件

2.1 创建SVG文件声明及子标签

代码语言:ts复制
// 创建SVG 对象:声明及SVG标签
this.svgManager.createSVGDeclares();

// 获取SVG标签对应的对象
let svgTagObj = this.svgManager.getSVGRoot();

// 构建SVG中的rect节点
let rect: SVGRect = new SVGRect();
rect.setX(50);
rect.setY(50);
rect.setRX(20);
rect.setRY(20);
rect.setWidth(100);
rect.setHeight(100);
rect.addAttribute('style', 'fill:rgb(255,0,255);stroke-width:2;stroke:rgb(0,0,0)')

// 输出标准格式rect对象
let rectObj = rect.toObj();

// 构建固定格式的节点描述对象
let svgFormatForRect: SVGSpecifiedFormat = new SVGSpecifiedFormat();
svgFormatForRect.setElementType(SVGAttrConstants.ATTR_VALUE_ELEMENT);
svgFormatForRect.setElementName('rect');
svgFormatForRect.setAttributes(rectObj);

if (svgTagObj) {

  // 为SVG标签添加固定格式的Rect子标签
  this.svgManager.addChildNode(svgTagObj, svgFormatForRect.toObj());
  consoleInfo('Test svg: add svg svgTotalRoot', JSON.stringify(this.svgManager.getSVGTotalObj()));
}

// 获取整个SVG文件对应的对象
let svgTotalObj = this.svgManager.getSVGTotalObj();
let success = function () {
     consoleInfo('saveFile', 'success');
}

// 将SVG文件对象保存为.svg格式文件,文件保存在 /project's path/files中
this.svgManager.saveSVG('svg.svg', svgTotalObj, success);

结果

代码语言:ts复制
add svg svgTotalRoot: {
    "declaration":{
        "attributes":{
            "version":"1.0","encoding":"utf-8","standalone":"yes"

     }

      },"elements":[{
        "type":"element","name":"svg","attributes":{
          "xmlns":"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink"
      },"elements":[{
        "type":"element","name":"rect","attributes":{
    "x":50,"y":50,"rx":20,"ry":20,"width":100,"height":100,"style":"fill:rgb(255,0,255);stroke-width:2;stroke:rgb(0,0,0)"
        }
    }]
  }]
}

2.2 手动创建SVG文件及子标签

代码语言:ts复制
// 清空已存在的SVG根
this.svgXMLRoot = this.svgManager.getSVGTotalObj();
this.svgManager.removeByKey(this.svgXMLRoot, SVGAttrConstants.ATTR_KEY_DECLARATION);
this.svgManager.removeByKey(this.svgXMLRoot, SVGAttrConstants.ATTR_KEY_ELEMENTS);

// 构建SVG标签对应的对象
let svg: SVGRoot = new SVGRoot();
svg.setXMLNS(XMLConstants.XMLNS_NAMESPACE_URI_SVG);
svg.setXMLNSLink(XMLConstants.XLINK_NAMESPACE_URI);
svg.setSvgId('svgRoot');
svg.setXMLSpace(false);
svg.setWidth(250);
svg.setHeight(250);
svg.setViewBox(10, 10, 250, 250);
let svgObj = svg.toObj();

let svgSpecifiedFormat: SVGSpecifiedFormat = new SVGSpecifiedFormat();
svgSpecifiedFormat.setElementType(SVGAttrConstants.ATTR_VALUE_ELEMENT);
svgSpecifiedFormat.setElementName('svg');
svgSpecifiedFormat.setAttributes(svgObj);

// 构建SVG标签内的Rect子标签的对象
let rect: SVGRect = new SVGRect();
rect.setX(50);
rect.setY(50);
rect.setRX(20);
rect.setRY(20);
rect.setWidth(100);
rect.setHeight(100);
rect.addAttribute('style', 'fill:rgb(0,0,255);stroke-width:2;stroke:rgb(0,0,0)')
let rectObj = rect.toObj();

let svgFormatForRect: SVGSpecifiedFormat = new SVGSpecifiedFormat();
svgFormatForRect.setElementType(SVGAttrConstants.ATTR_VALUE_ELEMENT);
svgFormatForRect.setElementName('rect');
svgFormatForRect.setAttributes(rectObj);
svgSpecifiedFormat.setElements(svgFormatForRect.toObj());

if (this.svgXMLRoot) {

  // 构建SVG文件声明
  let declarationAttrs: object = {};
  declarationAttrs['version'] = '1.0';
  declarationAttrs['encoding'] = 'utf-8';
  declarationAttrs['standalone'] = 'no';

  let declarationObj: object = {};
  declarationObj[SVGAttrConstants.ATTR_KEY_ATTRIBUTES] = declarationAttrs

  this.svgXMLRoot[SVGAttrConstants.ATTR_KEY_DECLARATION] = declarationObj;
  this.svgManager.addChildNode(this.svgXMLRoot, svgSpecifiedFormat.toObj());
  consoleInfo('Test svg: add line svgTotalRoot', JSON.stringify(this.svgManager.getSVGTotalObj()));
}

结果

代码语言:ts复制
Test svg: add svg svgTotalRoot: {
  "declaration":{"attributes":{
      "version":"1.0","encoding":"utf-8","standalone":"no"
    }
  },"elements":[{
          "type":"element","name":"svg","attributes":{
    "xmlns":"http://www.w3.org/2000/svg","xmlns:xlink":"http://www.w3.org/1999/xlink","id":"svgRoot","xml:space":"default","width":250,"height":250,"viewBox":{
      "x":10,"y":10,"width":250,"height":250
     }
    },"elements":[{
          "type":"element","name":"rect","attributes":{"x":50,"y":50,"rx":20,"ry":20,"width":100,"height":100,"style":"fill:rgb(0,0,255);stroke-width:2;stroke:rgb(0,0,0)"}
      }]
    }]
}

3. 操作SVG图像对象

3.1 修改已存在的子标签的属性

代码语言:ts复制
// 获取SVG根标签对应的操作对象
let svgRoot = this.svgManager.getSVGRoot();
if (!svgRoot) {
  consoleInfo('Test rect: update attr for rect1', 'svg tag is null');
  return false;
}

// 根据主键获取对应的属性值
let svgElements = this.svgManager.getValueForKey(svgRoot, SVGAttrConstants.ATTR_KEY_ELEMENTS);
if (!svgElements) {
  consoleInfo('Test rect: update attr for rect1', `svg tag's elements is null`);
  return false;
}

if (typeof svgElements !== SVGAttrConstants.TYPEOF_OBJECT || !Array.isArray(svgElements)) {
  consoleInfo('Test rect: update attr for rect1', `the elements's type of svg tag is not array`);
  return;
}

let rectResult = null;
try {
  svgElements.forEach((item) => {
    if (typeof item === SVGAttrConstants.TYPEOF_OBJECT) {
      let nameValue: string = this.svgManager.getValueForKey(item, SVGAttrConstants.ATTR_KEY_NAME);
      if (nameValue === 'rect') {
        rectResult = item;
        throw 'has got rect,jump out';
      }
    }
  })
} catch (e) {
  if (!rectResult) {
    consoleInfo('Test rect: update attr for rect1', 'rect not exist');
    return;
  }

  if (typeof rectResult === SVGAttrConstants.TYPEOF_OBJECT) {
    let rectAttributes = rectResult[SVGAttrConstants.ATTR_KEY_ATTRIBUTES];
    rectAttributes['x'] = 20;
    rectAttributes['y'] = 20;
    rectAttributes['rx'] = 10;
    rectAttributes['ry'] = 50;
    rectAttributes['width'] = 80;
    rectAttributes['height'] = 80;
    
    // 为标签添加/设置属性键值对
    this.svgManager.setAttribute(rectAttributes, 'style', 'fill:rgb(0,255,0);stroke-width:10;stroke:rgb(0,255,255)');
    this.allAttrRectObj = rectResult;
  }
  consoleInfo('Test rect: update attr for rect1 svgTotalObj', JSON.stringify(this.svgManager.getSVGTotalObj()));
}

3.2 移除属性键值对

代码语言:ts复制
let attrs = this.svgManager.getValueForKey(rectOriginData, SVGAttrConstants.ATTR_KEY_ATTRIBUTES);
if (!attrs) {
  consoleInfo('test remove '   firstAttrName, 'rect1 has no attributes');
  return;
}
this.svgManager.removeByKey(attrs, firstAttrName);

4. 解析SVG图像文件

代码语言:ts复制
this.svgManager.parse('svg.svg', (parseXMLResultObj) =>{
	this.svgJson = parseXMLResultObj;
})

结果

代码语言:ts复制
{"declaration":{
      "attributes":{
          "version":"1.0","encoding":"utf-8"
      }
        },"elements":[{

          "type":"element","name":"svg","attributes":{
                "id":"svgRoot","space":"default","width":"250","height":"250","viewBox":"10 10 250 250 "
      },"elements":[{
          "type":"element","name":"rect","attributes":{
      "x":"50","y":"50","rx":"20","ry":"20","width":"100","height":"100","style":"fill:rgb(0,0,255);stroke-width:2;stroke:rgb(0,0,0)"
          }
      }]
      }]
}

接口说明

  1. 获取SVG管理类实例
代码语言:ts复制
   static getInstance(): SVGManager
  1. 获取整个SVG文件对应的可以操作对象
代码语言:ts复制
   getSVGTotalObj(): object
  1. 创建SVG文件声明及SVG根标签
代码语言:ts复制
   createSVGDeclares(): object
  1. 获取SVG根标签对应的可操作对象
代码语言:ts复制
   getSVGRoot(obj: Object = this.svgObj): object
  1. 添加子标签(不覆盖原子标签)
代码语言:ts复制
   addChildNode(parentObj: Object, childPropertyValue: Object): boolean
  1. 设置子标签(覆盖原子标签)
代码语言:ts复制
   setChildNode(parentObj: Object, childPropertyValue: Object): boolean
  1. 通过主键获取对应属性值
代码语言:ts复制
   getValueForKey(parentObj: Object, key: string): any
  1. 根据主键移除键值对
代码语言:ts复制
   removeByKey(parentObj: Object, key: string): void
  1. 为对象设置属性或子节点(覆盖原有键值对)
代码语言:ts复制
   setAttribute(parentObj: Object, key: string, value: string): void
  1. 创建文件夹
代码语言:ts复制
    createFolder(path: string): void 
  1. 获取文件根路径
代码语言:ts复制
    getFilePath(onSuccess: (filesDir: string) => void): void
  1. 保存SVG文件
代码语言:ts复制
    saveSVG(fileName: string, fileContent: string | Object, onSuccess?: () => void, onFailed?: (number, Error) => void): void
  1. 解析SVG文件
代码语言:ts复制
    parse(fileName: string, onSuccess: (result: string) => void, onFailed?: (error: Error) => void): void

约束与限制

在下述版本验证通过:

DevEco Studio: 4.1 Canary(4.1.3.322), SDK: API11 (4.1.0.36)

DevEco Studio: 4.0 (4.0.3.600), SDK: API10 (4.0.10.11)

DevEco Studio: 4.0 (4.0.3.512), SDK: API10 (4.0.10.9)

DevEco Studio: 3.1 Beta2(3.1.0.400), SDK: API9 Release(3.2.11.9)

目录

代码语言:shell复制
/XmlGraphicsBatik       # 工程根目录
├── entry                  # 示例代码文件夹
├── library    # 三方库源码文件夹
│   └── src
│       ├── index.ets      # 对外暴露文件的存放目录
│       ├── package.json   # 项目介绍
│       └──main/ets/batik
│          ├── SVGManager.ets    # SVG处理管理核心类
│          ├── SVGXMLChecker.ets # 检查SVG文本是否合规
│          ├── StringReader.ets  # 读取SVG文本字符串工具类
│          └── constants
│              ├── RegexConstants.ets   # 正则表达式常量类
│              ├── SVGAttrConstants.ets # SVG标准格式主键常量类
│              ├── SVGXMLConstants.ets  # SVG文件常量类
│              └── XMLConstants.ets     # XML文件常量类
│          └── svggen
│              ├── SVGSpecifiedFormat.ets  # SVG文件对应的可操作对象标准格式构造类
│              ├── SVGDeclares.ets         # SVG文件声明构造类 
│              ├── SVGRoot.ets             # SVG文件根标签构造类
│              ├── SVGCircle.ets           # Ciecle子标签构造类
│              ├── SVGEllipse.ets          # Ellipse子标签构造类
│              ├── SVGLine.ets             # Line子标签构造类
│              ├── SVGPath.ets             # Path子标签构造类
│              ├── SVGRect.ets             # Rect子标签构造类
│              └── SVGPolygonAndPolyLine.ets # Polygon 及 PolyLine子标签构造类
│          └── tools
│              ├── DeleteProperty.ts            # Delete工具函数
│              ├── GetKeysTest.ts               # GetKeysDelete工具函数 
│              ├── GlobalContext.ets            # GlobalContext构造类
│              ├── IsArrayFunction.ts           # IsArray工具函数
│              ├── MakePropertiesImmutable.ts   # 冻结对象工具函数
│              ├── ObjCreate.ts                 # 创建空对象工具函数
│              └── StringToHex.ts               # 字符串转不同进制工具函数
│          └── util
│              ├── LogUtil.ets         # 日志打印工具类
│              ├── ObjOrArrayUtil.ets  # 可操作对象及Array处理工具类
│              └── XMLRules.ets        # XML文件固定规则工具类

写在最后

如果你觉得这篇内容对你还蛮有帮助,我想邀请你帮我三个小忙: