【问题标题】:Canvas rotation - JavaScript画布旋转 - JavaScript
【发布时间】:2010-11-04 00:46:54
【问题描述】:

如果有人有答案,你能帮我吗? 我有 2 张图片 - 背景类似于弧线和箭头。我需要将箭头图像移动到背景图像上,就像这是一个时钟行情箭头。所以我需要:

  1. 旋转箭头使其与圆弧上的当前刻度平行
  2. 将箭头移动到下一点

为此,我需要在 JavaScript 中使用 Canvas 对象及其方法转换 - 这将允许移动箭头并旋转它。

问题是:如何使用 canvas.transform 方法来旋转(和理想的移动)箭头围绕圆弧?在这种情况下,它们之间应该是哪些值以及它们之间的关系:

contextData.clearRect (0, 0, contextData.canvas.width, contextData.canvas.height);
contextData.save ();
contextData.translate(indicatorData.width () / 2, indicatorData.height () / 2);
contextData.transform(1, 0, 0, 1, x, y);  // the question is HERE
contextData.drawImage(rotationArrow, -rotationArrow.width / 2, -rotationArrow.height / 2);
contextData.restore ();

提前致谢。

【问题讨论】:

    标签: javascript canvas transform


    【解决方案1】:

    不要使用变换矩阵,而是使用辅助函数 .rotate

    这样做可以让您围绕其中心旋转对象

    contextData.save()
    contextData.translate(indicatorData.width() / 2, indicatorData.height() / 2) // ASSUMING this  is the object you want to rotate around the center of and that it is being drawn at 0,0
    contextData.rotate(1.57) // 1.57 radians = about 90 degrees
    contextData.drawImage(rotationArrow, -rotationArrow.width / 2, -rotationArrow.height / 2);
    contextData.restore()
    

    【讨论】:

    • Rotate 方法用于修改对象在空间中的位置,因此它会影响可以应用于对象的任何其他方法,它们将无法正常工作。通常rotate方法应该只用于围绕物体旋转以产生透视错觉的相机。
    【解决方案2】:

    差点忘了...我找到了答案,它有效,这是最终代码。要使其在 IE 中运行,您应该添加 Google 的 excanvas 库并修复一些 IE8 问题,您需要添加兼容性元标记:

    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
       <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
       <title>Canvas</title>
       <script type="text/javascript" src="jquery.min.js"></script>
       <script type="text/javascript" src="excanvas.js"></script>
    </head>
    <body>
    
    <div class="indicator">
       <img class="image" src="usage_icon_electro.png" alt="" />
       <img class="pointer" src="usage_electro_pointer.png" alt="" />
       <canvas width="120" height="120" id="canvas"></canvas>
    </div>
    
    <script type="text/javascript">
    
    var indicatorClass = {
    
       timerHandle : 0,
       timerDelay : 10,
    
       rotationIncrement : 1,
       rotationStep : 0,
       rotationSteps : 50,
       rotationRadius : 35,
    
       angleCurrent : 5,
       angleDelta : 150,
    
       directionClockwise : true,
    
       canvasIndicator : null,
       canvasPointer : null,
       canvasContext : null,
    
       getRadianAngle : function (degreeValue) {
          return degreeValue * Math.PI / 180;
       },
    
       initCanvas : function (optionList) {
    
          try {
    
             var canvasData = $ ('.indicator #canvas').get (0);
    
             if ($.browser.msie) {
                canvasData = document.createElement('canvas');
                $ (canvasData)
                   .attr ('width', 120)
                   .attr ('height', 120)
                   .attr ('id', 'canvas')
                   .appendTo('.indicator');
                canvasData = G_vmlCanvasManager.initElement(canvasData);
                /*
                var metaCompatible = document.createElement('meta');
                $ (metaCompatible)
                   .attr ('http-equiv', 'X-UA-Compatible')
                   .attr ('content', 'IE=EmulateIE7')
                   .prependTo('head');
                */
                //$ ('head').prepend ('<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />');
    //alert ($ ('head').html ());
             }
    
             indicatorClass.canvasIndicator = $ ('.indicator');
             indicatorClass.canvasPointer = $ ('.indicator .pointer').get (0);
             indicatorClass.canvasContext = canvasData.getContext ("2d");
    
             $.extend (indicatorClass, optionList);
    
             var angleMax = indicatorClass.angleCurrent + indicatorClass.angleDelta;
             indicatorClass.setRotationAngle (510);
    
             indicatorClass.timerHandle = setInterval(function () { 
                if (indicatorClass.angleCurrent > angleMax) {
                   clearInterval (indicatorClass.timerHandle);
                }
                indicatorClass.angleCurrent += indicatorClass.rotationIncrement;
                indicatorClass.rotationStep += indicatorClass.rotationIncrement;
                indicatorClass.setRotation (); 
             }, indicatorClass.timerDelay);
    
          } catch (exceptionData) {
             alert ('Indicator is not loaded');
          }
       },
    
       getCircleCoords : function (stepIndex) {
    
          var centerX = indicatorClass.canvasIndicator.width () / 2;
          var centerY = indicatorClass.canvasIndicator.height () / 2;
          var coordValues = {
             currentX : (centerX + indicatorClass.rotationRadius * Math.cos (2 * Math.PI * stepIndex / indicatorClass.rotationSteps)),
             currentY : (centerY + indicatorClass.rotationRadius * Math.sin (2 * Math.PI * stepIndex / indicatorClass.rotationSteps))
          }
    
          return coordValues;
       },
    
       setRotationAngle : function (angleValue) {
    
          indicatorClass.canvasContext.translate(indicatorClass.canvasIndicator.width () / 2, indicatorClass.canvasIndicator.height () / 2);
    
          for (var currentAngle = 90; currentAngle <= 720; currentAngle++) {
    
             var sin = Math.sin(currentAngle * Math.PI / 360);  
             var cos = Math.cos(currentAngle * Math.PI / 360);
             var deltaX = indicatorClass.directionClockwise ? -sin : sin;
             var deltaY = indicatorClass.directionClockwise ? sin : -sin;
    
             if (currentAngle > angleValue) {
                indicatorClass.canvasContext.transform(cos, deltaY, deltaX, cos, 0, 0);
                return false;
             }
          }
       },
    
       setTransform : function () {
    
          var sin = Math.sin(indicatorClass.rotationStep * Math.PI / indicatorClass.rotationSteps);  
          var cos = Math.cos(indicatorClass.rotationStep * Math.PI / indicatorClass.rotationSteps);
          var deltaX = indicatorClass.directionClockwise ? -sin : sin;
          var deltaY = indicatorClass.directionClockwise ? sin : -sin;
    
          //indicatorClass.canvasContext.clearRect (0, 0, indicatorClass.canvasContext.canvas.width, indicatorClass.canvasContext.canvas.height);
          indicatorClass.canvasContext.save ();
          //indicatorClass.canvasContext.translate(indicatorClass.canvasIndicator.width () / 2, indicatorClass.canvasIndicator.height () / 2);
          indicatorClass.canvasContext.transform(cos, deltaY, deltaX, cos, 0, 0);
          indicatorClass.canvasContext.clearRect (-screen.width, -screen.height, screen.width, screen.height);
          indicatorClass.canvasContext.drawImage(indicatorClass.canvasPointer, -indicatorClass.canvasPointer.width / 2, -indicatorClass.canvasPointer.height - indicatorClass.rotationRadius);
          indicatorClass.canvasContext.restore ();
       },
    
       setRotation : function () {
    
          var currentAngle = indicatorClass.directionClockwise ? indicatorClass.angleCurrent : -indicatorClass.angleCurrent;
    
          indicatorClass.canvasContext.save ();
          indicatorClass.canvasContext.rotate(indicatorClass.getRadianAngle (currentAngle));
          indicatorClass.canvasContext.clearRect (-screen.width, -screen.height, screen.width, screen.height);
          indicatorClass.canvasContext.drawImage(indicatorClass.canvasPointer, -indicatorClass.canvasPointer.width / 2, -indicatorClass.canvasPointer.height - indicatorClass.rotationRadius);
          indicatorClass.canvasContext.restore ();
       }
    
    }
    
    window.onload = function () {
       indicatorClass.initCanvas ();
    }
    
    </script>
    
    <style type="text/css">
    .indicator {
       width:120px;
       height:120px;
       border:1px solid #ccc;
       text-align:center;
       position:relative;
    }
    .indicator .pointer {
       visibility:hidden;
    }
    .indicator #canvas {
       z-index:10000;
       position:absolute;
       top:0;
       left:0;
       width:100%;
       height:100%;
    }
    </style>
    
    </body>
    </html>
    

    【讨论】:

    • 发布答案时,最好包含一个最小示例。您不应该包含所有内容。
    猜你喜欢
    • 1970-01-01
    • 2021-06-26
    • 1970-01-01
    • 1970-01-01
    • 2014-02-01
    • 2016-07-29
    • 2013-05-29
    • 2022-01-04
    • 2014-01-18
    相关资源
    最近更新 更多