深入学习 SVG 教程

2018-04-15 admin

SVG

Introduction

Despite being standardized in the early 2000s, SVG (a shorthand for Scalable Vector Graphics) is a hot topic these days.

SVG has been penalized for quite a few years by the poor browser support (most notably IE).

I found this quote from a 2011 book: “at the time of writing, direct embedding of SVG into HTML works only in the very newest browsers”. 7 years ago, this is now a thing of the past, and we can use SVG images safely.

Today we can use SVG images safely, unless you have a lot of users with IE8 and below, or with older Android devices. In this case, fallbacks exist.

SVG Browser support

Some part of the success of SVG is due to the variety of screen displays we must support, at different resolutions and sizes. A perfect task for SVG.

Also, the rapid decline of Flash in the last few years led to a renewed interest in SVG, which is great for a lot of things that Flash did in the past.

SVG is a vector image file format. This makes them very different than image format such as PNG, GIF or JPG, which are raster image file formats.

The advantages of SVG

SVG images, thanks to being vector images, can infinitely scale and not have any issue in image quality degradation. How so? Because SVG images are built using XML markup, and the browser prints them by plotting each point and line, rather than filling some space with pre-defined pixels. This ensures SVG images can adapt to different screen sizes and resolutions, even ones that have yet to be invented.

Thanks to being defined in XML, SVG images are much more flexible than JPG or PNG images, and** we can use CSS and JavaScript to interact with them**. SVG images can even contain CSS and JavaScript.

SVG images can render vector-style images a lot smaller than other formats, and are mainly used on logos and illustrations. Another huge use case is icons. Once domain of Icon Fonts like FontAwesome, now designers prefer using SVG images because they are smaller and they allow to have multi-color icons.

SVG is easy to animate, which is a very cool topic.

SVG provides some image editing effects, like masking and clipping, applying filters, and more.

SVG are just text, and as such it can be efficiently compressed using GZip.

Your first SVG image

SVG images are defined using XML. This means that SVG will look very familiar if you are proficient in HTML, except rather than having tags that are suited for document construction (like p, article, footer, aside) in SVG we have the building blocks of vector images: path, rect, line and so on.

This is an example SVG image:

<svg width="10" height="10">
  <rect x="0" y="0" width="10" height="10" fill="blue" />
</svg>

Notice how it’s very easy to read and understand how the image will look like: it’s a simple blue rectangle of 10x10 pixels (the default unit).

Most of the times you won’t have to edit the SVG code, but you will use tools like Sketch or Figma or any other vector graphics tool to create the image, and export it as SVG.

The current version of SVG is 1.1, and SVG 2.0 is under development.

Using SVG

SVG images can be displayed by the browser by including them in a img tag:

<img src="image.svg" alt="My SVG image" />

just like you would do for other pixel-based image formats:

<img src="image.png" alt="My PNG image" />
<img src="image.jpg" alt="My JPG image" />
<img src="image.gif" alt="My GIF image" />
<img src="image.webp" alt="My WebP image" />

In addition, pretty uniquely, SVG they can be directly included in the HTML page:

<!DOCTYPE html>
<html>
  <head>
    <title>A page</title>
  </head>
  <body>
    <svg width="10" height="10">
      <rect x="0" y="0" width="10" height="10" fill="blue" />
    </svg>
  </body>
</html>

Please note that HTML5 and XHTML require a different syntax for inline SVG images. Luckily XHTML is a thing of the past, as it was more complex than necessary, but it’s worth knowing in case you still need to work on XHTML pages.

The ability to inline SVG in HTML makes this format a unicorn in the scene, as other images can’t do this, and must be fetched by opening a separate request for each one.

SVG Elements

In the example above you saw the usage of the rect element. SVG has a lot of different elements.

The most used ones are

  • text: creates a text element
  • circle: creates a circle
  • rect: creates a rectangle
  • line: creates a line
  • path: create a path between two points
  • textPath: create a path between two points, and a linked text element
  • polygon: allows to create any kind of polygon
  • g: groups separate elements

Coordinates start at 0,0 at the top-left of the drawing area, and extend from left to right for x, from top to bottom for y.

The images you see reflect the code shown above. Using the Browser DevTools you can inspect and change them.

text

The text element adds text. The text can be selected using the mouse. x and y define the starting point of the text

<svg>
  <text x="5" y="30">A nice rectangle</text>
</svg>

<text>A nice rectangle</text>

circle

Define a circle. cx and cy are the center coordinates, and r is the radius. fill is a common attribute and represents the figure color.

<svg>
  <circle cx="50" cy="50" r="50" fill="#529fca" />
</svg>

rect

Defines a rectangle. x, y are the starting coordinates, width and height are self-explanatory.

<svg>
  <rect x="0" y="0" width="100" height="100" fill="#529fca" />
</svg>

line

x1 and y1 define the starting coordinates. x2 and y2 define the ending coordinates. stroke is a common attribute and represents the line color.

<svg>
  <line x1="0" y1="0" x2="100" y2="100" stroke="#529fca" />
</svg>

path

A path is a sequence of lines and curves. It’s the most powerful tool to draw using SVG, and as such it’s the most complex.

d contains the directions commands. These commands start with the command name, and a set of coordinates:

  • M means Move, it accepts a set of coordinates x, y
  • L means Line, it accepts a set of coordinates x, y to draw the line to
  • H is an Horizontal Line, it only accept an x coordinate
  • V is a Vertical Line, it only accept an y coordinate
  • Z means Close Path, puts a line back to the start
  • A means Arch, it needs a whole tutorial on its own
  • Q is a quadratic Bezier curve, again it needs a whole tutorial on its own
<svg height="300" width="300">
  <path d="M 100 100 L 200 200 H 10 V 40 H 70"
        fill="#59fa81" stroke="#d85b49" stroke-width="3" />
</svg>

textPath

Adds a text along the shape of a path element.

<path id=“MyPath”></path><text><textpath xlink:href="#MyPath">Wow such a nice SVG tut</textpath></text>

polygon

Draw any random polygon with polygon. `points represents a set of x, y coordinates the polygon should link:

<svg>
  <polygon points="9.9, 1.1, 3.3, 21.78, 19.8, 8.58, 0, 8.58, 16.5, 21.78" />
</svg>

g

Using the g element you can group multiple elements:

<svg width="200" height="200">
  <rect x="0" y="0" width="100" height="100" fill="#529fca" />
  <g id="my-group">
    <rect x="0" y="100" width="100" height="100" fill="#59fa81" />
    <rect x="100" y="0" width="100" height="100" fill="#59fa81" />
  </g>
</svg>

SVG viewport and viewBox

The size of an SVG relative to its container is set by the width and height attributes of the svg element. Those units default to pixels, but you can use any other usual unit like % or em. This is the viewport.

Generally “container” means the browser window, but a svg element can contain other svg elements, in that case the container is the parent svg.

An important attribute is viewBox. It lets you define a new coordinates system inside the SVG canvas.

Say you have a simple circle, in a 200x200px SVG:

<svg width="200" height="200">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>

By specifying a viewBox you can choose to only show a portion of this SVG. For example you can start at point 0, 0 and only show a 100x100px canvas:

<svg width="200" height="200" viewBox="0 0 100 100">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>

starting at 100, 100 you will see another portion, the bottom right half of the circle:

<svg width="200" height="200" viewBox="100 100 100 100">
  <circle cx="100" cy="100" r="100" fill="#529fca" />
</svg>

A great way to visualize this is to imagine Google Maps being a gigantic SVG image, and your browser is a viewBox as big as the window size. When you move around, the viewBox changes its starting point (x, y) coordinates, and when you resize the window, you change the width and height of the viewBox.

Inserting SVG in Web Pages

There are various ways to add SVG to a webpage.

The most common ones are:

  • with an img tag
  • with the CSS background-image property
  • inline in the HTML
  • with an object, iframe or embed tag

See all these examples live on Glitch: flavio-svg-loading-ways.glitch.me/

With an img tag

<img src="flag.svg" alt="Flag" />

With the CSS background-image property

<style>
.svg-background {
  background-image: url(flag.svg);
  height: 200px;
  width: 300px;
}
</style>
<div class="svg-background"></div>

Inline in the HTML

<svg width="300" height="200" viewBox="0 0 300 200"
    version="1.1" xmlns="http://www.w3.org/2000/svg"
    xmlns:xlink="http://www.w3.org/1999/xlink">
  <title>Italian Flag</title>
  <desc>By Flavio Copes https://flaviocopes.com</desc>
  <g id="flag">
      <rect fill="green" x="0" y="0" width="100" height="200"></rect>
      <rect fill="white" x="100" y="0" width="100" height="200"></rect>
      <rect fill="red" x="200" y="0" width="100" height="200"></rect>
  </g>
</svg>

With an object, iframe or embed tag

<object data="flag.svg" type="image/svg+xml"></object>

<iframe src="flag.svg" frameborder="0"></iframe>

<embed src="flag.svg" type="" />

Using embed you have the option to get the SVG document from the parent document using

document.getElementById('my-svg-embed').getSVGDocument()

and from inside the SVG you can reference the parent document with:

window.parent.document

Inline SVG using a Data URL

You can use any of the above examples combined with Data URLs to inline the SVG in the HTML:

<img src="data:image/svg+xml;<DATA>" alt="Flag" />

<object data="data:image/svg+xml;<DATA>" type="image/svg+xml"></object>

<iframe data="data:image/svg+xml;<DATA>" frameborder="0"></iframe>

and in CSS too:

.svg-background {
  background-image: url("data:image/svg+xml;<DATA>");
}

Just change <DATA> with the appropriate Data URL.

Styling elements

Any SVG element can accept a style attribute, just like HTML tags. Not all CSS properties work as you would expect, due to the SVG nature. For example to change the color of a text element, use fill instead of color.

<svg>
  <text x="5" y="30" style="fill: green">A nice text</text>
</svg>

<svg>
  <text x="5" y="70" style="fill: green; font-family: Courier New">
    A nice text
  </text>
</svg>

You can use fill as an element attribute as well, as you saw before:

<svg>
  <text x="5" y="70" fill="green">A nice text</text>
</svg>

Other common properties are

  • fill-opacity, background color opacity
  • stroke, defines the border color
  • stroke-width, sets the width of the border

CSS can target SVG elements like you would target HTML tags:

rect {
  fill: red;
}
circle {
  fill: blue;
}

Interacting with a SVG with CSS or JavaScript

SVG images can be styled using CSS, or scripted with JavaScript, in those cases:

  • when the SVG is inlined in the HTML
  • when the image is loaded through object, embed or iframe tags

but (⚠️ depending on the browser implementation) they must be loaded from the same domain (and protocol), due to the same-origin policy.

iframe needs to be explicitly sized, otherwise the content is cropped, while object and embed resize to fit their content.

If the SVG is loaded using a img tag, or through CSS as a background, independently of the origin:

  • CSS and JavaScript cannot interact with it
  • JavaScript contained in the SVG is disabled
  • External resources like images, stylesheets, scripts, fonts cannot be loaded

In details


Feature Inline SVG object/embed/iframe img
Can interact with the user
Supports animations
Can run its own JavaScript 👎🏼
Can be scripted from outside 👎🏼 👎🏼

Inline SVG images are definitely the most powerful and flexible, and it’s the only way to perform certain operations with SVG.

If you want to do any interaction with the SVG with your scripts, it must be loaded inline in the HTML.

Loading an SVG in an img, object or embed works if you don’t need to interact with it, just show it in the page, and it’s especially convenient if you reuse SVG images in different pages, or the SVG size is quite big.

CSS inside SVG

Add the CSS in a CDATA:

<svg>
  <style>
    <![CDATA[
      #my-rect { fill: blue; }
    ]]>
  </style>
  <rect id="my-rect" x="0" y="0" width="10" height="10" />
</svg>

An SVG file can also include an external style sheet:

<?xml version="1.0" standalone="no"?>
<?xml-stylesheet type="text/css" href="style.css"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width=".." height=".." viewBox="..">
  <rect id="my-rect" x="0" y="0" width="10" height="10" />
</svg>

JavaScript inside SVG

You can put the JavaScript first, and wrap in in a load event to execute it when the page is fully loaded and the SVG is inserted in the DOM:

<svg>
  <script>
    <![CDATA[
      window.addEventListener("load", () => {
        //...
      }, false)
    ]]>
  </script>
  <rect x="0" y="0" width="10" height="10" fill="blue" />
</svg>

or you can avoid adding an event listener if you put the JS at the end of the other SVG code, to make sure the JavaScript runs when the SVG is present in the page:

<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue" />
  <script>
    <![CDATA[
      //...
    ]]>
  </script>
</svg>

SVG elements, just like html tags, can have id and class attributes, so we can use the Selectors API to reference them:

<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue"
        id="my-rect" class="a-rect" />
  <script>
    <![CDATA[
      console.log(document.getElementsByTagName('rect'))
      console.log(document.getElementById('my-rect'))
      console.log(document.querySelector('.a-rect'))
      console.log(document.querySelectorAll('.a-rect'))
    ]]>
  </script>
</svg>

Check out this Glitch flaviocopes-svg-script.glitch.me/ for an example of this functionality.

JavaScript outside the SVG

If you can interact with the SVG (the SVG is inline in the HTML), you can change any SVG attribute using JavaScript, for example:

document.getElementById("my-svg-rect").setAttribute("fill", "black")

or really do any other DOM manipulation you want.

CSS outside the SVG

You can change any styling of the SVG image using CSS.

SVG attributes can be easily overwritten in CSS, and they have a lower priority over CSS. They do not behave like inline CSS, which has higher priority.

<style>
  #my-rect {
    fill: red
  }
</style>
<svg>
  <rect x="0" y="0" width="10" height="10" fill="blue"
        id="my-rect" />
</svg>

SVG vs Canvas API

The Canvas API is a great addition to the Web Platform, and it has similar browser support as SVG. The main (and big) difference with SVG is that Canvas is not vector based, but rather pixel based, so

  • it has the same scaling issues as pixel-based PNG, JPG and GIF image formats
  • it makes it impossible to edit a Canvas image using CSS or JavaScript like you can do with SVG

SVG Symbols

Symbols let you define an SVG image once, and reuse it in multiple places. This is a great help if you need to reuse an image, and maybe just change a bit some of its properties.

You do so by adding a symbol element and assigning an id attribute:

<svg class="hidden">
  <symbol id="rectangle" viewBox="0 0 20 20">
    <rect x="0" y="0" width="300" height="300" fill="rgb(255,159,0)" />
  </symbol>
</svg>

<svg>
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<svg>
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

(xlink:href is for Safari support, even if it’s a deprecated attribute)

This starts to give an idea of the power of SVG.

If you want to style those 2 rectangles differently, for example using a different color for each? You can use CSS Variables.

<svg class="hidden">
  <symbol id="rectangle" viewBox="0 0 20 20">
    <rect x="0" y="0" width="300" height="300" fill="var(--color)" />
  </symbol>
</svg>

<svg class="blue">
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<svg class="red">
  <use xlink:href="#rectangle" href="#rectangle" />
</svg>

<style>
svg.red {
  --color: red;
}
svg.blue {
  --color: blue;
}
</style>

See my Glitch playground on SVG symbols.

Validate an SVG

An SVG file, being XML, can be written in an invalid format, and some services or apps might not accept an invalid SVG file.

SVG can be validated using the W3C Validator.

Should I include the xmlns attribute?

Sometimes an svg is defined as

<svg>
  ...
</svg>

sometimes as

<svg version="1.1" xmlns="http://www.w3.org/2000/svg">
  ...
</svg>

This second form is XHTML. It can also be used with HTML5 (documents with <!DOCTYPE html>`) but in this case the first form is simpler.

Should I worry about browser support?

In 2018 SVG is supported by the vast majority of user’s browsers.

You can still check for missing support using libraries like Modernizr, and provide a fallback:

if (!Modernizr.svg) {
  $(".my-svg").attr("src", "images/logo.png");
}

原文链接:https://flaviocopes.com/svg/

本站文章除注明转载外,均为本站原创或编译。欢迎任何形式的转载,但请务必注明出处。

转载请注明:文章转载自 JavaScript中文网 [https://www.javascriptcn.com]

本文地址:https://www.javascriptcn.com/read-27620.html

文章标题:深入学习 SVG 教程

相关文章
五款超实用的开源SVG工具
本文我们将分享5款超实用的开源的SVG工具:   1. SharpVectorGraphics (SVG)   SVG是基于Microsoft .Net开源项目设计而来,是建立在.Net framework上使用SVG的一款应用,支持生成、...
2016-01-13
JavaScript深入之类数组对象与
类数组对象 所谓的类数组对象: 拥有一个 length 属性和若干索引属性的对象 举个例子: var array = [&#x27;name&#x27;, &#x27;age&#x27;, &#x27;sex&#x27;]; var ...
2017-05-27
深入分析JSON编码格式提交表单数据
以JSON编码格式提交表单数据是HTML5对WEB发展进化的又一大贡献,以前我们的HTML表单数据是通过key-value方式传输的服务器端,这种形式的传输对数据组织缺乏管理,形式十分原始。而新出现的JSON格式提交表单数据方法,将表单里的...
2017-03-25
深入浅出分析javaScript中this用法
本文实例讲述了javaScript中this用法。分享给大家供大家参考。具体分析如下: 之前学javascript的时候总搞不清this,这个this不像java里的this那么好理解。我后来也是看了许多别人写的文章,才理解过来的。现在把别...
2017-03-23
深入理解JavaScript的React框架的原理
如果你在两个月前问我对React的看法,我很可能这样说: 我的模板在哪里?javascript中的HTML在做些什么疯狂的事情?JSX开起来非常奇怪!快向它开火,消灭它吧! 那是因为我没有理解它. 我发誓,React 无疑是在正确的轨道...
2017-03-26
JavaScript函数使用的基本教程
函数是一组可重用的代码,可以在程序的任何地方被调用。这消除了一次又一次地写入相同的代码的需要。这将帮助程序员编写模块化代码。您可以在一些小且易于管理的功能划分大程序。 像任何其他高级编程语言,JavaScript支持所有必要写模块化的代码使...
2017-03-24
JavaScript中pop()方法的使用教程
JavaScript数组pop()方法删除数组中的最后一个元素,并返回该元素。 语法 下面是参数的详细信息: 返回值: 返回从数组中删除的元素。 例子: &lt;html&gt; &lt;head&gt; &lt;title&gt;Java...
2017-03-24
深入探寻seajs的模块化与加载方式
由于一直在使用,所以了解了下seajs的源代码。这里是我对下面几个问题的理解: 1、seajs的require(XXX)的方法是怎样实现模块加载的? 2、为什么需要预加载? 3、为什么需要构建工具? 4、构建前后的代码究竟有些什么区别,为什...
2017-03-22
深入理解JavaScript编程中的原型概念
JavaScript 的原型对象总是让人纠结。即使是经验丰富的JavaScript专家甚至其作者,经常对这一概念给出很有限的解释。我相信问题来自于我们对原型最早的认识。原型总是与new, constructor 以及令人困惑的prototy...
2017-03-25
JavaScript 闭包深入理解(closure)
一、什么是闭包? “官方”的解释是:闭包是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。 相信很少有人能直接看懂这句话,因为他描述的太学术。其实这句话通俗的来说就是:JavaScript...
2017-03-23
回到顶部