javascript - 如何检测鼠标是否在顺时针方向移动

标签 javascript canvas rotation html5-canvas

我想在鼠标移动时在 Canvas 上旋转一个形状,我想检测鼠标是否在 顺时针方向 移动,但我不知道该怎么做。这是我的代码:

var canvas = document.getElementById('canvas');
var img = document.getElementById('photo');
var ctx = canvas.getContext('2d');

var annotation_rect = canvas.getBoundingClientRect();
rect = {
      startX : 150,
      startY : 50,
      w : 250,
      h : 150,
      endX : 0,
      endY : 0,
      rotate: 0
    };
var drag = false;
var rotating = false;
var update = true; // when true updates canvas
var rotate_angle = 5; // in degrees - for rotating blurred part
var angle = rotate_angle * (Math.PI / 180);
var original_source = img.src;
img.src = original_source;

function rotateRight(){
	rect.rotate += angle;
  update = true;
}

function rotateLeft(){
	rect.rotate -= angle;
  update = true;
}

function init() {
    img.addEventListener('load', function(){
        canvas.width = img.width;
        canvas.height = img.height;
        canvas.addEventListener('mousedown', mouseDown, false);
        canvas.addEventListener('mouseup', mouseUp, false);
        canvas.addEventListener('mousemove', mouseMove, false);
    });
    
    // start the rendering loop
    requestAnimationFrame(updateCanvas);
}

// main render loop only updates if update is true
function updateCanvas(){
  if(update){
      drawCanvas();
      update = false;
  }

  requestAnimationFrame(updateCanvas);
}

// draws a rectangle with rotation 
function drawRect(){
		ctx.setTransform(1,0,0,1,rect.startX + rect.w / 2, rect.startY + rect.h / 2);
    ctx.rotate(rect.rotate);
    ctx.beginPath();
    ctx.shadowBlur = 5;
    ctx.filter = 'blur(10px)';
    ctx.rect(-rect.w/2, -rect.h/2, rect.w, rect.h);
    ctx.lineWidth = 3;
    ctx.strokeStyle = "#fff";
    ctx.fillStyle = "#fff";
    ctx.fill();
    ctx.stroke();
}

// clears canvas sets filters and draws rectangles
function drawCanvas(){    
		ctx.setTransform(1,0,0,1,0,0);
    ctx.clearRect(0, 0, canvas.width, canvas.height);
    ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
    ctx.fillRect(0, 0, canvas.width, canvas.height);
    drawRect()
}

// create new rect add to array 
function mouseDown(e) {
    drag = true;
}

function mouseUp() { drag = false; update = true; }



function startRotation(e){
    rotating = true;
}

function stopRotation(e){
    rotating = false;
}

function onShapeRotating(e){
    if(rotating){
         rotateRight();
    }
} 



function mouseMove(e) {
		var mouseX = e.offsetX - annotation_rect.left,
    		mouseY = e.offsetY - annotation_rect.top,
        endX = rect.startX + rect.w,
    		endY = rect.startY + rect.h
    
		var cursorOnShape = mouseX >= rect.startX && mouseX <= endX && mouseY >= rect.startY && mouseY <= endY;
    
    
    if(cursorOnShape){
        canvas.style.cursor = "pointer"
        
        canvas.addEventListener('mousedown', startRotation, false);
        canvas.addEventListener('mouseup', stopRotation, false);
        canvas.addEventListener('mousemove', onShapeRotating, false);
    }else{    
        canvas.style.cursor = "default"
        canvas.removeEventListener('mousedown', startRotation, false);
        canvas.removeEventListener('mouseup', stopRotation, false);
        canvas.removeEventListener('mousemove', onShapeRotating, false);
    }
}

init();
canvas{
  position: absolute;
  left: 0; 
  right: 0; 
  top: 0; 
  bottom: 0; 
  display:inline-block;
  background:rgba(0,0,0,0.3);
}
<div style="position: relative; overflow: hidden;display:inline-block;">
    <img id="photo" src="https://carsales.pxcrush.net/carsales/car/cil/cc5166737225893351785.jpg?width=600&height=300&overlay&aspect=FitWithIn&watermark=1439104668"/>
    <canvas id="canvas"></canvas>
</div>

因此我在 Canvas 上绘制了一个矩形,我检测鼠标是否在该矩形上,如果是,我调用函数 rotateShape 并在那里调用函数 rotateRight。那是有效的。如果您在鼠标所在的矩形上并按下并旋转它,它将旋转矩形,调用函数 rotateRight

但我希望能够检查鼠标是否顺时针方向移动。如果它沿顺时针方向移动,我将调用 rotateRight,如果不是,则我将调用 rotateLeft

知道怎么做吗?

Here is the fiddle.

最佳答案

不是按固定值旋转,而是按最后已知 Angular 和新 Angular 之间的差值旋转。

要获得这些 Angular ,您可以使用

var angle = Math.atan2(
  e.clientY - (rect.startY + rect.h /2),
  e.clientX - (rect.startX + rect.w /2)
);

var canvas = document.getElementById('canvas');
var img = document.getElementById('photo');
var ctx = canvas.getContext('2d');

var annotation_rect = canvas.getBoundingClientRect();
rect = {
  startX: 150,
  startY: 50,
  w: 250,
  h: 150,
  endX: 0,
  endY: 0,
  rotate: 0
};
var drag = false;
var rotating = false;
var update = true; // when true updates canvas
var original_source = img.src;
img.src = original_source;

// keep track of the last angle
var prevAngle = null;
// a single function
function rotate(angle) {
  rect.rotate += angle;
  update = true;
}
// called on mousemove when dragging
function onShapeRotating(e) {
  if (rotating) {
    var angle = Math.atan2(
      e.clientY - (rect.startY + rect.h / 2),
      e.clientX - (rect.startX + rect.w / 2)
    );
    if (prevAngle !== null)
      rotate(angle - prevAngle)
    prevAngle = angle;
  }
}

function init() {
  img.addEventListener('load', function() {
    canvas.width = img.width;
    canvas.height = img.height;
    canvas.addEventListener('mousedown', mouseDown, false);
    canvas.addEventListener('mouseup', mouseUp, false);
    canvas.addEventListener('mousemove', mouseMove, false);
  });

  // start the rendering loop
  requestAnimationFrame(updateCanvas);
}

// main render loop only updates if update is true
function updateCanvas() {
  if (update) {
    drawCanvas();
    update = false;
  }

  requestAnimationFrame(updateCanvas);
}

// draws a rectangle with rotation 
function drawRect() {
  ctx.setTransform(1, 0, 0, 1, rect.startX + rect.w / 2, rect.startY + rect.h / 2);
  ctx.rotate(rect.rotate);
  ctx.beginPath();
  ctx.shadowBlur = 5;
  ctx.filter = 'blur(10px)';
  ctx.rect(-rect.w / 2, -rect.h / 2, rect.w, rect.h);
  ctx.lineWidth = 3;
  ctx.strokeStyle = "#fff";
  ctx.fillStyle = "#fff";
  ctx.fill();
  ctx.stroke();
}

// clears canvas sets filters and draws rectangles
function drawCanvas() {
  ctx.setTransform(1, 0, 0, 1, 0, 0);
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = 'rgba(0, 0, 0, 0.6)';
  ctx.fillRect(0, 0, canvas.width, canvas.height);
  drawRect()
}

// create new rect add to array 
function mouseDown(e) {
  drag = true;
}

function mouseUp() {
  prevAngle = null;
  drag = false;
  update = true;
}



function startRotation(e) {
  rotating = true;
}

function stopRotation(e) {
  rotating = false;
}


function mouseMove(e) {
  var mouseX = e.offsetX - annotation_rect.left,
    mouseY = e.offsetY - annotation_rect.top,
    endX = rect.startX + rect.w,
    endY = rect.startY + rect.h

  var cursorOnShape = mouseX >= rect.startX && mouseX <= endX && mouseY >= rect.startY && mouseY <= endY;


  if (cursorOnShape) {
    canvas.style.cursor = "pointer"

    canvas.addEventListener('mousedown', startRotation, false);
    canvas.addEventListener('mouseup', stopRotation, false);
    canvas.addEventListener('mousemove', onShapeRotating, false);
  } else {
    canvas.style.cursor = "default"
    canvas.removeEventListener('mousedown', startRotation, false);
    canvas.removeEventListener('mouseup', stopRotation, false);
    canvas.removeEventListener('mousemove', onShapeRotating, false);
  }
}

init();
canvas {
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  bottom: 0;
  display: inline-block;
  background: rgba(0, 0, 0, 0.3);
}
<div style="position: relative; overflow: hidden;display:inline-block;">
  <img id="photo" src="https://carsales.pxcrush.net/carsales/car/cil/cc5166737225893351785.jpg?width=600&height=300&overlay&aspect=FitWithIn&watermark=1439104668" />
  <canvas id="canvas"></canvas>
</div>


现在,您的代码有很多问题需要修复,但我会交给您。

你最好在整个 Canvas /文档上使用单个事件,而不是有选择地添加。
您的 cursorOnShape 算法没有考虑矩形的旋转。

关于javascript - 如何检测鼠标是否在顺时针方向移动,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49147241/

相关文章:

jquery - 动画选项 HTML5 Canvas/CSS3/jQuery

rotation - Julia AffineTransforms 旋转角的符号

Java 俄罗斯方 block 旋转

javascript - 如何使用 javascript/Jquery 调用 iOS 搜索按钮?

JavaScript Canvas 下载

javascript - 在每个月的第一个星期日创建重复日期

java - JFrame 太小并且 pack() 似乎不起作用

html - CSS 旋转文本但保持垂直对齐

javascript - 填充缓存数据

javascript - 如何在 Canvas 上为移动图像绘制多条路径