svg在android上的应用

2017-10-09  本文已影响0人  zhnd

背景

SVG:可缩放矢量图形(Scalable Vector Graphics),基于可扩展标记语言(XML),是W3C("World Wide Web ConSortium",国际互联网标准组织)在2000年8月制定的一种新的二维矢量图形格式,于2003年1月14日成为W3C推荐标准。

矢量图特点:
优点
(1)文件小;
(2)图像元素对象可编辑;
(3)图像放大或缩小不影响图像的分辨率;
(4)图像的分辨率不依赖于输出设备;
(5)线条非常顺滑并且是同样粗细的;
(6)颜色的边缘是非常顺滑的。
缺点
(1)重画图像困难;
(2)真实照片逼真度低,要画出自然度高的图像需要很多的技巧;
(3)无法产生色彩艳丽、复杂多变的图像;
(4)矢量图仿图绘制做卡通的相似度97%以上,3%是清晰美化的。

SVG优势:
SVG 可被非常多的工具读取和修改(比如记事本)
SVG 与 JPEG 和 GIF 图像比起来,尺寸更小,且可压缩性更强
SVG 是可伸缩的
SVG 图像可在任何的分辨率下被高质量地打印
SVG 可在图像质量不下降的情况下被放大
SVG 图像中的文本是可选的,同时也是可搜索的(很适合制作地图)
SVG 可以与 Java 技术一起运行
SVG 是开放的标准
SVG 文件是纯粹的 XML

矢量图很适合用于记录诸如符号、图标等简单的图形。而位图则适合于没有明显规律的、颜色丰富细腻的图片。

Android微信上的SVG

SVG教程jpg,png图片在线转svgsvgeditor

应用

1、android svg

在Android 5.X之后,Android中添加了对SVG的path标签的支持。

示例

svg.xml

<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="100dp"
    android:height="100dp"
    android:viewportHeight="100"
    android:viewportWidth="100">

    <group>
        <path
            android:name="path3"
            android:pathData="
            M 0,0
            L 100,0
              100,100
            "
            android:strokeColor="#222222"
            android:strokeLineCap="round"
            android:strokeWidth="1" />
    </group>

</vector>

anim_path3.xml

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000"
    android:propertyName="pathData"
    android:repeatCount="infinite"
    android:repeatMode="reverse"
    android:valueFrom="
            M 0,0
            L 100,0
              100,100
            "
    android:valueTo="
            M 0,0
            L 0,100
              100,100
            "
    android:valueType="pathType" />

anim_svg.xml

<?xml version="1.0" encoding="utf-8"?>
<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/svg">

    <target
        android:name="path3"
        android:animation="@animator/anim_path3" />

</animated-vector>
path标签
M = moveto(M X,Y):将画笔移动到指定的坐标位置,但未发生绘制

L = lineto(L X,Y):画直线到指定的坐标位置

H = horizontal lineto(H X):画水平线到指定的X轴坐标

V = vertical lineto(V Y):画垂直线到指定的Y轴坐标

C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝塞曲线

S = smooth curveto(S X2,Y2,ENDX,ENDY):三次贝塞曲线

Q = quadratic Belzier curveto(Q X,Y,ENDX,ENDY):二次贝塞曲线

T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射前面路径后的终点

A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线

Z = closepath():关闭路径

2、glide

glide-svgGlide从v3迁移到v4
glide库支持加载本地或网络的svg图片。

示例
RequestBuilder<PictureDrawable> requestBuilder = GlideApp.with(this)
                .as(PictureDrawable.class)
                .transition(withCrossFade())
                .listener(new SvgSoftwareLayerSetter());
requestBuilder.load("http://www.webhek.com/wordpress/wp-content/uploads/2014/05/kiwi.svg").into(viewImage1);
requestBuilder.load(R.raw.spiral).into(viewImage2);

使用下面这种方式同样可以加载svg图片,不过显示没有上面那种方式清晰。

Glide.with(this).load("http://www.webhek.com/wordpress/wp-content/uploads/2014/05/kiwi.svg").into(viewImage3);
Glide.with(this).load(R.raw.spiral).into(viewImage4);

对比如下图:


IMG_20171009_140905.jpg

通过查看代码,可以看到glide用到了androidsvg库。

import com.caverock.androidsvg.SVG;
20171009114721.png
androidsvg:GitHub官网
SVGParser.class
private static final String TAG_SVG = "svg";
private static final String TAG_A = "a";
private static final String TAG_CIRCLE = "circle";
private static final String TAG_CLIPPATH = "clipPath";
private static final String TAG_DEFS = "defs";
private static final String TAG_DESC = "desc";
private static final String TAG_ELLIPSE = "ellipse";
private static final String TAG_G = "g";
private static final String TAG_IMAGE = "image";
private static final String TAG_LINE = "line";
private static final String TAG_LINEARGRADIENT = "linearGradient";
private static final String TAG_MARKER = "marker";
private static final String TAG_MASK = "mask";
private static final String TAG_PATH = "path";
private static final String TAG_PATTERN = "pattern";
private static final String TAG_POLYGON = "polygon";
private static final String TAG_POLYLINE = "polyline";
private static final String TAG_RADIALGRADIENT = "radialGradient";
private static final String TAG_RECT = "rect";
private static final String TAG_SOLIDCOLOR = "solidColor";
private static final String TAG_STOP = "stop";
private static final String TAG_STYLE = "style";
private static final String TAG_SWITCH = "switch";
private static final String TAG_SYMBOL = "symbol";
private static final String TAG_TEXT = "text";
private static final String TAG_TEXTPATH = "textPath";
private static final String TAG_TITLE = "title";
private static final String TAG_TREF = "tref";
private static final String TAG_TSPAN = "tspan";
private static final String TAG_USE = "use";
private static final String TAG_VIEW = "view";

这个库支持的svg标签。

3、android-pathview

android-pathview
通过android-pathview库可以实现svg动画效果。

示例
viewPath.setSvgResource(R.raw.monitor);
viewPath.useNaturalColors();
viewPath.setFillAfter(true);
viewPath.getPathAnimator()
        .delay(100)
        .duration(1000)
        .interpolator(new AccelerateDecelerateInterpolator())
        .start();

PathView.java

/**
 * Set the svg resource id.
 *
 * @param svgResource - The resource id of the raw svg.
 */
public void setSvgResource(int svgResource) {
    svgResourceId = svgResource;
}

这里的setSvgResource只支持通过资源id加载,如果你需要用到其他的加载方式,比如assets、流等,那么你需要修改这个库,因为它也用到了上面提到的androidsvg库,后者是支持多种方式的。
SVG.class

public static SVG getFromInputStream(InputStream is) throws SVGParseException {
    SVGParser parser = new SVGParser();
    return parser.parse(is);
}

public static SVG getFromString(String svg) throws SVGParseException {
    SVGParser parser = new SVGParser();
    return parser.parse(new ByteArrayInputStream(svg.getBytes()));
}

public static SVG getFromResource(Context context, int resourceId) throws SVGParseException {
    return getFromResource(context.getResources(), resourceId);
}

public static SVG getFromResource(Resources resources, int resourceId) throws SVGParseException {
    SVGParser parser = new SVGParser();
    return parser.parse(resources.openRawResource(resourceId));
}

public static SVG getFromAsset(AssetManager assetManager, String filename) throws SVGParseException, IOException {
    SVGParser parser = new SVGParser();
    InputStream is = assetManager.open(filename);
    SVG svg = parser.parse(is);
    is.close();
    return svg;
}

所以如果要对这个库进行修改,你应该导入这个库模块。
build.gradle

//compile 'com.eftimoff:android-pathview:1.0.8@aar'
compile project(':android-pathview')

settings.gradle

include ':android-pathview'
20171009154547.png

查看代码可以知道,这个库做的工作实际就是将svg图片的path解析成android的path,然后绘制出来,实现动画效果。

关于动态加载

可以通过下载svg图片,然后以流的方式读取,完成加载。

参考资料

Android动画机制与使用技巧(五)——Android 5.X SVG 矢量动画机制
Android实现炫酷SVG动画效果

上一篇下一篇

猜你喜欢

热点阅读