javascript - SVG - 动画问题

标签 javascript animation svg smil

我有一些形状,我使用两个按钮旋转,一个用于顺时针方向,另一个用于逆时针方向:

var svgNS = "http://www.w3.org/2000/svg";

function cwAnim(evt) {
  if (window.svgDocument == null)
    svgDoc = evt.target.ownerDocument;

  addRotateTransform('someShape', 1, -1, 180);
  addRotateTransform('shape1', 1, 1, 360);
  addRotateTransform('shape2', 1, 1, 360);
}

function acwAnim(evt) {
  if (window.svgDocument == null)
    svgDoc = evt.target.ownerDocument;

  addRotateTransform('someShape', 1, 1, 180);
  addRotateTransform('shape1', 1, -1, 360);
  addRotateTransform('shape2', 1, -1, 360);
}

function addRotateTransform(target_id, dur, dir, angle) {
  var my_element = svgDoc.getElementById(target_id);
  var a = svgDoc.createElementNS(svgNS, "animateTransform");

  var bb = my_element.getBBox();
  var cx = bb.x + bb.width / 2;
  var cy = bb.y + bb.height / 2;

  a.setAttributeNS(null, "attributeName", "transform");
  a.setAttributeNS(null, "attributeType", "XML");
  a.setAttributeNS(null, "type", "rotate");
  a.setAttributeNS(null, "dur", dur + "s");
  a.setAttributeNS(null, "repeatCount", "1");
  a.setAttributeNS(null, "fill", "freeze");
  a.setAttributeNS(null, "additive", "sum");
  a.setAttributeNS(null, "accumulate", "sum");
  a.setAttributeNS(null, "from", "0 " + cx + " " + cy);
  a.setAttributeNS(null, "to", angle * dir + " " + cx + " " + cy);

  my_element.appendChild(a);
  a.beginElement();
}
<svg width="600px" height="600px" viewBox="0 0 1000 1000">
  <circle stroke="#000000" stroke-miterlimit="10" cx="468.451" cy="474.385" r="350" />
  <g id="someShape">
    <circle fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" cx="468.451" cy="474.385" r="350" />
    <path id="shape1" fill="#DC5A00" stroke="#000000" stroke-miterlimit="10" d="M692.373,317.798C692.373,418.425,606.244,500,500,500
			c-106.245,0-192.374-81.575-192.374-182.202c0-100.629,86.128-182.204,192.374-182.204
			C606.244,135.595,692.373,217.169,692.373,317.798z M553.391,220.34c-39.316,0-71.188,31.87-71.188,71.187
			s31.871,71.187,71.188,71.187c39.314,0,71.186-31.87,71.186-71.187S592.705,220.34,553.391,220.34z" />
    <path id="shape2" fill="#3DFF63" stroke="#000000" stroke-miterlimit="10" d="M577.368,647.034c0,69.738-56.913,126.271-127.119,126.271
			c-70.206,0-127.119-56.533-127.119-126.271c0-69.737,56.913-126.271,127.119-126.271
			C520.455,520.764,577.368,577.297,577.368,647.034z M466.352,617.373c-21.998,0-39.831,17.453-39.831,38.983
			c0,21.529,17.833,38.982,39.831,38.982s39.831-17.453,39.831-38.982C506.182,634.826,488.349,617.373,466.352,617.373z" />
  </g>
  <g onclick="cwAnim(evt)">
    <rect x="89.762" y="815.369" stroke="#000000" stroke-miterlimit="10" width="217.865" height="134.426" />
    <text transform="matrix(1 0 0 1 127.4673 864.5491)" fill="#FFFFFF" font-family="'MyriadPro-Regular'" font-size="21">AntiClockwise</text>
  </g>
  <g onclick="acwAnim(evt)">
    <rect x="692.373" y="815.369" stroke="#000000" stroke-miterlimit="10" width="194.11" height="134.426" />
    <text transform="matrix(1 0 0 1 752.0576 869.467)" fill="#FFFFFF" font-family="'MyriadPro-Regular'" font-size="21">Clockwise</text>
  </g>
</svg>

你也可以在这个CodePen上看到:http://codepen.io/Daolagajao/pen/qdyBLo

当我点击一次时,形状动画效果很好。 当我快速连续单击按钮时出现问题(双击、三次单击等)。旋转轴移动,这当然是不可取的。

这个问题有办法解决吗?就像当我点击下一步按钮时,上一个正在进行的动画停止保留位置并开始新的动画。

最佳答案

通过添加一个 busy 变量,您可以指示您当前正在制作动画并且您不应该制作任何动画。您可以用它做更多事情,但它解决了基本问题。

var svgNS = "http://www.w3.org/2000/svg";
var busy = false;

function animationDelegate(evt, direction){
    /* Check if we are busy before doing anything.*/
    /* If we are, stop executing this request, otherwise, set busy to true.*/
    if(busy) return; else busy = true;
    if(direction === 'cw') cwAnim(evt);
    else if(direction === 'ccw') acwAnim(evt);
    /* Your duration is 1 second, so 1000ms.*/
    /* Set a timeout that resets busy.*/
    setTimeout(function(){ busy = false}, 1000);
}

function cwAnim(evt){
  if ( window.svgDocument == null)
    svgDoc = evt.target.ownerDocument;

  addRotateTransform('someShape', 1, -1, 180);
  addRotateTransform('shape1', 1, 1, 360);
  addRotateTransform('shape2', 1, 1, 360);				
}

function acwAnim(evt){
  if ( window.svgDocument == null)
    svgDoc = evt.target.ownerDocument;

  addRotateTransform('someShape', 1, 1, 180);
  addRotateTransform('shape1', 1, -1, 360);
  addRotateTransform('shape2', 1, -1, 360);							
}

function addRotateTransform(target_id, dur, dir, angle){
  var my_element = svgDoc.getElementById(target_id);
  var a = svgDoc.createElementNS(svgNS, "animateTransform");

  var bb = my_element.getBBox();
  var cx = bb.x + bb.width/2;
  var cy = bb.y + bb.height/2;

  a.setAttributeNS(null, "attributeName", "transform");
  a.setAttributeNS(null, "attributeType", "XML");
  a.setAttributeNS(null, "type", "rotate");
  a.setAttributeNS(null, "dur", dur + "s");
  a.setAttributeNS(null, "repeatCount", "1");
  a.setAttributeNS(null, "fill", "freeze");
  a.setAttributeNS(null, "additive", "sum");
  a.setAttributeNS(null, "accumulate", "sum");
  a.setAttributeNS(null, "from", "0 "+cx+" "+cy);
  a.setAttributeNS(null, "to", angle*dir+" "+cx+" "+cy);

  my_element.appendChild(a);
  a.beginElement();
}
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="600px" height="600px" viewBox="0 0 1000 1000" enable-background="new 0 0 1000 1000" xml:space="preserve">
  <circle stroke="#000000" stroke-miterlimit="10" cx="468.451" cy="474.385" r="350" />
  <g id="someShape">
    <circle fill="#FFFFFF" stroke="#000000" stroke-miterlimit="10" cx="468.451" cy="474.385" r="350" />
    <path id="shape1" fill="#DC5A00" stroke="#000000" stroke-miterlimit="10" d="M692.373,317.798C692.373,418.425,606.244,500,500,500
			c-106.245,0-192.374-81.575-192.374-182.202c0-100.629,86.128-182.204,192.374-182.204
			C606.244,135.595,692.373,217.169,692.373,317.798z M553.391,220.34c-39.316,0-71.188,31.87-71.188,71.187
			s31.871,71.187,71.188,71.187c39.314,0,71.186-31.87,71.186-71.187S592.705,220.34,553.391,220.34z" />
    <path id="shape2" fill="#3DFF63" stroke="#000000" stroke-miterlimit="10" d="M577.368,647.034c0,69.738-56.913,126.271-127.119,126.271
			c-70.206,0-127.119-56.533-127.119-126.271c0-69.737,56.913-126.271,127.119-126.271
			C520.455,520.764,577.368,577.297,577.368,647.034z M466.352,617.373c-21.998,0-39.831,17.453-39.831,38.983
			c0,21.529,17.833,38.982,39.831,38.982s39.831-17.453,39.831-38.982C506.182,634.826,488.349,617.373,466.352,617.373z" />
  </g>
  <g onclick="animationDelegate(evt, 'ccw')">
    <rect x="89.762" y="815.369" stroke="#000000" stroke-miterlimit="10" width="217.865" height="134.426" />
    <text transform="matrix(1 0 0 1 127.4673 864.5491)" fill="#FFFFFF" font-family="'MyriadPro-Regular'" font-size="21">AntiClockwise</text>
  </g>
  <g onclick="animationDelegate(evt, 'cw')">
    <rect x="692.373" y="815.369" stroke="#000000" stroke-miterlimit="10" width="194.11" height="134.426" />
    <text transform="matrix(1 0 0 1 752.0576 869.467)" fill="#FFFFFF" font-family="'MyriadPro-Regular'" font-size="21">Clockwise</text>
  </g>
</svg>

关于javascript - SVG - 动画问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31454203/

相关文章:

iOS 动画一系列图像

javascript - SVG 上的 JQuery 事件未触发

javascript - React-Native:虽然前面有声明,但 undefined 不是对象

javascript - react 过渡组 : how do you unmount a component after it has finished it's exit animation

javascript - getJSON 完成后全局变量未更新

android - 有人曾经在图像上做过基本的 'scan-animation' 吗?

javascript - 多多边形 SVG 选择(填充颜色)和蒙版导出到图像

css - 为内联 svg 添加没有文本的下划线文本装饰

javascript - Vue.js 组件点击事件找不到方法

javascript - javascript 是否有一种方法可以在没有 for 循环的情况下循环遍历对象?