内容简介:最近需要在 React-Native 项目里实现一个填满特定图形的效果,找很久都没发现能满足需求的开源库,于是就打算用 SVG 自己怼一个。好在这方面教程还不少,虽然不能一步到位,但几篇文章加一起也能把效果实现出来,于是在这里把入门过程记录一下,希望帮后来者省点功夫。SVG(Scalable Vector Graphics) 是一种基于 XML 语法的图像格式。跟基于像素处理的图片格式不同,它是基于对图像形状的描述来实现的,本质上是一个文本文件,体积上较小,而且在放大的时候也不会失真。因为 SVG 是基于
最近需要在 React-Native 项目里实现一个填满特定图形的效果,找很久都没发现能满足需求的开源库,于是就打算用 SVG 自己怼一个。好在这方面教程还不少,虽然不能一步到位,但几篇文章加一起也能把效果实现出来,于是在这里把入门过程记录一下,希望帮后来者省点功夫。
SVG 是个啥?
SVG(Scalable Vector Graphics) 是一种基于 XML 语法的图像格式。跟基于像素处理的图片格式不同,它是基于对图像形状的描述来实现的,本质上是一个文本文件,体积上较小,而且在放大的时候也不会失真。
因为 SVG 是基于 XML 语法的,所以对于前端开发者来说,写起来应该比较顺手;对于 React-Native 的项目,因为 JSX 的关系,用起 SVG 来也是没有“语言障碍”的。
SVG 长什么样?
直接上源码:
<svg width='100' height="100" viewBox="0 0 100 100" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> <defs> <clipPath id="heart"> <path d="M81.495,13.923c-11.368-5.261-26.234-0.311-31.489,11.032C44.74,13.612,29.879,8.657,18.511,13.923 C6.402,19.539,0.613,33.883,10.175,50.804c6.792,12.04,18.826,21.111,39.831,37.379c20.993-16.268,33.033-25.344,39.819-37.379 C99.387,33.883,93.598,19.539,81.495,13.923z"/> </clipPath> </defs> <rect x='0' y='0' fill='rgb(217,217,217)' width="100%" height="100%" clip-path="url(#heart)" /> <rect x='0%' y="50%" fill='red' width="100%" height="100%" clip-path="url(#heart)" /> </svg>
这张 SVG 图渲染出来是这样的:
直接把上面的代码保存为文本,就可以用浏览器打开并显示了。macOS 的用户还可以直接空格预览。
配合一些参数的改变,做动画也是分分钟的事情。对于之前没有怎么用过 SVG 的我来说,简直是打开了新世界的大门。
接下来就让我们一起探究一下上面这个图是怎么来的。
SVG 显示原理
根据上面的例子,我们可以大胆猜测一下: <path>
标签下 d
属性的值就是用来描绘这个心形的外框路径的。既然描绘路径已经是确定的了,那一张 SVG 图片是怎么实现缩放不失真的特性的呢?
要回答这个问题,就要让我们先了解一下 SVG 的一些基本显示原理。
The SVG Canvas
假设我们要将一个 SVG 图形绘制到一张画布(Canvas)上,概念上这张画布应该是无限大的,这样我们的图形才可以是任意大小。然而,实际上 SVG 图片是显示在一个有限的区域里的,就像我们透过窗户看窗外的风景一样,这个有限区域被称为“观察孔”(Viewport)。
The Viewport
“观察孔”指的是 SVG 图片可见的那一部分,想象我们透过窗户看窗外的风景,这个窗子就是外面风景的观察孔。
类似的,我们在浏览网页的时候面对的也是这种情况,网页的大小通常比浏览器的窗口要大,这时候浏览器就是这个网页的观察孔了。
我们通过设置 <svg>
标签的 width
和 height
属性来确定这张 SVG 的观察孔大小,对于上面的心形来说,观察孔是 100x100 的正方形:
<!-- the viewport will be 100px by 100px --> <svg width="100" height="100"> <!-- SVG content drawn onto the SVG canvas --> </svg>
在 SVG 里,数值的单位是可选的。在我们不主动提供的时候,默认会以 px
为单位。可选的单位有 em
、 ex
、 px
、 pt
、 pc
、 cm
、 mm
、 in
和百分比。
坐标系统
在观察孔的大小确定下来之后,SVG 就会建立一套初始的坐标系统:以最左上角为 (0, 0)
点,x 轴和 y 轴分别向右和向下延伸(就像移动客户端和网页显示里那样)。在这个基础上,我们刚刚创建的观察孔也就有了属于自己的一套位置标识: (x: 0, y: 0, width: 100, height: 100)
。
The viewbox
在了解了上述知识之后,我们就可以来说说 viewbox
这个属性了。
我们可以把 viewbox
理解为“真正的坐标系统”,因为它决定了 SVG 图形是怎么绘制到画布上的。一个 SVG 图形的大小可以与观察孔不一样,它可能会完整地显示出来,也可能会被观察孔裁减掉一部分。
就像一张普通图片一样,当你需要把图形完整地放进一个视图里面时,可以调节图片的拉伸模式,一边让图片的大小更为合理。SVG 里对应的属性是 preserveAspectRatio
。
viewbox
会一次性设置4个参数:
<svg viewbox="<min-x> <min-y> <width> <height>"></svg>
其中, <min-x>
和 <min-y>
不能设置为负数, <width>
和 <height>
设置为 0 的话,元素就压根不会绘制了。
所以说, viewbox="0 0 100 100"
就做了下面几件事情:
- 在画布上划分出来一个 100x100 大小的区域,放在 (0, 0) 点上
- 把 SVG 图形缩放成合适这个区域的样子
- 将整个区域(包括里面的图形)放大到铺满整个观察孔
- 将这个坐标系统 按比例 映射到到初始坐标系统上
那对于上面的爱心图片来说,我们尝试调整一下 viewbox
的原点,将它设置为 viewbox="50 50 100 100"
试试:
可以看到,就像地图软件一样,镜头往画面的右下方移动了一段。这也相当于把整个画面往左上方推了过去一点,我们可以通过设置画布的 transform
属性来实现相同的效果: transform="translate(-50 -50)"
。
当设计师给你一张 SVG 图片的时候,其中的图案路径可能是按照一定的大小和位移来绘制的,比如从(10, 10) 点开始画的一张 40x40 的图,这时候你的 viewbox
就应该设置为 viewbox="10 10 40 40"
,让图片放到最合适的坐标系统上。
小结
上面的例子演示了一张 SVG 图的常规操作,限于篇幅原因,还有一些有意思的情况没有展示到,比如当 viewbox
里设置的宽高比与我们在 <svg>
标签里设置的宽高比不一样会发生什么呢?这种情况下,就需要我们去了解一下 preserveAspectRatio
属性了。
在参考文章 Understanding SVG Coordinate Systems and Transformations (Part 1) 里,有对这方面更详细的解释,而且作者还提供了非常直观的在线预览工具,相信会对偏向于使用图像思维的同学们更有帮助。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 入门GitHub,这一个开源项目足够了!
- 更好就足够了吗?| 驱动变革
- Python文件操作,看这篇就足够
- 想读懂Linux内核,这一篇就足够!
- 强大美观的通用弹窗XPopup,一个就足够!
- 谷歌大脑:只要网络足够宽,激活函数皆可抛
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Geometric Folding Algorithms
Erik D Demaine / Cambridge University Press / 2008-8-21 / GBP 35.99
Did you know that any straight-line drawing on paper can be folded so that the complete drawing can be cut out with one straight scissors cut? That there is a planar linkage that can trace out any alg......一起来看看 《Geometric Folding Algorithms》 这本书的介绍吧!