# XmlGraphicsBatikETS **Repository Path**: xiaocui202208/XmlGraphicsBatikETS ## Basic Information - **Project Name**: XmlGraphicsBatikETS - **Description**: No description available - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 12 - **Created**: 2022-08-08 - **Last Updated**: 2022-08-08 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # XmlGraphicsBatikETS # 简介 XmlGraphicsBatikETS项目用于处理可缩放矢量图形(SVG)格式的图像,例如显示、生成、解析或者操作图像。 支持SVG图像的显示,可显示静态及动态SVG图像; 支持快捷生成SVG图像文件; 支持操作SVG图像进行颜色、样式、内容的修改; 支持将SVG图像的xml文本解析为可操作对象。 # 下载安装 ``` npm install @ohos/XmlGraphicsBatikETS --save ``` OpenHarmony npm 环境配置等更多内容,请参考 [如何安装OpenHarmony npm包](https://gitee.com/openharmony-tpc/docs/blob/master/OpenHarmony_npm_usage.md) 。 # 使用说明 对SVG图像进行生成、操作、解析等操作均依赖于SVGManager管理类 ``` import {SVGManager} from '@ohos/XmlGraphicsBatikETS'; private svgManager: SVGManager = SVGManager.getInstance(); ``` ## 1. 显示SVG图像 ``` // Iamge组件支持显示media资源文件 及 工程目录中的SVG图片 Image($r('app.media.svgSample')) .width(150) .height(150) // this.filePath 工程目录路径:/data/storage/el2/base/haps/entry/files Image('file://' + this.filePath + '/svg.svg') .width(150) .height(150) ``` ## 2. 生成SVG图像文件 2.1 创建SVG文件声明及子标签 ``` // 创建SVG 对象:声明及SVG标签 this.svgManager.createSVGDeclares(); // 获取SVG标签对应的对象 var svgTagObj = this.svgManager.getSVGRoot(); // 构建SVG中的rect节点 var 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对象 var rectObj = rect.toObj(); // 构建固定格式的节点描述对象 var 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文件对应的对象 var svgTotalObj = this.svgManager.getSVGTotalObj(); var success = function () { consoleInfo('saveFile', 'success'); } // 将SVG文件对象保存为.svg格式文件,文件保存在 /project's path/files中 this.svgManager.saveSVG('svg.svg', svgTotalObj, success); ``` 结果 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文件及子标签 ``` // 清空已存在的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标签对应的对象 var 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); var svgObj = svg.toObj(); var svgSpecifiedFormat: SVGSpecifiedFormat = new SVGSpecifiedFormat(); svgSpecifiedFormat.setElementType(SVGAttrConstants.ATTR_VALUE_ELEMENT); svgSpecifiedFormat.setElementName('svg'); svgSpecifiedFormat.setAttributes(svgObj); // 构建SVG标签内的Rect子标签的对象 var 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)') var rectObj = rect.toObj(); var svgFormatForRect: SVGSpecifiedFormat = new SVGSpecifiedFormat(); svgFormatForRect.setElementType(SVGAttrConstants.ATTR_VALUE_ELEMENT); svgFormatForRect.setElementName('rect'); svgFormatForRect.setAttributes(rectObj); svgSpecifiedFormat.setElements(svgFormatForRect.toObj()); if (this.svgXMLRoot) { // 构建SVG文件声明 var declarationAttrs: object = Object.create(null); declarationAttrs['version'] = '1.0'; declarationAttrs['encoding'] = 'utf-8'; declarationAttrs['standalone'] = 'no'; var declarationObj: object = Object.create(null); 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())); } ``` 结果 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 修改已存在的子标签的属性 ``` // 获取SVG根标签对应的操作对象 var svgRoot = this.svgManager.getSVGRoot(); if (!svgRoot) { consoleInfo('Test rect: update attr for rect1', 'svg tag is null'); return false; } // 根据主键获取对应的属性值 var 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; } var rectResult = null; try { svgElements.forEach((item) => { if (typeof item === SVGAttrConstants.TYPEOF_OBJECT) { var 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) { var 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 移除属性键值对 ``` var 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图像文件 ``` this.svgManager.parse('svg.svg', (parseXMLResultObj) =>{ this.svgJson = parseXMLResultObj; }) ``` 结果 {"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管理类实例 ``` static getInstance(): SVGManager ``` 2. 获取整个SVG文件对应的可以操作对象 ``` getSVGTotalObj(): object ``` 3. 创建SVG文件声明及SVG根标签 ``` createSVGDeclares(): object ``` 4. 获取SVG根标签对应的可操作对象 ``` getSVGRoot(obj: Object = this.svgObj): object ``` 5. 添加子标签(不覆盖原子标签) ``` addChildNode(parentObj: Object, childPropertyValue: Object): boolean ``` 6. 设置子标签(覆盖原子标签) ``` setChildNode(parentObj: Object, childPropertyValue: Object): boolean ``` 7. 通过主键获取对应属性值 ``` getValueForKey(parentObj: Object, key: string): any ``` 8. 根据主键移除键值对 ``` removeByKey(parentObj: Object, key: string): void ``` 9. 为对象设置属性或子节点(覆盖原有键值对) ``` setAttribute(parentObj: Object, key: string, value: string): void ``` 10. 创建文件夹 ``` createFolder(path: string): void ``` 11. 获取文件根路径 ``` getFilePath(onSuccess: Function): void ``` 12. 保存SVG文件 ``` saveSVG(fileName: string, fileContent: string | Object, onSuccess?: Function, onFailed?: Function): void ``` 13. 解析SVG文件 ``` parse(fileName: string, onSuccess: Function, onFailed?: Function): void ``` # 兼容性 支持 OpenHarmony API version 9 及以上版本。 # 目录 ``` /XmlGraphicsBatikETS # 工程根目录 ├── entry # 示例代码文件夹 ├── XmlGraphicsBatikETS # 三方库源码文件夹 │ └── 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子标签构造类 │ └── util │ ├── LogUtil.ets # 日志打印工具类 │ ├── ObjOrArrayUtil.ets # 可操作对象及Array处理工具类 │ └── XMLRules.ets # XML文件固定规则工具类 ``` # 贡献代码 使用过程中发现任何问题都可以提 [Issue](https://gitee.com/openharmony-tpc/XmlGraphicsBatikETS/issues) 给我们,当然,我们也非常欢迎你给我们发 [PR](https://gitee.com/openharmony-tpc/XmlGraphicsBatikETS/pulls) 。 # 开源协议 本项目基于 [Apache License 2.0](https://gitee.com/openharmony-tpc/XmlGraphicsBatikETS/blob/master/LICENSE) 协议,请自由地享受和参与开源。