画布旋转 - JavaScript

发布于 2024-09-30 09:44:42 字数 687 浏览 1 评论 0原文

如果有人有答案,可以帮我吗? 我有 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 ();

提前致谢。

If someone has the answer could you help me, please?
I have 2 images - background similar to arc and arrow. And i need to move arrow image over background image like this is a clock ticker arrow. So i need :

  1. Rotate arrow to make it parallel to current tick on the arc
  2. Move arrow to the next point

For this i need to use Canvas object in JavaScript and its method transform - this will allow to move arrow and rotate it.

The question is : how to use canvas.transform method to rotate (and desirable move) arrow around the arc? And which values and what relation between them should be in this case :

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 ();

Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

盛夏尉蓝 2024-10-07 09:44:42

不要使用变换矩阵,而是使用辅助函数 .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()

Instead of fooling around with a transformation matrix, use the helper function .rotate

Doing this will let you rotate an object about its center

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()
水中月 2024-10-07 09:44:42

差点忘了......我找到了答案,它有效,这是最终的代码。要使其在 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>

Almost forgot ... i found the answer, it works and this is the final code. To make it worked in IE you should add excanvas library from Google and to fix some IE8 issues you need to add compatibility meta tag :

<!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>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文