动画Svg路径D坐标

时间:2017-02-26 11:22:44

标签: javascript jquery html animation svg

拥有svg path坐标:

M 8,21 L 12,21 L 17,26 L 17,10 L 12,15 L 8,15 L 8,21 z M 19,14 L 19,22 C 20.48,21.32 21.5,19.77 21.5,18 C 21.5,16.26 20.48,14.74 19,14 z M 19,11.29 C 21.89,12.15 24,14.83 24,18 C 24,21.17 21.89,23.85 19,24.71 L 19,26.77 C 23.01,25.86 26,22.28 26,18 C 26,13.72 23.01,10.14 19,9.23 L 19,11.29 z

按下这些内容时,如何协调svg路径顺利更改:

M 8,21 L 12,21 L 17,26 L 17,10 L 12,15 L 8,15 L 8,21 Z M 19,14 L 19,22 C 20.48,21.32 21.5,19.77 21.5,18 C 21.5,16.26 20.48,14.74 19,14 Z

提前谢谢。

4 个答案:

答案 0 :(得分:1)

使用SVG动画的解决方案:

为此,我们需要使用正确的坐标在两个动画中创建一个路径,当您按下按钮时,脚本将运行其中一个动画

在线示例:

[0][0] = [0]
[1][0] = [length]
[N][K] = [(length*N) + K]
$(function() {
  $('#button').click(function() {
    if ($('#button.-pause').length == 1 && $('#button.-play').length == 0) {
      $('#button svg path .button-play')[0].beginElement();
      $('#button').removeClass('-pause');
      $('#button').addClass('-play');
    } else {
      $('#button svg path  .button-pause')[0].beginElement();
      $('#button').removeClass('-play');
      $('#button').addClass('-pause');
    };
    return false;
  });
});
@import url('data:text/css;charset=UTF-8,body { font-family: Tahoma, sans-serif; font-size: 0.8rem; } a {display: inline-block;color: #427fed;cursor: pointer;text-decoration: none;margin-right:5px;} a:hover {text-decoration: underline;} button { -webkit-padding-end: 10px; -webkit-padding-start: 10px; min-height: 2em; min-width: 4em; padding-bottom: 1px; -webkit-appearance: none; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } button:hover { background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } button:active { background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } button:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; } select { -webkit-padding-end: 20px; -webkit-padding-start: 6px; background-position: right center; background-repeat: no-repeat; min-height: 2em; min-width: 4em; padding-bottom: 0; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } select:hover { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } select:active { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } select:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; }');

#button {
  min-width: auto;
  padding: 3px 3px 0 1px;
  cursor: pointer;
}

答案 1 :(得分:1)

为了在按钮中包含的svg路径之间采用平滑且稍微简单的方法,我将使用不透明度。在视觉上,用户看到平滑过渡。 (另一个需要考虑的选择)

以下示例使用您的原始路径。

<!DOCTYPE HTML>

<html>

<head>
  <title>Transition opacity in button</title>
</head>

<body>
<button onClick=pathOpacity()>
<svg width=30 height=30>
<path opacity=0 id=path0 d="M 8,21 L 12,21 L 17,26 L 17,10 L 12,15 L 8,15 L 8,21 z M 19,14 L 19,22 C 20.48,21.32 21.5,19.77 21.5,18 C 21.5,16.26 20.48,14.74 19,14 z M 19,11.29 C 21.89,12.15 24,14.83 24,18 C 24,21.17 21.89,23.85 19,24.71 L 19,26.77 C 23.01,25.86 26,22.28 26,18 C 26,13.72 23.01,10.14 19,9.23 L 19,11.29 z" stroke='black' stroke-width="1" fill="none" />
<path opacity=1 id=path1 d="M 8,21 L 12,21 L 17,26 L 17,10 L 12,15 L 8,15 L 8,21 Z M 19,14 L 19,22 C 20.48,21.32 21.5,19.77 21.5,18 C 21.5,16.26 20.48,14.74 19,14 Z" stroke='black' stroke-width="1" fill="none" />
</svg>
</button>
<script>
//---click button---
function pathOpacity()
{
var FPS=100  //----frames per second---
var opacity = 0//---starting value---
var opacity0 =+path0.getAttribute("opacity")
var opacity1 =+path1.getAttribute("opacity")

function frame()
{
    opacity+=.02
    if(opacity0==0)
    {
        path0.setAttribute("opacity",opacity)
        path1.setAttribute("opacity",1-opacity)
    }
    else
    {
        path0.setAttribute("opacity",1-opacity)
        path1.setAttribute("opacity",opacity)
    }
    if(opacity >= 1)
    {
        clearInterval(iT)

        if(opacity0==0)
        {
            path0.setAttribute("opacity",1)
            path1.setAttribute("opacity",0)
        }
        else
        {
            path0.setAttribute("opacity",0)
            path1.setAttribute("opacity",1)
        }
    }
}
//---start interval timer---
var iT = setInterval(frame, 1000/FPS ) //---draw every 10ms ---
}
</script>
</body>

</html>

答案 2 :(得分:0)

使用JQuery解决此问题的方法:

$.prototype.animatePathD = function(d, o) {
  // Подстраиваем под разные браузера
  var i = $('body *').length;
  $('body').append('<svg id="animatepathd' + i + '" style="display:none"><path d="' + d + '"></svg>');
  d = $('#animatepathd' + i + ' path').attr('d');
  $('#animatepathd' + i).remove();

  var e = this,
    d = {
      primary: {
        frame: $(e).attr('d').replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'),
        coord: $(e).attr('d').replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',')
      },
      final: {
        frame: d.replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'),
        coord: d.replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',')
      }
    },
    opt = o;
  if (opt == undefined) {
    opt = {
      duration: 1000,
      easing: 'linear'
    };
  } else if (/^\d+$/.exec(opt) != null) {
    opt = {
      duration: opt,
      easing: 'linear'
    };
    if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) {
      opt.duration = 1000
    };
  } else {
    if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) {
      opt.duration = 1000
    };
    if (opt.easing != 'swing' && opt.easing != 'linear') {
      opt.easing = 'linear'
    };
  };
  if (d.primary.frame == d.final.frame) {
    var funPoint = {
      primary: {},
      final: {},
      list: '',
      frame: "'" + d.final.frame + "'"
    };
    for (var i = 0; i < d.primary.coord.length; i++) {
      funPoint.primary['c' + i] = d.primary.coord[i];
      funPoint.final['c' + i] = d.final.coord[i];
      funPoint.list = ', c' + i;
      if (d.primary.coord.length != 0) {
        funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+obj.elem.c" + i + "+'")
      } else {
        funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+c" + i + "+'")
      };
    };
    funPoint.list = funPoint.list.replace(/^\,\ (.+)$/, '$1');
    $(funPoint.primary).animate(funPoint.final, {
      duration: opt.duration,
      easing: opt.easing,
      step: function(c0, obj) {
        $(e).attr('d', eval(funPoint.frame));
      }
    });
  } else {
    console.error('Frameworks coordinates do not match!');
  };
};

他以这种方式开始:

$(svg path).animatePathD('coordinates', opt);

坐标 - 新坐标;
opt - 动画的速度或实施的参数。它只需要2个参数:持续时间(执行速度;只接受数字;默认值 - 1000)和缓动(动画类型,需要两个参数:线性和默认摆动 - 线性);

外部编辑器示例https://jsfiddle.net/yuri_spivak/ws4xknot/
在线示例

$.prototype.animatePathD = function(d, o) {
  // Подстраиваем под разные браузера
  var i = $('body *').length;
  $('body').append('<svg id="animatepathd' + i + '" style="display:none"><path d="' + d + '"></svg>');
  d = $('#animatepathd' + i + ' path').attr('d');
  $('#animatepathd' + i).remove();

  var e = this,
    d = {
      primary: {
        frame: $(e).attr('d').replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'),
        coord: $(e).attr('d').replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',')
      },
      final: {
        frame: d.replace(/\ \-[0-9.]+/g, ' {n}').replace(/[0-9.]+/g, '{n}'),
        coord: d.replace(/[^0-9-.]+/g, ',').replace(/([0-9.]+)\-([0-9.]+)/g, '$1,$2').replace(/^\,(.+)\,$/, '$1').split(',')
      }
    },
    opt = o;
  if (opt == undefined) {
    opt = {
      duration: 1000,
      easing: 'linear'
    };
  } else if (/^\d+$/.exec(opt) != null) {
    opt = {
      duration: opt,
      easing: 'linear'
    };
    if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) {
      opt.duration = 1000
    };
  } else {
    if (opt.duration == undefined || /^\d+$/.exec(opt.duration) == null) {
      opt.duration = 1000
    };
    if (opt.easing != 'swing' && opt.easing != 'linear') {
      opt.easing = 'linear'
    };
  };
  if (d.primary.frame == d.final.frame) {
    var funPoint = {
      primary: {},
      final: {},
      list: '',
      frame: "'" + d.final.frame + "'"
    };
    for (var i = 0; i < d.primary.coord.length; i++) {
      funPoint.primary['c' + i] = d.primary.coord[i];
      funPoint.final['c' + i] = d.final.coord[i];
      funPoint.list = ', c' + i;
      if (d.primary.coord.length != 0) {
        funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+obj.elem.c" + i + "+'")
      } else {
        funPoint.frame = funPoint.frame.replace(/\{n\}/, "'+c" + i + "+'")
      };
    };
    funPoint.list = funPoint.list.replace(/^\,\ (.+)$/, '$1');
    $(funPoint.primary).animate(funPoint.final, {
      duration: opt.duration,
      easing: opt.easing,
      step: function(c0, obj) {
        $(e).attr('d', eval(funPoint.frame));
      }
    });
  } else {
    console.error('Frameworks coordinates do not match!');
  };
};

$(function() {
  $('#button').click(function() {
    if ($('#button.-pause').length == 1 && $('#button.-play').length == 0) {
      $('#button svg path').animatePathD('M 12,26 16,26 16,10 12,10 z M 21,26 25,26 25,10 21,10 z', {
        duration: 150,
        easing: 'linear'
      });
      $('#button').removeClass('-pause');
      $('#button').addClass('-play');
    } else {
      $('#button svg path').animatePathD('M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z', 150);
      $('#button').removeClass('-play');
      $('#button').addClass('-pause');
    };
    return false;
  });
});
@import url('data:text/css;charset=UTF-8,body { font-family: Tahoma, sans-serif; font-size: 0.8rem; } a {display: inline-block;color: #427fed;cursor: pointer;text-decoration: none;margin-right:5px;} a:hover {text-decoration: underline;} button { -webkit-padding-end: 10px; -webkit-padding-start: 10px; min-height: 2em; min-width: 4em; padding-bottom: 1px; -webkit-appearance: none; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } button:hover { background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } button:active { background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } button:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; } select { -webkit-padding-end: 20px; -webkit-padding-start: 6px; background-position: right center; background-repeat: no-repeat; min-height: 2em; min-width: 4em; padding-bottom: 0; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } select:hover { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } select:active { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } select:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; }');

#button {
  min-width: auto;
  padding: 3px 3px 0 1px;
  cursor: pointer;
}
<script src="https://code.jquery.com/jquery-3.1.1.js"></script>

<button id="button" class="-pause">
  <svg width="36" height="36" viewBox="0 0 36 36">
    <path d="M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z"></path>
  </svg>
</button>

答案 3 :(得分:0)

使用标准动画svg的脚本版本:

$.prototype.animatePathD = function(d) {
  var e = this,
      animate = $(e).find('animate[data-animatePathD]');
  if(animate.length){
    animate.attr({
      'attributeName': 'd', 
      'attributeType': 'XML',
      'from': animate.attr('to') || $(e).attr('d'),
      'to': d,
      'fill': 'freeze'
    });
    animate[0].beginElement();
  };
};

<强>运行:

  1. 将path元素添加到动画data-animatePathD属性和所有必需属性
  2.   

    示例:

    <path>
      <animate data-animatePathD dur="0.15s" begin="none" />
    </path>
    
    1. JS的功能改变了函数的坐标:
    2. svg path - 路径元素的路径; 坐标 - 新坐标;

      在线示例:

      &#13;
      &#13;
      $.prototype.animatePathD = function(d) {
        var e = this,
            animate = $(e).find('animate[data-animatePathD]');
        if(animate.length){
          animate.attr({
            'attributeName': 'd', 
            'attributeType': 'XML',
            'from': animate.attr('to') || $(e).attr('d'),
            'to': d,
            'fill': 'freeze'
          });
          animate[0].beginElement();
        };
      };
      
      $(function() {
        $('#button').click(function() {
          if ($('#button.-pause').length == 1 && $('#button.-play').length == 0) {
            $('#button svg path').animatePathD('M 12,26 16,26 16,10 12,10 z M 21,26 25,26 25,10 21,10 z');
            $('#button').removeClass('-pause');
            $('#button').addClass('-play');
          } else {
            $('#button svg path').animatePathD('M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z');
            $('#button').removeClass('-play');
            $('#button').addClass('-pause');
          };
          return false;
        });
      });
      &#13;
      @import url('data:text/css;charset=UTF-8,body { font-family: Tahoma, sans-serif; font-size: 0.8rem; } a {display: inline-block;color: #427fed;cursor: pointer;text-decoration: none;margin-right:5px;} a:hover {text-decoration: underline;} button { -webkit-padding-end: 10px; -webkit-padding-start: 10px; min-height: 2em; min-width: 4em; padding-bottom: 1px; -webkit-appearance: none; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } button:hover { background-image: -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } button:active { background-image: -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } button:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; } select { -webkit-padding-end: 20px; -webkit-padding-start: 6px; background-position: right center; background-repeat: no-repeat; min-height: 2em; min-width: 4em; padding-bottom: 0; -webkit-user-select: none; background-image: -webkit-linear-gradient(#ededed, #ededed 38%, #dedede); border: 1px solid rgba(0, 0, 0, 0.25); border-radius: 2px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.08), inset 0 1px 2px rgba(255, 255, 255, 0.75); color: #444; font: inherit; margin: 0 1px 0 0; outline: none; text-shadow: 0 1px 0 rgb(240, 240, 240); } select:hover { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#f0f0f0, #f0f0f0 38%, #e0e0e0); border-color: rgba(0, 0, 0, 0.3); box-shadow: 0 1px 0 rgba(0, 0, 0, 0.12), inset 0 1px 2px rgba(255, 255, 255, 0.95); color: black; } select:active { background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAAICAQAAACxSAwfAAAAUklEQ%E2%80%A6BbClcIUcSAw21QhXxfIIrwKAMpfNsEUYRXGVCEFc6CQwBqq4CCCtU4VgAAAABJRU5ErkJggg==), -webkit-linear-gradient(#e7e7e7, #e7e7e7 38%, #d7d7d7); box-shadow: none; text-shadow: none; } select:focus { -webkit-transition: border-color 200ms; border-color: rgb(77, 144, 254); outline: none; }');
      
      #button {
        min-width: auto;
        padding: 3px 3px 0 1px;
        cursor: pointer;
      }
      &#13;
      <script src="https://code.jquery.com/jquery-3.1.1.js"></script>
      
      <button id="button" class="-pause">
        <svg width="36" height="36" viewBox="0 0 36 36">
          <path d="M 12,26 18.5,22 18.5,14 12,10 z M 18.5,22 25,18 25,18 18.5,14 z">
            <animate data-animatePathD dur="0.15s" begin="none" />
          </path>
        </svg>
      </button>
      &#13;
      &#13;
      &#13;