【问题标题】:SVG Polygon transitionSVG 多边形过渡
【发布时间】:2016-05-18 01:38:37
【问题描述】:

我正在尝试转换 SVG <polygon> 元素。

codepen 在这里:http://codepen.io/anon/pen/vLQOKr

我有一个这样的多边形:

<svg width="300" height="200" viewBox="0 0 300 200"> <polygon points="0 0, 145 0, 150 20, 155 0, 300 0, 300 200, 0 200, 0 0" /> </svg>

现在,当我更改points 属性的值时,我可以看到浏览器中反映的更改。

我在这里的目标是使用转换(例如transition: all 2s ease 0s)来查看此更改的动画。

这是否可行?

它附带的codepen,当您单击按钮时,points 值正在被替换,但transition 动画不起作用。

谢谢, 卡罗尔

【问题讨论】:

    标签: javascript svg css-transitions


    【解决方案1】:

    我不会推荐 SMIL,因为它的支持有限,并且在不久的将来会被弃用。 CSS 动画对属性不起作用,所以 JS 是唯一的方法。这是一个例子:

    var getPoints = function (isDeeper) {
        return isDeeper ?
            '0 0,  45 0, 150 150, 255 0, 300 0, 300 200, 0 200, 0 0' :
            '0 0, 145 0, 150  20, 155 0, 300 0, 300 200, 0 200, 0 0';
            
    };
    
    var pointsToObj = function (points) {
        var ps = points.match(/\d+/g).map(Number),
            obj = {length: ps.length};
    
        ps.forEach(function (n, i) {
            obj['_' + i] = n;
        });
    
        return obj;
    };
    
    var objToPoints = function (obj) {
        var ps = [];
    
        for (var i = 0; i < obj.length; i++)
            ps.push(obj['_' + i]);
    
        return ps.join(' ');
    };
    
    
    var renderPoints = function ($element, isDeeper) {
        var dest = pointsToObj(getPoints(isDeeper)),
            src = pointsToObj($element.attr('points'));
    
        $(src).animate(dest, {
            step: function (now, fx) {
                src[fx.prop] = fx.now;
                $element.attr('points', objToPoints(src));
            }
        });
    };
    
    $(function () {
    
        var $button = $('button');
        var $element = $('svg polygon');
        var isDeeper = false;
        $button.bind('click', function () {
            isDeeper = !isDeeper;
            renderPoints($element, isDeeper);
        });
    
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    
    <svg width="300" height="200" viewBox="0 0 300 200"
         xmlns="http://www.w3.org/2000/svg" version="1.1"
         xmlns:xlink="http://www.w3.org/1999/xlink">
        <polygon points="0 0, 145 0, 150 20, 155 0, 300 0, 300 200, 0 200, 0 0"/>
    </svg>
    
    <button style="position:fixed;top:0;right:0">Click to change</button>

    【讨论】:

    • 随着 SVG2 的更新,对 svg 的 js 动画的支持将与 SMIL 一样有限。 (您的示例不适用于 FF)。有关弃用 SMIL 的任何链接? (别跟我说 chrome 的“这对我们来说太难了!”)
    • 它确实适用于FF,我的错,错过了按钮:/但是,任何关于官方弃用的链接?
    【解决方案2】:

    您只能对指定为 CSS“属性”的属性使用 CSS 动画。 points 不是其中之一——至少现在还不是。

    不过,您可以使用 SVG 的 SMIL 动画功能对其进行动画处理。

    <svg width="300" height="200" viewBox="0 0 300 200">
      <polygon points="">
        <animate attributeType="XML" attributeName="points"
                 dur="2s" repeatCount="indefinite"
                 values="0 0, 145 0, 150 20, 155 0, 300 0, 300 200, 0 200, 0 0;
                         0 0, 145 0, 150 50, 155 0, 300 0, 300 200, 0 200, 0 0;
                         0 0, 145 0, 150 20, 155 0, 300 0, 300 200, 0 200, 0 0"
                 keyTimes="0; 0.5; 1" 
                 calcMode="spline"
                 keySplines=".5 0 .5 1;
                             .5 0 .5 1" />
      </polygon>
    </svg>

    这里我们指定了三个关键帧:开始、结束和回到开始。对于缓动,有两个 keySplines 值,每个行进方向一个。

    手动触发

    如果您需要能够手动控制动画 - 例如根据您的示例。您可以有两个不同的&lt;animate&gt; 元素。每个方向一个。然后你可以通过调用beginElement()来触发每个动画。你可以找到更多关于here的信息。

    IE 支持

    很遗憾,SMIL 动画在 IE 中不起作用。所以你需要使用FakeSmile JS库来添加对IE的支持。

    或者您可以使用 JS SVG 库之一,例如 SNapJS、RaphaelJS 等。它们中的大多数都具有跨浏览器动画功能。

    或者自己做动画:)

    当然,您也可以自己对路径进行插值。不要将该 Y 坐标设置为 20 或 50,而是使用超时或 requestAnimationFrame 逐步更改它。

    【讨论】:

      猜你喜欢
      • 2019-06-15
      • 2015-07-23
      • 2021-10-26
      • 1970-01-01
      • 2023-04-06
      • 2020-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多