svg

SVG基本图形和属性

基本图形

<rect> 长方形 x y width height rx ry
<circle>  圆形 cx cy r
<ellipse> 椭圆 cx cy rx ry
<line> 直线  x1 y1 x2 y2
<polyline> 折线 points="x1 y1 x2 y2 x3 y3"
<polygon> 多边形 points="x1 y1 x2 y2 x3 y3"

基本属性

fill 填充颜色
stroke 描边颜色
stroke-width 描边宽度
transform 与父坐标系的变形

基本操作API

创建图形
document.createElementNS(ns, tagName)

添加图形
element.appendChild(childElement)

设置/获取属性
element.setAttribute(name, value)
element.getAttribute(name)

SVG 图形分组

标签创建分组

属性继承

transform 属性定义坐标变换

可以嵌套使用

Path

Path字符串

<path d="M0,0L10,20C30-10,40,20,100,100" stroke="red">

Path 命令总汇

命令基本规律

  • 区分大小写:大写代表坐标参数为绝对位置,小写则为相对位置
  • 最后的参数表示最终要到达的位置
  • 上一个命令结束的位置就是下一个命令开始的位置
  • 命令可以重复参数表示重复执行同一条命令

移动和直线命令

弧线命令

贝塞尔曲线命令 - 二次贝塞尔曲线命令

贝塞尔曲线命令 - 三次贝塞尔曲线命令

贝塞尔曲线命令 - 光滑曲线

图形引用、裁切和蒙版

use标签创建图形引用

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body {
                margin: 0;
                padding: 0;
                width: 100%;
                height: 100%;
                background: #001122;
                line-height: 0;
                font-size: 0;
            }
        </style>
    </head>
    <body>
        <svg width="100%" height="100%"
             viewBox="-400 -300 800 600"
             preserveAspectRatio="xMidYMid slice">
            <defs>
                <polygon id="star" points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" fill="white"></polygon>
            </defs>
            <g id="star-group"></g>
        </svg>
    </body>
    <script>
        var paper = document.querySelector('svg');
        var SVG_NS = "http://www.w3.org/2000/svg";
        var XLINK_NS = "http://www.w3.org/1999/xlink";

        renderStar();

        function use(origin) {
            var _use = document.createElementNS(SVG_NS, "use");
            _use.setAttributeNS(XLINK_NS, 'xlink:href', "#" + origin.id);
            return _use;
        }

        function random(min, max) {
            return min + (max - min) * Math.random();
        }

        function renderStar() {
            var starRef = document.getElementById('star');
            var starGroup = document.getElementById('star-group');
            var starCount = 500;

            var star;
            while (starCount--) {
                star = use(starRef);
                star.setAttribute('transform', 'translate(' + random(-400, 400) + ', ' + random(-300, 50) + ')'
                    + 'scale(' + random(0.1, 0.6) + ')'
                );

                starGroup.appendChild(star);
            }

        }
    </script>
</html>

clipPath 标签裁切图形

            <g id="light-tower" transform="translate(200, 0)">
                <defs>
                    <clipPath id="light-clip">
                        <polygon points="0 0 -300 -15 -400 15" fill="rgba(255, 255, 255, 0.5)"></polygon>
                    </clipPath>
                </defs>
                <polygon points="0 0 5 50 -5 50" fill="white"></polygon>
                <ellipse cx="0" cy="0" rx="300" ry="100" fill="rgba(255, 255, 255, 0.3)"
                         clip-path="url(#light-clip)"></ellipse>
            </g

use、clip、mask 综合demo

<use> xlink:href="#id"

<clipPath> clip-path="url(#clip-id)"

<mask> mask="url(mask-id)"

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body {
                margin: 0;
                padding: 0;
                width: 100%;
                height: 100%;
                background: #001122;
                line-height: 0;
                font-size: 0;
            }
        </style>
    </head>
    <body>
        <svg width="100%" height="100%"
             viewBox="-400 -300 800 600"
             preserveAspectRatio="xMidYMid slice">
            <defs>
                <polygon id="star" points="0 -10 2 -2 10 0 2 2 0 10 -2 2 -10 0 -2 -2" fill="white"></polygon>
            </defs>
            <g id="real">
                <g id="star-group"></g>
                <g id="light-tower" transform="translate(200, 0)">
                    <defs>
                        <clipPath id="light-clip">
                            <polygon points="0 0 -300 -15 -400 15" fill="rgba(255, 255, 255, 0.5)"></polygon>
                        </clipPath>
                    </defs>
                    <polygon points="0 0 5 50 -5 50" fill="white"></polygon>
                    <ellipse cx="0" cy="0" rx="300" ry="100" fill="rgba(255, 255, 255, 0.3)"
                             clip-path="url(#light-clip)"></ellipse>
                </g>
                <g id="moon-group">
                    <mask id="moon-mask">
                        <circle cx="-250" cy="-150" r="100" fill="white"></circle>
                        <circle cx="-200" cy="-200" r="100" fill="black"></circle>
                    </mask>

                    <circle cx="-250" cy="-150" r="100" fill="yellow" mask="url(#moon-mask)"></circle>
                </g>
            </g>
            <g id="reflect" transform="translate(0 50)" mask="url(#fading)">
                <defs>
                    <linearGradient id="fade" x1="0" x2="0" y1="0" y2="1">
                        <stop offset="0" stop-color="rgba(255, 255, 255, 0.3)"></stop>
                        <stop offset="0.5" stop-color="rgba(255, 255, 255, 0)"></stop>
                    </linearGradient>
                    <mask id="fading">
                        <rect x="-400" y="0" width="800" height="300" fill="url(#fade)"></rect>
                    </mask>
                </defs>
                <use xlink:href="#real" transform="scale(1, -1) translate(0 -50)"></use>
            </g>
            <line x1="-400" y1="50" x2="400" y2="50" stroke="white"></line>
        </svg>
    </body>
    <script>
        var paper = document.querySelector('svg');
        var SVG_NS = "http://www.w3.org/2000/svg";
        var XLINK_NS = "http://www.w3.org/1999/xlink";

        renderStar();

        function use(origin) {
            var _use = document.createElementNS(SVG_NS, "use");
            _use.setAttributeNS(XLINK_NS, 'xlink:href', "#" + origin.id);
            return _use;
        }

        function random(min, max) {
            return min + (max - min) * Math.random();
        }

        function renderStar() {
            var starRef = document.getElementById('star');
            var starGroup = document.getElementById('star-group');
            var starCount = 500;

            var star;
            while (starCount--) {
                star = use(starRef);
                star.setAttribute('opacity', random(0.5, 0.8));
                star.setAttribute('transform', 'translate(' + random(-400, 400) + ', ' + random(-300, 50) + ') '
                    + 'scale(' + random(0.1, 0.6) + ')'
                );

                starGroup.appendChild(star);
            }

        }
    </script>
</html>

SVG动画

动画原理

值在时间上的变化

SMIL

http://www.zhangxinxu.com/wordpress/?p=4333

定位动画目标

  • Internal Resource Identifier 定位
    <animate xlink:href="url(#rect1)"> </animate>

  • 被包含在目标元素里

<rect x="0" ...>
      <animate> </animate>
</rect>

基本动画

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body, svg {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    <body>
        <svg>
            <rect x="100" y="100" width="100" height="50" fill="red">
                <!--
                <animate attributeType="XML"
                         attributeName="x"
                         from="100"
                         to="500"
                         dur="1s"
                         fill="freeze"
                         repeatCount="indefinite"
                ></animate>
                -->

                <animate id="goright"
                         attributeType="XML"
                         attributeName="x"
                         begin="0; goleft.end"
                         from="100"
                         to="500"
                         dur="1s"
                         fill="freeze"
                ></animate>
                <animate id="goleft"
                         attributeType="XML"
                         attributeName="x"
                         begin="goright.end + 1s"
                         from="500"
                         to="100"
                         dur="1.5s"
                         fill="freeze">
                </animate>

                <animate
                        attributeType="XML"
                        attributeName="fill"
                        from="red"
                        to="yellow"
                        dur="6s"
                        fill="freeze"
                >

                </animate>
            </rect>
        </svg>
    </body>
</html>

变换动画

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body, svg {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    <body>
        <svg viewBox="-400 -400 800 800">
            <rect x="100" y="100" width="100" height="50" fill="red">
                <!-- 两个 animateTransform 相互覆盖-->
                <animateTransform
                        id="rotate"
                        attributeType="XML"
                        attributeName="transform"
                        type="rotate"
                        from="0"
                        to="360"
                        dur="3s"
                        fill="freeze"
                        repeatCount="indefinite"
                ></animateTransform>
                <animateTransform
                        id="scale"
                        attributeType="XML"
                        attributeName="transform"
                        type="scale"
                        from="1"
                        to="2"
                        dur="3s"
                        fill="freeze"
                        repeatCount="indefinite">
                </animateTransform>
            </rect>
        </svg>
    </body>
</html>

路径动画

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body, svg {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
            }
        </style>
    </head>
    <body>
        <svg viewBox="-400 -400 800 800">
            <rect x="-25" y="-25" width="50" height="50" fill="rgba(0, 255, 255, .6)">
                <!--
                <animateMotion
                        path="M 0 0L 100 100A 200 200 0 1 0 0 -100"
                        dur="3s"
                        rotate="auto">
                </animateMotion>
                -->

                <animateMotion
                        dur="3s"
                        rotate="auto">
                    <mpath xlink:href="#motion-path"></mpath>   <!-- 不需要写url -->
                </animateMotion>
            </rect>
            <path id="motion-path" d="M 0 0L 100 100A 200 200 0 1 0 0 -100" stroke="gray" stroke-width="2"
                  fill="none"></path>
        </svg>
    </body>
</html>

Scripting Animation - 力导向图

弹簧模型

动画demo

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            html, body, svg {
                width: 100%;
                height: 100%;
                margin: 0;
                padding: 0;
                text-align: center;
            }

            a {
                display: inline-block;
                padding: 10px 30px;
                background: #b9b9b9;
                border-radius: 30px;
                cursor: pointer;
                margin-top: 20px;
            }
        </style>
    </head>
    <body>
        <a id="btn">重复点击激活动画</a>
        <svg viewBox="0 0 360 160" version="1.1" xmlns="http://www.w3.org/2000/svg">
            <g transform="translate(0, -100)">
                <path stroke="#000" stroke-width="5" stroke-linecap="butt" fill="white" stroke-linejoin="miter"
                      fill-opacity="0.3" stroke-opacity="1" id="logo-border"
                      d="M 68 20 L 10 45 L 10 140 L 222 140 L 280 115 L 280 20 Z">
                </path>
                <defs>
                    <style>
                        .cls {
                            font-size: 46px;
                            text-anchor: middle;
                            font-weight: bold;
                            font-family: "PingFang SC";
                        }
                    </style>
                </defs>
                <g transform="translate(47 68)">
                    <text id="text-1" class="cls" transform="translate(150 0) ">
                        <tspan x="0">测</tspan>
                    </text>
                </g>
                <g transform="translate(97 68)">
                    <text id="text-2" class="cls" transform="translate(150 0) ">
                        <tspan x="0">试</tspan>
                    </text>
                </g>
                <g transform="translate(197 121)">
                    <text id="text-3" class="cls" transform="translate(-150 0) ">
                        <tspan x="0">代</tspan>
                    </text>
                </g>
                <g transform="translate(247 121)">
                    <text id="text-4" class="cls" transform="translate(-150 0) ">
                        <tspan x="0">码</tspan>
                    </text>
                </g>
                <!--
                <path fill="#000" fill-opacity="1" stroke-opacity="0" id="text-1" d=" M28.9,64.8h40.3v6.4H28.9V64.8z M67.8,38.3v6.3H30.3v-6.3h15.3v-7.1l8.1,0.4c0,0.5-0.4,0.8-1.4,1v5.7H67.8z M41.6,45.7
      c1.7,5.3,2.9,11.8,3.2,16.4l-6.7,1.7c-0.1-4.4-1.3-11.3-2.7-16.4L41.6,45.7z M64.3,47.5c-0.2,0.4-0.7,0.7-1.5,0.8
      c-1.1,5.3-3.4,11.8-5.3,16.1l-6-1.8C53.2,58,55,51,55.7,45.6L64.3,47.5z" transform="translate(150 0)"></path>
                -->
                <!--
                <path fill="#000" fill-opacity="1" stroke-opacity="0" id="text-2" d="M116.9,53.9H99.3c-0.3,0.5-0.6,1.1-0.9,1.6h13.2l1.3-0.1l3.4,0.5c0,0.4-0.1,1-0.2,1.5c-1.1,15.1-2.1,15.5-10.2,15.3
      c0-1.1-0.4-2.5-0.8-3.8c-1.1,1.7-2.2,3.2-3.4,4.3c-1.1-1.2-2.9-2.7-4.5-3.6c2.8-2,5.1-5.5,6.7-9.2h-1.5c-2.2,4.1-6.1,8.6-9.5,11.1
      c-1.1-1.2-2.8-2.8-4.2-3.7c2.9-1.6,5.8-4.4,8-7.4h-1.7c-1.6,1.7-3.3,3.2-5.2,4.4c-0.7-0.8-2.1-2.1-3.2-3c-3.2,1.4-6.2,2.8-8.5,3.7
      c0,0.5-0.4,0.8-0.7,0.9l-2.4-6.9c1.4-0.4,3.2-1,5.1-1.7V46.2h-4.1v-6H80v-9l7.2,0.4c0,0.5-0.4,0.7-1.3,0.9v7.8h3.6v6h-3.6v9.7
      l3.2-1.2l0.8,3.5c1.3-1.3,2.4-2.7,3.3-4.3h-4.6v-5.3h28.2V53.9z M113.9,32.1v15.3H92.6V32.1H113.9z M108,37.7v-1.3h-9.8v1.3H108z
      M108,43.1v-1.3h-9.8v1.3H108z M108.9,60.5c-0.8,2.5-1.9,5-3.2,7.4c0.7,0,1.2,0,1.6,0c0.6,0,0.9-0.1,1.3-0.5
      c0.5-0.6,1-2.5,1.4-6.9H108.9z" transform="translate(150 0)"></path>
                -->
                <!--
                <path fill="#000" fill-opacity="1" stroke-opacity="0" id="text-3" d="M189.5,111.6v0.4c1.3,0.7,5,3.2,5.9,3.9l-3.5,4.5c-0.6-0.7-1.5-1.6-2.4-2.5v7.8h-6.1v-6.7c-1.4,1.7-2.9,3.2-4.3,4.4
      c-1-1.3-2.8-3.4-4.1-4.4c2.7-1.7,5.5-4.5,7.4-7.3h-6.2v-5.2h7.1v-2.5h-7.6v-5.1h3.8c-0.3-1.4-0.7-2.9-1.3-4.2l2.7-0.8h-4.4v-5.1
      h6.8v-4.3l7.4,0.4c0,0.5-0.4,0.8-1.3,0.9v3h6.5v5.1h-3.6l3.3,0.8c-0.1,0.3-0.5,0.5-1.2,0.6c-0.4,1.1-1.1,2.4-1.7,3.6h4.1v5.1h-6.2
      c-0.2,0.3-0.5,0.5-1.2,0.6v1.9h6.7v5.2H189.5z M187.3,98.7c0.6-1.5,1.2-3.4,1.6-5h-5.6c0.7,1.6,1.3,3.6,1.5,5H187.3z M216.7,98.6
      v5.8h-3.8v21.1h-6.1v-21.1h-3.1c-0.1,6.4-1.2,15.5-6.7,21.3c-0.8-1.4-3-3.5-4.5-4.3c4.7-5.2,5.2-12.4,5.2-18.2V88.3l2.9,0.8
      c3.7-1.3,7.5-3.1,9.9-4.7l5.8,4.5c-0.3,0.3-0.8,0.3-1.3,0.3c-2.9,1.6-7.2,3.2-11.3,4.4v5H216.7z"
                      transform="translate(-150 0)"></path>
                      -->
                <!--
                <path fill="#000" fill-opacity="1" stroke-opacity="0" id="text-4" d="M241.5,101.4h-11.2v24.1h-6.1V85.9h17.3V101.4z M235.6,90.2h-5.3v1.4h5.3V90.2z M230.3,97h5.3v-1.5h-5.3V97z M261.4,85.9
      v32.6c0,5.2-1.5,6.9-9.2,6.9c-0.1-1.5-0.7-3.7-1.4-5.4v4.2h-5.6v-2.3c-4.4,0.3-8.6,0.6-11.5,0.8c-0.1,0.4-0.4,0.6-0.8,0.6
      l-1.3-5.1l2.7-0.1V107h-2.2v-4.2h20.9v4.2h-2.3v12.1c1.4,0.1,3,0.1,3.6,0.1c0.6,0,0.8-0.2,0.8-0.8v-16.9h-11.4V85.9H261.4z
       M245.2,107h-5.4v1.3h5.4V107z M239.8,111.6v1.3h5.4v-1.3H239.8z M239.8,117.9l5.4-0.3v-1.3h-5.4V117.9z M255.2,90.2h-5.5v1.4h5.5
      V90.2z M249.7,97.2h5.5v-1.6h-5.5V97.2z" transform="translate(-150 0)"></path>
                 -->
            </g>

            <!--
            <g transform="translate(0, 100)">
                <path stroke="#000" stroke-width="5" stroke-linecap="butt" fill="red" stroke-linejoin="miter"
                      fill-opacity="0.3" stroke-opacity="1" id="logo-border11"
                      d="M10,20 L10,103 L45,140 L280,140 L280,57 L245,20 Z"></path>
            </g>
            -->


            <!--
            <animate xlink:href="#logo-border" attributeName="d" dur="500ms" id="logo-anim"
                     from="M10,20 L10,103 L45,140 L280,140 L280,57 L245,20 Z;"
                     to="M68,20 L10,45 L10,140 L222,140 L280,115 L280,20 Z;" begin="indefinite" fill="freeze"
                     additive="replace"></animate>

            <animateTransform id="text-1-animate-transform" xlink:href="#text-1" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            <animateTransform id="text-2-animate-transform" xlink:href="#text-2" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            <animateTransform id="text-3-animate-transform" xlink:href="#text-3" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="-150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            <animateTransform id="text-4-animate-transform" xlink:href="#text-4" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="-150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            -->
            <animate xlink:href="#logo-border" attributeName="d" dur="500ms" id="logo-anim"
                     from="M68,20 L10,45 L10,140 L222,140 L280,115 L280,20 Z;"
                     to="M10,20 L10,103 L45,140 L280,140 L280,57 L245,20 Z;"
                     begin="indefinite" fill="freeze"
                     additive="replace"></animate>

            <animateTransform id="text-1-animate-transform" xlink:href="#text-1" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            <animateTransform id="text-2-animate-transform" xlink:href="#text-2" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            <animateTransform id="text-3-animate-transform" xlink:href="#text-3" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="-150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
            <animateTransform id="text-4-animate-transform" xlink:href="#text-4" attributeName="transform"
                              attributeType="XML" type="translate" from="0,0" to="-150,0" dur="500ms"
                              begin="logo-anim.begin+0s" fill="freeze" additive="replace"></animateTransform>
        </svg>
    </body>
    <script>
        var btn = document.getElementById("btn");
        var anim = document.getElementById("logo-anim");
        var text1Anim = document.getElementById("text-1-animate-transform");
        var text2Anim = document.getElementById("text-2-animate-transform");
        var text3Anim = document.getElementById("text-3-animate-transform");
        var text4Anim = document.getElementById("text-4-animate-transform");

        var flag = false;

        btn.addEventListener("click", function () {
            anim.beginElement();

            // 修改各个动画的起始结束
            if (flag) {
                // to="M10,20 L10,103 L45,140 L280,140 L280,57 L245,20 Z;"
                // from="M68,20 L10,45 L10,140 L222,140 L280,115 L280,20 Z;"
                anim.setAttribute("to", "M68,20 L10,45 L10,140 L222,140 L280,115 L280,20 Z;");
                anim.setAttribute("from", "M10,20 L10,103 L45,140 L280,140 L280,57 L245,20 Z;");


                text1Anim.setAttribute("from", "0,0");
                text1Anim.setAttribute("to", "150, 0");
                text2Anim.setAttribute("from", "0,0");
                text2Anim.setAttribute("to", "150, 0");

                text3Anim.setAttribute("from", "0,0");
                text3Anim.setAttribute("to", "-150, 0");
                text4Anim.setAttribute("from", "0,0");
                text4Anim.setAttribute("to", "-150, 0");
                flag = false;
            } else {
                anim.setAttribute("to", "M10,20 L10,103 L45,140 L280,140 L280,57 L245,20 Z;");
                anim.setAttribute("from", "M68,20 L10,45 L10,140 L222,140 L280,115 L280,20 Z;");

                text1Anim.setAttribute("to", "0,0");
                text1Anim.setAttribute("from", "150, 0");
                text2Anim.setAttribute("to", "0,0");
                text2Anim.setAttribute("from", "150, 0");

                text3Anim.setAttribute("to", "0,0");
                text3Anim.setAttribute("from", "-150, 0");
                text4Anim.setAttribute("to", "0,0");
                text4Anim.setAttribute("from", "-150, 0");
                flag = true;
            }

        })
    </script>
</html>
posted @ 2020-09-01 15:58  Au_ww  阅读(186)  评论(0编辑  收藏  举报