SVG对骑手端weex绘图功能扩展实践
Posted 点我达技术团队
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SVG对骑手端weex绘图功能扩展实践相关的知识,希望对你有一定的参考价值。
前言
公司采用weex对骑手工程改造已经有3个多月了,随着骑手工程中weex页面比例不断增大,对weex来实现复杂UI的需求也越来越强烈,插件市场的插件长期没人维护,开发者苦不堪言,我们对此进行了探索,出于对android,ios,web兼容的考虑,我们选择了svg技术对weex进行插件扩展的研究,希望能帮助到正在使用weex开发的小伙伴们少走些弯路。
1.SVG简介
1.1 什么是SVG?
SVG指可伸缩矢量图形(Scalable Vector Graphics)
SVG用来定义用于网络的基于矢量的图形;
SVG使用xml格式定义图形;
SVG图像在放大或改变尺寸的情况下其图形质量不会有所损失;
SVG是万维网联盟的标准;
SVG与诸如DOM和XSL之类的W3C标准是一个整体(于2003年1月14日成为W3C推荐标准)。
1.2 SVG工作流?
1.3 为什么选择SVG?
SVG是基于XML与html语义一样,具有很好的交互性,图像文件可读,易于修改和编辑。
目前主流的平台及android,iOS,web都有比较好的支持。
1.4 SVG优势
可通过文本编辑器来创建和修改
图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
SVG可在任何的分辨率下被高质量的打印
可在图片质量不下降的情况下被放大
SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强。
支持事件绑定
SVG 可以与 Java 技术一起运行
SVG 是开放的标准
SVG 文件是纯粹的 XML
1.5 SVG实例
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="100%" height="100%" version="1.1"
xmlns="http://www.w3.org/2000/svg">
</svg>
<circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
</svg>
1.6 SVG预定义的形状元素
矩形
<rect>
圆形
<circle>
椭圆
<ellipse>
线
<line>
折线
<polyline>
多边形
<polygon>
路径
<path>
2. Weex 插件扩展(有相关经验的小伙伴可忽略)
2.1 weex-iOS插件扩展方式介绍
iOS组件 Component
扩展步骤
iOS端 *1.创建自定义的组件继承WXComponent类 *2.重写- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance方法 *3.现实自定义的UI样式 *4.支持js方法在特殊的状态调用重写addEvent和removeEvent方法,在需要的位置调用fireEvent方法执行对应的js方法 *5.支持js调模块扩展出来的方法,编写扩展方法WXEXPORTMETHOD(@selector(method))扩展 *6.使用WXSDKEngine的+registerComponent:withClass:去注册 js端 1.直接在需要该组件的template中使用 2.如果组件需要传递参数,则可以通过:key=value的形式传递,方法@methodName=JSmethod,实现js方法 3.调用扩展方法:this.$refs.refName.methodName
iOS模块 Module
扩展步骤
iOS端 *1.创建自定义的模块实现
协议 *2.实现自定义的功能并callback回调给js *3.使用WX EXPORTMETHOD或WX EXPORTMETHOD_SYNC来抛出native方法给js *4.使用WXSDKEngine的+registerModule:withClass:去注册 js端 1.直接在需要该组件的script中使用weex.requireModule()获得已注册的模块 2.在需要的位置调用注册的方法
2.2 weex-android插件扩展方式介绍
android组件 Component
扩展步骤
android端 *1.创建自定义的组件继承WXComponent/WXVContainer类 *2.使用initComponentHostView(context)初始化,initView()方法已过时 *3.现实自定义的UI样式, 通过添加注解@WXComponentProp设置属性 *4.使用instance.fireEvent()方法执行对应的js方法 *5.支持js调模块扩展出来的方法,编写扩展方法@JSMethod(uiThread = false或true)扩展 *6.使用WXSDKEngine的WXSDKEngine.registerComponent()去注册 js端 1.直接在需要该组件的template中使用 2.如果组件需要传递参数,则可以通过:key=value的形式传递,方法@methodName=JSmethod,实现js方法 3.调用扩展方法:this.$refs.refName.methodName
android模块 Module
扩展步骤
android端 *1.创建自定义的模块继承WXModule *2.实现自定义的功能并callback回调给js *3.使用@JSMethod(uiThread = false或true)将自定义的方法抛给js *4.使用WXSDKEngine的WXSDKEngine.registerModule()去注册 js端 1.直接在需要该组件的script中使用weex.requireModule()获得已注册的模块 2.在需要的位置调用注册的方法
2.3 weex-web插件扩展方式介绍
web组件 Component
扩展步骤
js端 1.使用npm install加载weex-vue-render组件 2.使用Weex.registerComponent('name', component); 注册组件 3.在webpack.config中使用weex.install(components)加载所有组件 4.调用扩展方法:
web组件 Module
扩展步骤
js端
使用npm install加载weex-vue-render组件
使用Weex.registerModule('name', module)
在webpack.config中使用weex.install(modules)加载所有组件 4.调用扩展方法:const moduleName = weex.requireModule('ModuleName'); 调用模块方法moduleName.xx()
3.Weex 交互(有相关经验的小伙伴可忽略)
3.1 Weex-web和native交互(iOS使用WKWebView,android使用WebView)
Weex-web端
1.Weex-web调用native提供的方法: iOS:webkit.messageHandlers.weexCallHandler.postMessage(data) android:window.dianwoda.weexCallHandler(data); 2.解决方案:使用callHandler的调用方式来实现 参数: a. name:调用native的方法名,即约定的具体需要调用native的什么方法,例:setHeaderTitle(设置header的title) b. params:传给native端的参数,例:{'title': '这是商品详情页的标题'} c. onSuccess:调用native方法成功后的回调方法名 d. onFail:调用native的方法名,即约定的具体需要调用native的什么方法,例:setHeaderTitle(设置header的title) 3.问题:由webpack打包生成的Weex-web的vuejs文件的methods方法不在window下native无法调用到, 解决方案:将方法绑到window下面
iOS端
1.iOS调用Weex-web的方法回传数据:[webView evaluatejavascript:jsStr completionHandler:^(id _Nullable d, NSError * _Nullable error) {}];
android端
1.android调用Weex-web的方法回传数据:通过getSettings()获得WebSettings,然后用setJavaScriptEnabled()调用Js
3.2 Weex和iOS交互
1.Weex调用iOS的方法
方式1:通过iOS注册的Module方式来抛出方法供weex调用
2.iOS调用weex的方法
方式1:拿到weex页面的instanceId通过fireEvent方法调用weex方法 如:[[WXSDKManager bridgeMgr] fireEvent:weexInstance.instanceId ref:WXSDKROOT_REF type:type params:params domChanges:nil]; 方式2:在组件中使用fireEvent方法来调用weex方法 方式3:使用fireGlobalEvent来通知调用weex方法
注:fireEvent方式是通过JSContext实现,fireGlobalEvent是通过通知实现
3.3 Weex和android交互
1.Weex调用android的方法
方式1:通过android注册的Module方式来抛出方法供weex调用
2.android调用weex的方法
方式1:拿到weex页面的instance通过fireEvent(getRef(), numClick, data, null);方法来调用weex方法 方式2:使用fireGlobalEvent来广播调用weex方法
注:fireEvent方式是通过webView调用js实现,fireGlobalEvent是通过广播实现
4.Weex SVG实践
4.1 Weex-web SVG扩展
SVG可在Weex-web上直接使用:
例如:使用 <path>
绘制一段弧形
<svg>
<path d="M 0,304 C 0,304 375,270 750,0" stroke-width="4" stroke="#3A3A41" fill="#42424F" />
</svg>
代码解释: path> 标签用来定义路径。 下面的命令可用于路径数据: M = moveto L = lineto H = horizontal lineto V = vertical lineto C = curveto S = smooth curveto Q = quadratic Belzier curve T = smooth quadratic Belzier curveto A = elliptical Arc Z = closepath 注释:以上所有命令均允许小写字母。大写表示绝对定位,小写表示相对定位。
4.2 Weex-iOS SVG扩展
思路:根据svg api规范在iOS端通过 Core Graphics库来实现一套iOS-svg标准的组件库,并通过weex Component的方式把这个组件库暴露给weex使用。
4.2.1.使用Core Graphics来定义符合svg api规范的各种view,如线,圆形,矩形等等。
Core Graphics的使用介绍 这是一个绘图专用的API族,它经常被称为QuartZ或QuartZ 2D。Core Graphics是iOS上所有绘图功能的基石,包括UIKit。
基本概念:
1.绘图需要 CGContextRef
CGContextRef即图形上下文。可以这么理解,我们绘图是需要一个载体或者说输出目标,它用来显示绘图信息,并且决定绘制的东西输出到哪个地方。
2.怎么拿到context?
第一种方法是利用cocoa为你生成的图形上下文。 第二种方法就是创建一个图片类型的上下文
Core Graphics的使用步骤:
1.先在drawRect方法中获得上下文context; 2.绘制图形(线,图形,图片等); 3.设置一些修饰属性; 4.渲染到上下文,完成绘图。
代码:
- (void)drawRect:(CGRect)rect
{
// 1.获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// --------------------------实心圆
// 2.画图
CGContextAddEllipseInRect(ctx, CGRectMake(10, 10, 50, 50));
[[UIColor greenColor] set];
// 3.渲染
CGContextFillPath(ctx);
}
4.2.2.将使用Core Graphics来定义符合svg api规范的各种view通过Component扩展给weex。
例如:给weex扩展划线的api 1.使用Core Graphics定义一条线
@implementation WXSVGLine
....
- (CGPathRef)getPath:(CGContextRef)context
{
[self setBoundingBox:CGContextGetClipBoundingBox(context)];
CGMutablePathRef path = CGPathCreateMutable();
CGFloat x1 = self.x1;
CGFloat y1 = self.y1;
CGFloat x2 = self.x2;
CGFloat y2 = self.y2;
CGPathMoveToPoint(path, nil, x1, y1);
CGPathAddLineToPoint(path, nil, x2, y2);
return (CGPathRef)CFAutorelease(path);
}
.....
@end
2.通过Component把线扩展给weex使用
@implementation WXSVGLineComponent
.....
- (WXSVGRenderable *)node
{
WXSVGLine *lineView = [WXSVGLine new];
lineView.x1 = [WXConvert WXPixelType:_x1 scaleFactor:self.weexInstance.pixelScaleFactor];
lineView.y1 = [WXConvert WXPixelType:_y1 scaleFactor:self.weexInstance.pixelScaleFactor];
.....
return lineView;
}
- (void)updateAttributes:(NSDictionary *)attributes
{
WXSVGLine *lineView = (WXSVGLine *)self.view;
if (attributes[@"x1"]) {
_x1 = attributes[@"x1"];
lineView.x1 = [WXConvert WXPixelType:_x1 scaleFactor:self.weexInstance.pixelScaleFactor];
}
.....
[super updateAttributes:attributes];
}
@end
4.3 Weex-android SVG扩展
思路:根据svg api规范在android端通过 graphics库来实现一套android-svg标准的组件库,并通过weex Component的方式把这个组件库暴露给weex使用。
4.3.1.使用graphics来定义符合svg api规范的各种view,如线,圆形,矩形等等。
Android画图--同样有三个基本对象:Color,Paint,Canvas 它们都位于android.graphics画图包下面。 1.Canvas : 画布对象,相当于现实生活中画图用的画纸或者画布 2.Paint : 画笔对象,相当于现实生活中画图用的 笔。对画笔的一些参数设置是很重要的。 3.Color: 颜色对象,相当于现实生活中的 调料
4.3.2.将使用android.graphics来定义符合svg api规范的各种view通过Component扩展给weex。
例如:给weex扩展划线的api 1.使用android.graphics定义一条线
public class WXSvgLine extends WXSvgPath {
.....
@Override
public void draw(Canvas canvas, Paint paint, float opacity) {
mPath = getPath(canvas, paint);
super.draw(canvas, paint, opacity);
}
@Override
protected Path getPath(Canvas canvas, Paint paint) {
Path path = new Path();
float x1 = ParserHelper.fromPercentageToFloat(mX1, mCanvasWidth, 0, mScale);
float y1 = ParserHelper.fromPercentageToFloat(mY1, mCanvasHeight, 0, mScale);
....
path.moveTo(x1, y1);
path.lineTo(x2, y2);
return path;
}
public static class Creator implements ComponentCreator {
public Creator() {
}
public WXComponent createInstance(WXSDKInstance instance, WXDomObject node, WXVContainer parent) throws IllegalAccessException, InvocationTargetException, InstantiationException {
return new WXSvgLine(instance, node, parent);
}
}
}
5.SVG编辑工具介绍
5.1 SVGSUS
SVGSUS功能特色:
支持导入 SVG 图标包,管理方便
可直接把图标拖至 AI/PS/SKETCH 等工具上使用
图标搜索功能
可输出不同终端用的 SVG 代码(如:Web/Android/iOS)
下面我们来看看这个 svgsus 工具的使用体验。
导入图标包
使用图标,用户可以很方便的从软件把图标拖到 AI、PS、Sketch 等设计工具上直接使用。
转换为 SVG 图标代码
svgsus 工具可以转换种代码格式,包括:Web, iOS, OS X, Android 等。使用方法也超简单: 方法1:单击你需要用的图标,然后在编辑器上 Ctrl + V 即可粘贴代码。 方法2:直接拖动图标到编辑器 方法3:这个有点帅,直接在拖动图标时,经过 svgsus 界面,再拖入编辑器里,就可以生成代码了,请看帅气的 DEMO 吧!
从AI、Sketch 设计软件中输出 SVG 图标
首先在 AI 或 Sketch 里复制你要输出的图标,然后在 svgsus 上粘贴一下,最后,在文件夹里粘贴一下,完成!请看帅气的 DEMO 吧!
以上是关于SVG对骑手端weex绘图功能扩展实践的主要内容,如果未能解决你的问题,请参考以下文章