前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >聊聊有关SVG那些事儿

聊聊有关SVG那些事儿

作者头像
贺biubiu
发布2019-06-11 13:16:13
1.3K0
发布2019-06-11 13:16:13
举报
文章被收录于专栏:HLQ_Struggle

前言

前几天,老伙计推送微信的一篇文章,文章标题为:【Android微信上的SVG】,正好LZ借此机会学习了解下有关SVG的相关内容。

微信文章阅读后感

首先,微信提出了几个论点:

  • “清晰”和“体积”的矛盾与麻烦 面对android的各种dpi某事,想要所有设备上的图片都能有最清晰的效果,就意味着每种dpi模式都必须提供一份对应尺寸的资源,除非你不在乎安装包的体积有多大,所以这显然是不可能去做的。(想要清晰,每种dpi都需要放置对应的图片,相应的缺点就是造成Apk会随着图片越来越多而越来越大)在过去的几年里andorid从mdpi发展到xxxhdpi,每当微信想让相同的图片在更清晰的屏幕上显示我们想要的效果时,我们总要重新提供一份体积更大的高清png并且删掉可能不太多使用的小分辨率图片。(android从m发展到xxx,想要适配,而且Apk要尽可能小,只能兼容主流大的,舍弃使用频率小的)只保留一种分辨率图片的方法确实比所有dpi都来一份体积要小一点,然后只是用一份资源还需要承担的负面效果则是当向其他dpi模式scale时,图片也会变得模糊,并且你还要决定自己什么时候该更换上更大分辨率的图片了。(保留一种图片,Apk大小确实减小了,相对应的兼容性却大大降低,这时候,就主要考虑兼容性的问题)
  • 矢量图SVG 栅格图自身特点导致了高清资源同安装包体积之间的矛盾。这方面矢量图存在明显的优势,它可以在表达清晰图片的同时,不增加文件体积。而且只要你不重新设计图片,就用不着再去适配高dpi模式,矢量图什么分辨率都可以自适应。(矢量图SVG,在表达清晰图片的同时还不增加文件体积,并且兼容所有分辨率)我们认为SVG是比较合适的矢量化资源方案,因为它相比目前android上的一些矢量化方案更成熟、周边工具支持更好。像VectorDrawable、ttf这样的方案总有这不尽人意的地方,对于UI同学来说这两个模式也不太好操作,不能轻易生成的资源会牺牲大家的工作效率是明显得不偿失的。(另外,VectorDrawable经过我们测试发现性能并不理想,这受限于他的实现方法。)(SVG是比较合适的矢量化资源方案,相对来说方案更成熟、周边工具支持更好)

而微信上的SVG亟需解决的俩个问题如下:

  • 性能问题 理论上讲,SVG的效率可能会不如PNG好,这是因为它需要运行时的计算和对应平台的渲染绘制。而且对于PNG来说的另一优势是在开启硬件加速的设备上,绘制Bitmap一个非常快速的过程。可以想象,让SVG不比PNG慢将是一件很有挑战的事情。(SVG对CPU的挑战比较大,不过对于现在的手机来说,这点问题属于小意思了)
  • 开发者的使用成本问题 SVG并不是android支持的标准资源格式,android资源框架自然不可能天然支持SVG的资源加载,而修改框架和提供支持很可能意味着会增加后面使用SVG的开发同学的学习成本和使用成本。因此必须要考虑如何即可以用SVG但又不增加开发负担

让我们一起来见证下,经过微信团队的优化后,真实有效的数据吧!

  • 清晰度

两张xxhdpi资源在OPPO R7Plus上的显示结果。左边SVG,右边PNG。

  • 体积 在之前的一次灰度中我们替换了130个资源,这使得最终体积减小了211KB,平均每个减小1.6KB。后面微信会将所有可以矢量化的资源全部替换成SVG,预计这将减小大约1.5MB左右的体积,对比目前压缩后全部约7MB的png,这是个不小的节约。
  • 性能

SVG在加载的过程中得到非常大优势,而Draw的时候因为没有硬件渲染导致性能远不如PNG。但通过在加载阶段的大幅提升,让SVG在整体耗时上赢了PNG。

而关于以上,微信提出了如下:

  • 为什么我们可以将“加载”和“渲染”相加在一起来比较?

事实上,SVG渲染过程使用了Picture进行绘制。Picture并不支持硬件加速,因此必须要将View的LayerType设为Software,而这个操作的意义就是为View创建了一个Bitmap将Picture绘制其上,同时缓存起来。所以,我们可以将“加载”和“渲染”放在一起进行比较,就是因为只有第一次的加载和渲染上我们同PNG是不同的。在这之后,一旦创建好了SoftwareLayer用的Bitmap,绘制过程就同PNG图片一样,可以用硬件渲染来画Bitmap了。

所以,我们得到了比PNG快上70%的SVG矢量化资源

而相对应的优点背后,也存在着不可避免的牺牲:

由于我们实现方式的原因,启动进程时每个SVG将额外消耗掉280us左右的时间。大概就是当我们替换完1000个资源后,我们的启动时间可能会增加280ms。

这样做是有原因的,一方面是因为我们必须这么做来实现框架的无感知,另外也是为了使SVG的整体效率更高(因为生成了一些代码使得后面通过ResourceID免除了反射查找一些类的时间)。而事实上即便我们把这个时间加回到每次加载平均值中,SVG也依旧领先于PNG的整体耗时。

好了,有关微信官方讲述的内容介(kao)绍(bei)到此结束,下面,我们将从概念、过程以及使用的方面去讲解说明有关SVG的基本操作流。

Hi,SVG

可能上面微信介绍大家有点懵,没关系,LZ也是一样懵,我们只需要了解如下几点即可:

  1. SVG的优势相比PNG,SVG有着更好的兼容性以及相比使用PNG,SVG体积更小;
  2. SVG并不是android支持的标准资源格式;
  3. SVG相对PNG,则性能尤其对CPU消耗比较大,不过针对于目前的手机而言,还是比较能接受。

而关于SVG,它究竟是什么?到现在我们了解甚少,不过,没关系,慢慢来呗~

SVG,即Scalable Vector Graphics 可伸缩矢量图形。而关于详细,请查阅:W3School官方

首先要解释下矢量图像以及位图图像?

  • 矢量图象 SVG是W3C 推出的一种开放标准的文本式矢量图形描述语言,他是基于XML的、专门为网络而设计的图像格式。So,SVG是一种采用XML来描述二维图形的语言,所以它可以直接打开xml文件来修改和编辑。
  • 位图图像 位图图像(Bitmap)的存储单位是图像上每一点的像素值,因而文件会比较大,像GIF、JPEG、PNG等都是位图图像格式。 而Android中的矢量图,便是Vector,在Android中也被称为Vector Drawable。

而这里需要注明的一点:

Vector图像刚发布的时候,是只支持Android 5.0+的,自从AppCompat 23.2之后,Vector可以使用于Android 2.1以上的所有系统,只需要引用com.android.support:appcompat-v7:23.2.0以上的版本就可以了。(所谓的兼容也就是表里不一,即低版本非真实使用SVG,而是生成PNG图片)

还要说明的是,Android 5.0发布的时候,Google提供了Vector的支持,即:Vector Drawable类

Vector Drawable,Hello

Vector Drawable相对于普通的Drawable来说,有以下几个好处:

(1)Vector图像可以自动进行适配,不需要通过分辨率来设置不同的图片;

(2)Vector图像可以大幅减少图像的体积,同样一张图,用Vector来实现,可能只有PNG的几十分之一;

(3)使用简单,很多设计工具,都可以直接导出SVG图像,从而转换成Vector图像 功能强大;

(4)不用写很多代码就可以实现非常复杂的动画 成熟、稳定,前端已经非常广泛的进行使用了。

Vector 语法简介

主要通过使用Path标签,我们几乎可以完成所有操作。

而关于Path指令,具体解析如下所示:

  1. M = moveto(M X,Y) :将画笔移动到指定的坐标位置,相当于 android Path 里的moveTo();
  2. L = lineto(L X,Y) :画直线到指定的坐标位置,相当于 android Path 里的lineTo();
  3. H = horizontal lineto(H X):画水平线到指定的X坐标位置;
  4. V = vertical lineto(V Y):画垂直线到指定的Y坐标位置 ;
  5. C = curveto(C X1,Y1,X2,Y2,ENDX,ENDY):三次贝赛曲线 ;
  6. S = smooth curveto(S X2,Y2,ENDX,ENDY): 同样三次贝塞尔曲线,更平滑 ;
  7. Q = quadratic Belzier curve(Q X,Y,ENDX,ENDY):二次贝赛曲线 ;
  8. T = smooth quadratic Belzier curveto(T ENDX,ENDY):映射 同样二次贝塞尔曲线,更平滑 ;
  9. A = elliptical Arc(A RX,RY,XROTATION,FLAG1,FLAG2,X,Y):弧线 ,相当于arcTo();
  10. Z = closepath():关闭路径(会自动绘制链接起点和终点);

注意,’M’ 处理时,只是移动了画笔, 没有画任何东西。

而关于以上的语法,我们只需要了解即可。

因为相对于编写过程中的消耗,我们都可以借助于一些工具来完成。

SVG初使用

关于编辑以及绘制SVG,我们可以通过如下网站搭配使用:

•SVG生成工具;

•SVG转为VectorDrawable

下面开始演示之路:

SVG生成:

接下来,SVG转为VectorDrawable:

之后,将下载完成后的xml拷贝到drawable目录下。

首先,我们简单的解析部分的语法,好让大家以后真正遇到后不会那么棘手。

代码语言:javascript
复制
android:pathData="
M 287 87.5 
C 351.893458105 87.5 404.5 138.091823269 404.5 200.5 
C 404.5 262.908176731 351.893458105 313.5 287 313.5 
C 222.106541895 313.5 169.5 262.908176731 169.5 200.5 
C 169.5 138.091823269 222.106541895 87.5 287 87.5 
Z"

首先,将坐标移动到 287 87.5 位置,接着,分别绘制三次贝赛曲线,最后关闭路径。从而形成了一个图形。

首先,我们先当作一个图片直接使用:

代码语言:javascript
复制
   <ImageView
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_gravity="center"
        android:src="@drawable/method_draw_image" />

5.0+上显示效果如下:

不知道大家还记得,之前LZ说的,所谓的兼容,并不是真正的让低版本去使用SVG,而是在低版本上面讲SVG转为了png,不信你瞧:

有的小伙伴说,忒麻烦了,还有其他的方式么?简单点的?

Android Studio 创建 Vector Asset

右击res下的drawable目录,选择new,点击Vector Asset。

你可以调整透明度,也可以设置图片大小,如下:

当然,你也可以选择系统内容的图片,如下:

使用方式如上述一致,首先我们看一下生成的xml文件内容:

代码语言:javascript
复制
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp" // 宽度
    android:height="24dp" // 高度
    android:alpha="0.80" // 透明度
    android:viewportHeight="24.0" // 高度平均分为24等份
    android:viewportWidth="24.0"> // 宽度平均分为24等份
    <path
        android:fillColor="#FF000000"
        android:pathData="M6,18c0,0.55 0.45,1 1,1h1v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L11,19h2v3.5c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5L16,19h1c0.55,0 1,-0.45 1,-1L18,8L6,8v10zM3.5,8C2.67,8 2,8.67 2,9.5v7c0,0.83 0.67,1.5 1.5,1.5S5,17.33 5,16.5v-7C5,8.67 4.33,8 3.5,8zM20.5,8c-0.83,0 -1.5,0.67 -1.5,1.5v7c0,0.83 0.67,1.5 1.5,1.5s1.5,-0.67 1.5,-1.5v-7c0,-0.83 -0.67,-1.5 -1.5,-1.5zM15.53,2.16l1.3,-1.3c0.2,-0.2 0.2,-0.51 0,-0.71 -0.2,-0.2 -0.51,-0.2 -0.71,0l-1.48,1.48C13.85,1.23 12.95,1 12,1c-0.96,0 -1.86,0.23 -2.66,0.63L7.85,0.15c-0.2,-0.2 -0.51,-0.2 -0.71,0 -0.2,0.2 -0.2,0.51 0,0.71l1.31,1.31C6.97,3.26 6,5.01 6,7h12c0,-1.99 -0.97,-3.75 -2.47,-4.84zM10,5L9,5L9,4h1v1zM15,5h-1L14,4h1v1z" />
</vector>

而运行的效果则是:

GitHub查看地址

https://github.com/HLQ-Struggle/SVGStudy

参考资料

1.微信官方SVG介绍;

2.W3School官方;

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-04-03,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 贺biubiu 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档