XmlGraphicsBatik项目用于处理可缩放矢量图形(SVG)格式的图像,例如显示、生成、解析或者操作图像。
支持SVG图像的显示,可显示静态及动态SVG图像;
支持快捷生成SVG图像文件;
支持操作SVG图像进行颜色、样式、内容的修改;
支持将SVG图像的xml文本解析为可操作对象。
ohpm install @ohos/xmlgraphicsbatik
OpenHarmony ohpm 环境配置等更多内容,请参考如何安装 OpenHarmony ohpm 包
对SVG图像进行生成、操作、解析等操作均依赖于SVGManager管理类
使用本库需要预先在MainAbility.ts 中预制文件路径: GlobalContext.getContext().setObject(“filesDir”, this.context.filesDir);
import {SVGManager} from '@ohos/XmlGraphicsBatik';
private svgManager: SVGManager = SVGManager.getInstance();
// Iamge组件支持显示media资源文件 及 工程目录中的SVG图片
Image($r('app.media.svgSample'))
.width(150)
.height(150)
Image('file://' + this.filePath + '/svg.svg')
.width(150)
.height(150)
2.1 创建SVG文件声明及子标签
// 创建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);
结果
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标签对应的对象
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()));
}
结果
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.1 修改已存在的子标签的属性
// 获取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 移除属性键值对
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);
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)"
}
}]
}]
}
static getInstance(): SVGManager
getSVGTotalObj(): object
createSVGDeclares(): object
getSVGRoot(obj: Object = this.svgObj): object
addChildNode(parentObj: Object, childPropertyValue: Object): boolean
setChildNode(parentObj: Object, childPropertyValue: Object): boolean
getValueForKey(parentObj: Object, key: string): any
removeByKey(parentObj: Object, key: string): void
setAttribute(parentObj: Object, key: string, value: string): void
createFolder(path: string): void
getFilePath(onSuccess: (filesDir: string) => void): void
saveSVG(fileName: string, fileContent: string | Object, onSuccess?: () => void, onFailed?: (number, Error) => void): void
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)
/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文件固定规则工具类
为了能让大家更好的学习鸿蒙(HarmonyOS NEXT)开发技术,这边特意整理了《鸿蒙开发学习手册》(共计890页),希望对大家有所帮助:https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr21.cn/FV7h05
https://qr18.cn/F781PH
https://qr18.cn/F781PH
1.项目开发必备面试题
2.性能优化方向
3.架构方向
4.鸿蒙开发系统底层方向
5.鸿蒙音视频开发方向
6.鸿蒙车载开发方向
7.鸿蒙南向开发方向