SVG 从“完全不懂”到“足够开个入门分享”

栏目: 后端 · 前端 · 发布时间: 6年前

内容简介:最近需要在 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 图渲染出来是这样的:

SVG 从“完全不懂”到“足够开个入门分享”

直接把上面的代码保存为文本,就可以用浏览器打开并显示了。macOS 的用户还可以直接空格预览。

配合一些参数的改变,做动画也是分分钟的事情。对于之前没有怎么用过 SVG 的我来说,简直是打开了新世界的大门。

接下来就让我们一起探究一下上面这个图是怎么来的。

SVG 显示原理

根据上面的例子,我们可以大胆猜测一下: <path> 标签下 d 属性的值就是用来描绘这个心形的外框路径的。既然描绘路径已经是确定的了,那一张 SVG 图片是怎么实现缩放不失真的特性的呢?

要回答这个问题,就要让我们先了解一下 SVG 的一些基本显示原理。

The SVG Canvas

假设我们要将一个 SVG 图形绘制到一张画布(Canvas)上,概念上这张画布应该是无限大的,这样我们的图形才可以是任意大小。然而,实际上 SVG 图片是显示在一个有限的区域里的,就像我们透过窗户看窗外的风景一样,这个有限区域被称为“观察孔”(Viewport)。

The Viewport

“观察孔”指的是 SVG 图片可见的那一部分,想象我们透过窗户看窗外的风景,这个窗子就是外面风景的观察孔。

类似的,我们在浏览网页的时候面对的也是这种情况,网页的大小通常比浏览器的窗口要大,这时候浏览器就是这个网页的观察孔了。

我们通过设置 <svg> 标签的 widthheight 属性来确定这张 SVG 的观察孔大小,对于上面的心形来说,观察孔是 100x100 的正方形:

<!-- the viewport will be 100px by 100px -->
<svg width="100" height="100">
		<!-- SVG content drawn onto the SVG canvas -->
</svg>

在 SVG 里,数值的单位是可选的。在我们不主动提供的时候,默认会以 px 为单位。可选的单位有 emexpxptpccmmmin 和百分比。

坐标系统

在观察孔的大小确定下来之后,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" 就做了下面几件事情:

  1. 在画布上划分出来一个 100x100 大小的区域,放在 (0, 0) 点上
  2. 把 SVG 图形缩放成合适这个区域的样子
  3. 将整个区域(包括里面的图形)放大到铺满整个观察孔
  4. 将这个坐标系统 按比例 映射到到初始坐标系统上

那对于上面的爱心图片来说,我们尝试调整一下 viewbox 的原点,将它设置为 viewbox="50 50 100 100" 试试:

SVG 从“完全不懂”到“足够开个入门分享”

可以看到,就像地图软件一样,镜头往画面的右下方移动了一段。这也相当于把整个画面往左上方推了过去一点,我们可以通过设置画布的 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) 里,有对这方面更详细的解释,而且作者还提供了非常直观的在线预览工具,相信会对偏向于使用图像思维的同学们更有帮助。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Geometric Folding Algorithms

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》 这本书的介绍吧!

JS 压缩/解压工具
JS 压缩/解压工具

在线压缩/解压 JS 代码

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具