html5之svg

html5

浏览数:192

2019-5-11

HTML5之svg

矢量图,缩放不变形。

1. 绘制基础

1.1标签绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg基础</title>
</head>
<body>
<svg xmlns="http://www.w3.org/2000/svg" width="800" height="800">

   <rect x="10" y="10" width="50" height="50" rx="5" ry="5"         fill="#000"/>

<circle cx="35" cy="100" r="20" />

<ellipse cx="35" cy="160" rx="30" ry="20" />

<line x1="10" y1="200" x2="200" y2="200"
style="stroke:rgb(99,99,99);stroke-width:5" />

<polyline points="10,250 500,250 80,300" style="stroke-width:1" />
    </svg>
</body>
</html>

1.2 js绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>demo</title>
</head>
<body>
    

    <div id="canvas"></div>

    <script>
        var SVG_NS = 'http://www.w3.org/2000/svg';
        var canvas = document.getElementById('canvas');

        function createSVG(){
            var svg = document.createElementNS(SVG_NS, 'svg');
            svg.setAttribute('width', '800');
            svg.setAttribute('height', '800');
            var circle = document.createElementNS(SVG_NS, 'circle');
            circle.setAttribute('cx', '35');
            circle.setAttribute('cy', '50');
            circle.setAttribute('r', '20');
            circle.setAttribute('stroke-width', '5');
            svg.appendChild(circle);
            canvas.appendChild(svg);
            return svg;
        };

        createSVG()


    </script>
</body>
</html>

1.3 path绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg</title>
</head>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" width="800" height="800">
        <!-- 简单点线命令 -->
        <!-- <path d="M10 10 H 90 V 90 H 10 L 10 10 " /> -->

        <!-- 三次贝塞尔曲线需要定义一个点和两个控制点 -->
        <!-- <path d="M10 110 C 0 140, 60 140, 50 110" stroke="black" fill="transparent"/> -->
        
        <!-- 三次贝塞尔曲线简写 -->
        <!-- <path d="M10 80 C 40 10, 65 10, 95 80 S 150 150, 180 80" stroke="black" fill="transparent"/> -->
       
       <!--二次贝塞尔曲线只需要一个控制点,用来确定起点和终点的曲线斜率-->
        <!-- <path d="M10 80 Q 95 10 180 80" stroke="black" fill="transparent"/> -->

        <!-- 二次贝塞尔曲线简写 -->
        <!-- <path d="M10 80 Q 52.5 10, 95 80 T  180 80" stroke="black" fill="transparent"/> -->
        
        <!-- 弧形 -->
        <!-- x轴半径,y轴半径,旋转情况,弧线角度,弧线方向, -->
        <path d="M10 315
           L 110 215
           A 30 50 0 0 1 162.55 162.45
           L 172.55 152.45
           A 30 50 -45 0 1 215.1 109.9
           L 315 10" stroke="black" fill="green" stroke-width="2" fill-opacity="0.5"/>
    </svg>
</body>
</html>

1.4 文本绘制

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg</title>
</head>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" width="800" height="800">
        <text x="20" y="90" dx="10 20 20 60" dy="10" style="font-size: 50px;font-family:'Arial'">SVGA文本插入</text>
        <path d="M30,0 V200,M0,100H200" stroke="red"></path>
    </svg>
</body>
</html>

2.动画基础

2.1 直线动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg动画</title>
</head>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" width="10000" height="1000">
        <rect x="100" y="100" width="100" height="100" fill="red">
            <animate
                id="goright"
                attributeType="XML"
                attributeName="x"
                begin="0;goleft.end"
                form="100"
                to="500"
                dur="2s"
                fill="freeze"
            ></animate>
             <animate
                id="goleft"
                attributeType="XML"
                attributeName="x"
                begin="goright.end"
                form="500"
                to="100"
                dur="2s"
                fill="freeze"
            ></animate>
        </rect>
    </svg>
</body>
</html>

2.2 弧线动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg动画</title>
</head>
<body>
    <svg 
        xmlns="http://www.w3.org/2000/svg" 
        width="1000" 
        height="1000"
    >
        <rect x="200" y="0" width="100" height="100" fill="red">
            <animateTransform
                id="rotate"
                attributeName="transform"
                attributeType="XML"
                type="rotate"
                form="0"
                to="60"
                dur="2s"
                fill="freeze"
            ></animate>
        </rect>
    </svg>
</body>
</html>

2.3 轨迹动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg动画</title>
</head>
<body>
    <svg 
        xmlns="http://www.w3.org/2000/svg" 
        width="10000" 
        height="1000"
        viewBox="-400 -400 800 800"
    >
        <rect 
            x="-25" 
            y="-25" 
            width="100" 
            height="100" 
            fill="rgba(0,255,255,.6)"
        >
            <!-- <animateMotion
                path="M 0 0 L 100 100 A 200 200 0 1 0 0 -100"
                dur="3s"
                rotate="auto"
            >
            </animateMotion> -->
        
            <animateMotion
                dur="3s"
                rotate="auto"
            >
                <mpath xlink:href="#motion-path"></mpath>
            </animateMotion>
        </rect>
        <path 
            id="motion-path"
            d="M 0 0 L 100 100 A 200 200 0 1 0 0 -100"
            stroke="red"
            fill="none"
        ></path>
    </svg>
</body>
</html>

2.4 文本动画

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg</title>
</head>
<body>
    <svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
        <defs>
            <pattern id="grid" x="0" y="0" width="20" height="20" patternUnits="userSpaceOnUse">
                <path stroke="#F0F0F0" fill="none" d="M0,0H20V20"></path>
            </pattern>
        </defs>
        <rect width="1200" height="1000" fill="url(#grid)"></rect>

        <text id="sintext" x="100" y="160" style="font-size: 14px;font-family:'Arial'">ABCDEFGHIJKLMNOPQRSTUVWXYZ</text>
        <path d="M100,0 V200M0,100H200" transform="translate(0,60)" stroke="red"></path>
    </svg>

    <script>
        var n = 26;
        var x = [];
        var y = null; 
        var i = n;
        var s = 100;
        var w = 0.02;
        var t = 0;

        while(i--) x.push(10);

        function arrange(t){
            y = [];
            var ly = 0, cy;
            for(i=0;i<n;++i){
                cy = -s*Math.sin(w*i*20+t);
                y.push(cy-ly);
                ly = cy;
            }
         
        }
        //渲染函数
        function render(){
            sintext.setAttribute('dx',x.join(' '));
            sintext.setAttribute('dy',y.join(' '));

        }
        //动画函数
        function frame(){
            t+=0.02;
            arrange(t);
            render();
            requestAnimationFrame(frame);
        };
        frame()
    </script>
</body>
</html>

2.5 动画综合练习

vector.js
(function(){
            function Vector(x,y){
                this.x = x || 0;
                this.y = y || 0;
            }
            Vector.prototype = {
                constructor:Vector,
                square:function(){
                    return this.x * this.x + this.y * this.y; 
                },
                length:function(){
                    return Math.sqrt(this.square()); 
                },
                add:function(q){
                    return new Vector(this.x + q.x,this.y+q.y); 
                },
                minus:function(q){
                    return new Vector(this.x - q.x,this.y-q.y);  
                },
                multipy:function(scale){
                    return new Vector(this.x*scale,this.y*scale);  
                },
                normalize:function(length){
                    if(length === undefined){
                        length = 1;
                    }
                    return this.multipy(length / this.length());
                }
            };
            Vector.fromPoints = function(p1,p2){
                return new Vector(p2.x - p1.x, p2.y - p1.y);
            };
            window.Vector = Vector;
        })();
index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>svg动画</title>
    <style>
        html,body,svg{
            margin:0;
            padding:0;
            width: 100%;
            height:100%;
        }
    </style>
</head>
<body>
    <svg 
        width="10000" 
        height="1000"
        viewBox="-400 -400 800 800"
    >
        <path 
            id="links"
            stroke="gray"
            fill="none"
        ></path>
    </svg>
    
    <script src="vector.js"></script>
    <script>
        var points = 'a,b,c'.split(',').map(function(name,index,arr){
            return {
                name:name,
                color:'hsl('+ (360*index/arr.length) + ',100%,60%)'
            };
        });
        var relation = 300;
        var svg = document.querySelector('svg');
        var k = 0.05;
        var Vector = window.Vector;

        function random(min,max){
            return Math.round(min +(max - min) *Math.random());
        };
        points.forEach(function(point){
            var circle = document.createElementNS('http://www.w3.org/2000/svg','circle');
            var x = random(-400,400);
            var y = random(-400,400);
            circle.setAttribute('cx',x);
            circle.setAttribute('cy',y);
            circle.setAttribute('r',10);
            circle.setAttribute('fill',point.color);
            svg.appendChild(circle);

            point.circle = circle;
            point.s = new Vector(x,y);
            point.v = new Vector();
            point.a = new Vector();
        });


        var lastFrameTime = +new Date();
        function update(){
            var frameTime = +new Date();
            var t = frameTime - lastFrameTime;
            t/=200;

            //点位置更新
            points.forEach(function(pa){
                var f = new Vector();
                //计算合力
                points.forEach(function(pb){
                    if(pa == pb) return;
                    var x = Vector.fromPoints(pa.s,pb.s);
                    var delta = x.length() -relation;

                    //f = k * x
                    f = f.add(x.normalize(delta * k));
                });
                pa.a = f;
                pa.v = pa.v.add(pa.a.multipy(t)).multipy(0.98);
                pa.s = pa.s.add(pa.v.multipy(t));
                pa.circle.setAttribute('cx',pa.s.x);
                pa.circle.setAttribute('cy',pa.s.y);
            });

            //连线更新
            var linkPath = [];
            points.forEach(function(pa){
                var sa = pa.s;
                points.forEach(function(pb){
                    if(pa == pb) return;
                    var sb = pb.s;
                    linkPath = linkPath.concat([
                        'M',sa.x,sa.y,
                        'L',sb.x,sb.y
                    ]);
                });
            });
            document.getElementById('links').setAttribute('d',linkPath.join(' '))
            lastFrameTime = frameTime;
            window.requestAnimationFrame(update);
        };

        window.requestAnimationFrame(update);
    </script>
</body>
</html>

3.图案动画

<!DOCTYPE html>
<html>
<head>
<meta name="description" content="满天星与灯塔">
  <meta charset="utf-8">
  <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 id='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>
    <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="white" mask="url(#moon-mask)"></circle>
    </g>
    <g id="light-tower" transform="translate(250,0)">
      <defs>
        <linearGradient id="tower" x1="0" y1="0" x2="1" y2="0">
          <stop offset="0" stop-color="#999"></stop>
          <stop offset="1" stop-color="#333"></stop>
        </linearGradient>
        <radialGradient id="light" cx="0.5" cy="0.5" r="0.5">
          <stop offset="0" stop-color="rgba(255,255,255,.8)"></stop>
          <stop offset="1" stop-color="rgba(255,255,255,0)"></stop>
        </radialGradient>
        <clipPath id="light-mask">
          <polygon points="0 0 -400 -15 -400 15" fill="rgba(255,0,0,0.5)">
            <animateTransform attributeName="transform" attributeType="XML" type="rotate" from="0" to="360" dur="7s" repeatCount="indefinite"></animateTransform>
          </polygon>
          <circle cx="0" cy="0" r="2"></circle>
        </clipPath>
      </defs>
      <polygon points="0 0 5 50 -5 50" fill="url(#tower)"></polygon>
      <ellipse cx="0" cy="0" rx="300" ry="100" fill="url(#light)" clip-path="url(#light-mask)"></ellipse>
      
    </g>
  </svg>


  <script>
      
    var paper = document.getElementById('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;
      while(starCount--){
        star = use(starRef);
        star.setAttribute('opacity', random(0.1, 0.4));
        star.setAttribute('transform', 'translate(' + random(-400, 400) + ',' + random(-300, 50) + ')' + ' scale(' + random(0.1, 0.6) + ')');
        starGroup.appendChild(star);
      }
    }
  </script>
</body>
</html>

这篇是对慕、课、网svg教程的笔记,链接贴在下面,大家可以去看看:

走进SVG:https://www.imooc.com/learn/143

作者:旧城