SVG精髓-笔记与实践

时间:2022-11-20 17:04:46

笔记链接:http://f5528907.wiz03.com/share/s/3RkEA70XbA2d2jbjQh1dHWIp3APUr93rFQYZ2srCaU2YDjgc

在网页中使用svg

1.当做图像使用:

  • 在<img>元素中使用:

<img src="./person.svg" alt="" title=""> 默认300px * 150px
        改变颜色:添加矢量图的阴影,fill设置成底色,filter设置成需要的颜色
 
filter: drop-shadow(rgb(0, 0, 0) 1px 0px)

                
  • 在css中使用

 
i {
    background-image: url("./person.svg");
    background-size: 100% 100%;
}
 
<i class="icon"></i>
.icon {
    width: 10px;
    height: 10px;
    display: block;
    background-color: red;
    -webkit-mask: url(./person.svg) no-repeat center;
    mask: url(./person.svg) no-repeat center;
}

                

  • svg-spirit
        使用svgxuse做polyfill,这个polyfill遍历文档中的<use>元素,然后如果它引用的是浏览器无法加载的外部SVG文件,它就在外部SVG中抓取并预置到文档中的<body>。
        glup插件gulp-svg-symbols,合成spirit。
 
common.svg 
<svg>
    //svg规范推荐将复用对象放在defs元素中当做模板,svg阅读器进入流式环境能够高效处理数据
    <defs>
        //symbol是除了<g>之外另一种组合元素的方式,永远不会显示,可定义图像模板
        //symbol 还可以指定 viewBox 和 preserveAspectRatio 属性,通过给<use>元素添加 width 和 height 属性就可以让symbol适配视口大小
        <symbol id="arrow">
         <polyline stroke="red" fill="none" points="30 0 0 30 30 60" stroke-width="6"/>
        </symbol>
    
        <symbol id="circle" preserveAspectRatio="xMidYMid slice" viewBox="0 0 40 40">
         <circle cx="100" cy="50" r="40" stroke="black" stroke-width="2" fill="red"/>
        </symbol>
    
        <g id="house" style="stroke: black;">
            <desc>House with door</desc>
            <rect x="0" y="41" width="60" height="60"/>
            <polyline points="0 41, 30 0, 60 41"/>
            <polyline points="30 101, 30 71, 44 71, 44 101"/>
        </g>
    </defs>
</svg>
实例:页面中使用
//左箭头
<svg width="30" height="60">
 <use xlink:href="$imageServer.getURI('/svg/common.svg')#arrow">
</svg>
//右箭头
<svg width="30" height="60">
    <use xlink:href="$imageServer.getURI('/svg/common.svg')#arrow" transform="scale(-1 1) translate(-30 0)">
</svg>

                

        注:出于安全的原因,并非所有的 SVG 阅读器都支持外部引用,尤其是 Web 浏览器。有些浏览器(尤其是 IE)完全不支持外部文件引用。其他浏览器也只允许 <use> 元素引用同一域下的文件或者专门配置了允许跨域使用的 Web 服务器上的文件

2.当做应用程序

        使用嵌入对象<object type="image/svg+xml">:让那些不能直接显示 SVG 但是有 SVG 插件的老版本浏览器用户也能查看图像。
 
<object data="./person.svg" type="image/svg+xml" title="" alt="">
  <!-- 文本或者栅格图像用作备用选项 -->
  <p>No SVG support! Here's a substitute:</p>
  <img src="./person.png" title="这里本来有一个svg的,但是你的浏览器太老了,所以给你显示了一张图片" alt="用户icon"/>
</object>

3.混合文档中的SVG标记

        SVG混入HTML或其他内容:使用<foreignObject>包裹XHTML代码,requiredFeatures和switch元素可以定义备用内容


坐标系统

        水平坐标(x 坐标)向右递增,垂直坐标(y 坐标)垂直向下递增。

1.视口

        svg的画布区域,width和height的取值可以是px/em/ex/pt/px/cm/mm/in/%,单位为百分比时,根据外层包裹的svg元素计算,svg为根元素就根据窗口尺寸计算,没有单位默认为px。

2.为视口指定用户坐标

        设置viewBox属性,属性值为最小 x 坐标、最小 y 坐标、宽度和高度,在元素中定义的width和height相当于百分比
        例如:在4cm * 5cm的视口上设置每厘米16个单位的坐标系统
 
<svg width="4cm" height="5cm" viewBox="0 0 64 80">
        <rect x="10" y="35" width="40" height="40" style="stroke: black; fill: none;"/>
  <!-- 房顶 -->
      <polyline points="10 35, 30 7.68, 50 35" style="stroke: black; fill: none;"/>
  <!-- 房门 -->
      <polyline points="30 75, 30 55, 40 55, 40 75" style="stroke: black; fill: none;"/>
</svg>

        如果视口和viewBox的宽高比不同,使用preserveAspectRatio指定被缩放的图像相对视口的对其方式,设置为none则会平铺不会被等比例缩放。

3.移动坐标系统

    translate变换位置:改变网格在画布上的位置

 
transform="translate(x-value, y-value)"
    scale缩放:缩放坐标系统-笔画也会变粗
 
transform="scale(x-value, y-value)"
        变换序列:将多个变换通过空格或逗号分隔,依次放入transfrom属性,平移缩放的先后顺序产生的结果不同
        
        原始位置:(当前视口 60 * 120,箭头宽高 30 * 60)
                
        transform="translate(20,0) scale(2) ",先移动再放大,基于原始的网格大小进行放大
                
        transform="scale(2) translate(20,0)",先放大再移动,根据放大后的网格大小进行移动,坐标系统偏移超过了视口,显示不全
                

    rotate旋转:角度的测量是按顺时针增加的,水平线的角度为 0 度。默认被旋转的是整个坐标系统,如果想围绕某个点旋转单个对象,可以指定角度和中心点

 
transform="rotate(angle, centerX, centerY)"

        skewX和skewY倾斜轴:

 
transform="skewX(30)"

渐变

linearGradient元素:线性渐变

        <stop>元素的offset属性确定渐变点,使用百分比或者0-1.0之间的小数,stop-color指定渐变点的颜色,stop-opacity可选,表示透明度(如果想要使用用户坐标空间而不是百分比指定渐变方向,设置 gradientUnits 为 userSpaceOnUse 而不是默认值 objectBoundingBox 即可)。
        默认行为是水平从左向右过渡,如果要颜色沿着竖线或者有角度的线条过渡,用x1 y1和x2 y2属性指定渐变的起点和终点。
 
<defs>
    <linearGradient id="three_stops">
        <stop offset="0%" style="stop-color: #ffcc00;"/>
        <stop offset="33.3%" style="stop-color: #cc6699"/>
        <stop offset="100%" style="stop-color: #66cc99;"/>
    </linearGradient>
    
    //继承了渐变点
    <linearGradient id="diagonal" xlink:href="#three_stops"
      x1="0%" y1="0%" x2="100%" y2="100%"/>
</defs>
<rect x="20" y="20" width="200" height="100"
    style="fill: url(#diagonal); stroke: black;"/>

radialGradient元素:径向渐变

        每个渐变点表示原型路径,从中心点向外扩散,使用cx(中心点 x 坐标)、cy(中心点 y 坐标)以及 r(半径)属性定义外圆,可选属性fx、fy改变焦点的位置,默认焦点为100%处的渐变点所在圆的圆心。
        spreadMethod属性:适用于绘制范围没有到达边缘的情况,可以设置为pad、repeat、reflect三个值之一来填补空白。

动画

 1.动画基础

        在元素中添加动画元素<animate>,可指定:
  • attributeName(动画中应该持续改变的值)
  • attributeType(XML或CSS)
  • from/by/to(属性的起始值/偏移量/结束值)
  • begin/dur(动画开始时间和持续时间)
  • fill(动画结束时的动作,取值为freeze-动画保持在最后阶段或remove-保持在起始状态)
  • end(动画的结束时间)
  • repeatCount(重复动画,整型值或indefinite)
  • repeatDur(动画持续时间,与repeatCount同时定义则取决于哪个时间先到达)
  • values(定义复杂的变化序列值,按逗号分隔)
  • keyTimes(0-1,与values对应,定义持续时间序列)
  • keyPoints(为使用路径定义运动的动画指定关键点,数目与keyTimes保持一致,必须设置calcMode为linear/spline)
  • calcMode(对时间的控制,paced/linear/discrete/spline)

2.同步动画

        除了绑定动画开始时间为文档加载时的延后时间,还可以绑定动画的开始时间为另一个动画的开始或者结束,还可以设置为另一个重复动画的第n次的时候,也可以基于事件。
 
begin = "otherAnim.end + 2s"
begin = "id.repeat(count)"
begin = "elementID.eventName + offset"
        和begin一样,也可以为end的值为一个指定的时间或在otherAnim的动画结束时结束,但是不能取代dur属性,同时设置end为另一个动画的结束和dur属性,动画结束则取决于哪个先结束。

3.对复杂属性应用动画

        可以对路径数据或者多边形的点应用动画,只要维持点的数量和路径片段的类型。
 
<polygon points="30 30 70 30 90 70 10 70"
  style="fill:#fcc; stroke:black">
  <animate id="animation"
    attributeName="points"
    attributeType="XML"
    to="50 30 70 50 50 90 30 50"
    begin="0s" dur="5s" fill="freeze" />
</polygon>
<path d="M15 50 Q 40 15, 50 50, 65 32, 100 40"
  style="fill:none; stroke: black" transform="translate(0,50)">
  <animate attributeName="d"
    attributeType="XML"
    to="M50 15 Q 15 40, 50 50, 32 65, 40 100"
    begin="0s" dur="5s" fill="freeze"/>
</path>

4.<set>元素

        对于非数字属性或者不能过度的属性,需要在动画序列的某个点上改变某个值可以使用<set>元素,例子:
 
//初始化一个不可见的文本项,在某个时间点可见
<circle cx="60" cy="60" r="30" style="fill: #ff9; stroke: gray;">
  <animate id="c1" attributeName="r" attributeType="XML"
    begin="0s" dur="4s" from="30" to="0" fill="freeze"/>
</circle>
<text text-anchor="middle" x="60" y="60" style="visibility: hidden;">
  <set attributeName="visibility" attributeType="CSS"
    to="visible" begin="4.5s" dur="1s" fill="freeze"/>
  All gone!
</text>

5.<animateTransform>元素

        <animate>元素不适用于旋转、平移、缩放或倾斜变换,所以衍生出了<animateTransform>元素,设置attributeName为transform,用type指定变换的属性(translate、scale、rotate、skewX 或者 skewY 之一)。
        如果为多个变化应用动画,必须使用additive属性,默认值为replace,后面的动画设置会覆盖前面的,设置为sum会累积变换。
 
<rect x="-10" y="-10" width="20" height="20"
  style="fill: #ff9; stroke: black;">
  <animateTransform attributeName="transform" attributeType="XML"
    type="scale" from="1" to="4 2"
    additive="sum" begin="0s" dur="4s" fill="freeze"/>
  <animateTransform attributeName="transform" attributeType="XML"
    type="rotate" from="0" to="45"
    additive="sum" begin="0s" dur="4s" fill="freeze"/>
</rect>

6.<animateMotion>元素

        <animateMotion>元素让对象沿着任意路径运动,需要在元素中用到path属性,如果希望对象倾斜使其x轴始终平行于路径方向,只要给<animateMotion>元素添加一个rotate:auto属性。


相关工具
使用svg的库:Snap.svg

svg转iconfont:

  • gulp-iconfont
  • gulp-iconfont-css

解决svg不能通过id引用的兼容性

npm install --save svgxuse

合并svg工具:

  • gulp-svg-sprites:只需将用到的 SVG 放到某个文件夹中就可以自动被拼合成 Sprite 并输出对应 CSS。 两个工具都支持生成 PNG 格式的位图作为 Fallback,缺点是生成位图要依赖phantomjs 这个重量级 JS 库。
  • gulp-svg-symbols:只使用 SVG Symbols 而无需 Sprite 支持。
 
//gulpfile.js
var gulp = require('gulp');
var svgSymbols = require('gulp-svg-symbols');
 
gulp.task('sprites', function () {
  return gulp.src('svg/icons/*.svg')
    .pipe(svgSymbols())
    .pipe(gulp.dest('assets'));
});
  • icomoon