html - svg中齿轮逆时针旋转

标签 html svg svg-animate

我想要一个简单的齿轮,能够顺时针、逆时针旋转它并暂停动画。当我只有这两个按钮时,我的代码工作正常:顺时针和暂停;但添加逆时针按钮及其相关功能后,没有任何作用!
<强> Fiddle

    <!DOCTYPE html>
<html>

<head>  
  <title> Animated Gears</title>
  <meta http-equiv="X-UA-Compatible" content="IE=Edge"/> <!--  Remove this line in production. -->
</head>

<body>
  <div align="center"> <!-- An inexpensive way to center everything. -->
    <div style=" margin-bottom: 8px;">
      <button id="clockwise" type="button" onclick="clockwise();">
        clockwise
      </button> 
              <button id="pause" type="button" onclick="pauseAnim();">
        Pause
      </button> 
<button id="counterclockwise" type="button" onclick="counterclockwise();">
        Counterclockwise
      </button>       
      </div> 


    <svg id="svgElement" width="800px" height="800px" viewBox="0 0 800 800"> <!-- Give the svg element a name so that we can easily access it via JavaScript. -->
      <rect x="0" y="0" width="100%" height="100%" rx="16" ry="16" 
            style="fill: none; stroke: black; stroke-dasharray: 10, 5;" />

      <defs> <!-- Do not render the gear template, just define it. -->
        <g id="gearTemplate"> <!-- Give this group of graphic elements a name so that it can be "called" from the <use> element. -->
          <circle cx="0" cy="0" r="150" style="stroke: black;" />
          <line x1="0" y1="-150" x2="0" y2="150" style="stroke: white;"/> <!-- From top to bottom, draw the vertical wheel "spoke". -->        
          <line x1="-150" y1="0" x2="0" y2="0" style="stroke: white;"/> <!-- Draw left half of the horizontal "spoke". -->
          <line x1="0" y1="0" x2="150" y2="0" style="stroke: white;"/> <!-- Draw right half of the horizontal "spoke". -->
        </g>
      </defs>

      <g transform="translate(400, 400)"> <!-- Create a Cartesian coordinate system (with the y-axis flipped) for the animated gears. That is, place the origin at the center of the 800 x 800 SVG viewport: -->
        <use id="gear0" x="-150" y="0" xlink:href="#gearTemplate" style="fill: orange;" /> <!-- Use the previously defined gear template and position it appropriately. -->

      </g>
    </svg>
  </div>



 <script>

       "use strict";

    /* CONSTANTS */
    var initialTheta = 0; // The initial rotation angle, in degrees.
    var currentTheta = initialTheta; // The initial rotation angle to use when the animation starts.
    var thetaDelta = 0.5; // The amount to rotate the gears every ~16.7 milliseconds or so, in degrees.
    var angularLimit = 1080; // The maximum number of degrees to rotate the gears.

    /* GLOBALS */
    var requestAnimationFrameID;
    var transformObject = svgElement.createSVGTransform(); // Create a generic SVG transform object so as to gain access to its methods and properties, such as setRotate().
    var gear0 = document.getElementById('gear0');

gear0.transform.baseVal.appendItem(transformObject); // Append the transform object to gear0, now the gear0 object has inherited all the transform object's goodness.


     //...........................................     


function clockwise() {

if (!clockwise.startButtonClicked) { // Don't allow multiple instance of the function specified by requestAnimationFrame to be invoked by the browser. Note that button.startButtonClicked will be undefined on first use, which is effectively the same as false.
        /* Only do the following once per animation: */

        clockwise.startButtonClicked = true; // A custom property is attached to the button object to track whether the button has been clicked or not.
        requestAnimationFrameID = requestAnimationFrame(doAnim); // Start the animation loop.
      }
    }

     //..............................................
     function counterclockwise() {

if (!counterclockwise.startButtonClicked) { // Don't allow multiple instance of the function specified by requestAnimationFrame to be invoked by the browser. Note that button.startButtonClicked will be undefined on first use, which is effectively the same as false.
        /* Only do the following once per animation: */

        counterclockwise.startButtonClicked = true; // A custom property is attached to the button object to track whether the button has been clicked or not.
        requestAnimationFrameID = requestAnimationFrame(doAnim2); // Start the animation loop.
      }
    }



     //........................
    function pauseAnim() {
      cancelAnimationFrame(requestAnimationFrameID); // Stop calling the doAnim() function.

      clockwise.startButtonClicked = false; // Allow
     requestAnimationFrame() to be called if the Start button is clicked again. And disable the "+" or "-" buttons when paused.
     counterclockwise.startButtonClicked = false;

    }

         function doAnim() {
      if (currentTheta > angularLimit) {
        clockwise.startButtonClicked = false; // Let the user run the animation again if they choose.
        currentTheta = initialTheta; // If we let the user run the animation multiple times, be sure to set currentTheta back to an appropriate value.
        cancelAnimationFrame(requestAnimationFrameID); // Instruct the browser to stop calling requestAnimationFrame()'s callback.
        return; // We have completed our animation, time to quit.
      }

     gear0.transform.baseVal.getItem(0).setRotate(currentTheta, -150, 0); // Rotate the 0th gear about the point (-150, 0).

      currentTheta += thetaDelta; // Place this line here so that the gears are not over rotated on the last call to doAnim().
      requestAnimationFrameID = requestAnimationFrame(doAnim); // Call the doAnim() function about every 16.7 milliseconds (i.e., about 60 frames per second).     
     }
     //.................................................................

     function doAnim2() {
      if (currentTheta > angularLimit) {
        counterclockwise.startButtonClicked = false; // Let the user run the animation again if they choose.
        currentTheta = initialTheta; // If we let the user run the animation multiple times, be sure to set currentTheta back to an appropriate value.
        cancelAnimationFrame(requestAnimationFrameID); // Instruct the browser to stop calling requestAnimationFrame()'s callback.
        return; // We have completed our animation, time to quit.
      }

     gear0.transform.baseVal.getItem(0).setRotate(-currentTheta, -150, 0); // Rotate the 0th gear about the point (-150, 0).

      currentTheta += thetaDelta; // Place this line here so that the gears are not over rotated on the last call to doAnim().
      requestAnimationFrameID = requestAnimationFrame(doAnim2); // Call the doAnim() function about every 16.7 milliseconds (i.e., about 60 frames per second).     
     }



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

最佳答案

编辑 2015 年 1 月 19 日

现在您已经发布了有关 counterclocked 函数的尝试,看来您在 pause 函数内的注释存在问题(requestAnimationFrame() 为如果“开始”按钮是...,则调用... 未注释,导致语法错误。)
另外,我注意到您将 -currentTheta 应用于变换,如果您从“顺时针”转到“逆时针”,这会导致出现间隙。


那么,您的代码片段中缺少逆时针函数。所以很难告诉你出了什么问题。
但我承认它与顺时针相同,但方式不同:

var initialTheta = 0;
var currentTheta = initialTheta;
var thetaDelta = 0.5;
var angularLimit = 1080;
var angularLimitMin = -1080;

var requestAnimationFrameID;
var transformObject = svgElement.createSVGTransform();
var gear0 = document.getElementById('gear0');

gear0.transform.baseVal.appendItem(transformObject);


function clockwise() {
  if (!clockwise.startButtonClicked) {
    clockwise.startButtonClicked = true;
    requestAnimationFrameID = requestAnimationFrame(doAnim);
  }
}


function counterclockwise() {
  if (!counterclockwise.startButtonClicked) {
    counterclockwise.startButtonClicked = true;
    requestAnimationFrameID = requestAnimationFrame(undoAnim);
  }
}


function pauseAnim() {
  cancelAnimationFrame(requestAnimationFrameID);
  clockwise.startButtonClicked = false;
  counterclockwise.startButtonClicked = false;
}

function doAnim() {
  if (currentTheta > angularLimit) {
    clockwise.startButtonClicked = false;
    currentTheta = initialTheta;
    cancelAnimationFrame(requestAnimationFrameID);
    return;
  }

  gear0.transform.baseVal.getItem(0).setRotate(currentTheta, -150, 0);
  currentTheta += thetaDelta;
  requestAnimationFrameID = requestAnimationFrame(doAnim);
}

function undoAnim() {
  if (currentTheta < angularLimitMin) {
    counterclockwise.startButtonClicked = false;
    currentTheta = initialTheta;
    cancelAnimationFrame(requestAnimationFrameID);
    return;
  }
  gear0.transform.baseVal.getItem(0).setRotate(currentTheta, -150, 0);
  currentTheta -= thetaDelta;
  requestAnimationFrameID = requestAnimationFrame(undoAnim);
}
<div align="center">
  <!-- An inexpensive way to center everything. -->
  <div style=" margin-bottom: 8px;">
    <button id="clockwise" type="button" onclick="clockwise();">clockwise</button>
    <button id="pause" type="button" onclick="pauseAnim();">Pause</button>
    <button id="counterclockwise" type="button" onclick="counterclockwise();">Counterclockwise</button>
  </div>
  <svg id="svgElement" width="800px" height="800px" viewBox="0 0 800 800">
    <rect x="0" y="0" width="100%" height="100%" rx="16" ry="16" style="fill: none; stroke: black; stroke-dasharray: 10, 5;" />
    <defs>
      <g id="gearTemplate">
        <circle cx="0" cy="0" r="150" style="stroke: black;" />
        <line x1="0" y1="-150" x2="0" y2="150" style="stroke: white;" />
        <line x1="-150" y1="0" x2="0" y2="0" style="stroke: white;" />
        <line x1="0" y1="0" x2="150" y2="0" style="stroke: white;" />
      </g>
    </defs>
    <g transform="translate(400, 400)">
      <use id="gear0" x="-150" y="0" xlink:href="#gearTemplate" style="fill: orange;" />
    </g>
  </svg>
</div>

还有updated snippet以及您的评论

关于html - svg中齿轮逆时针旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28015448/

相关文章:

javascript - 如何独立调用 d3.svg.line()?

CSS动画改变元素位置

python - Python 中的 HTML 标签验证

html - 在 W3C 验证器中验证 HTML 时如何获取徽章?

javascript - 浏览 https protected 网站时出现问题

css - 如何旋转 SVG 路径元素而不使其绕圈移动?

css - SVG 悬停时旋转图像填充

javascript - 在 Next.js 中避免重复的元描述和关键字

jquery - 使用 jQuery SVG 插件设置内联 SVG 的渐变

svg - 如何在SVG中定义具有无理坐标的点?