简体   繁体   English

如何旋转画布中的对象

[英]How to rotate object in the canvas

I'm trying to rotate only one object in the canvas, not the whole canvas. 我正在尝试仅旋转画布中的一个对象,而不旋转整个画布。

My code is as follows: 我的代码如下:

 var canvas = document.getElementById('canvas'); var buttons = document.getElementById('buttons'); var img = document.getElementById('photo'); var ctx = canvas.getContext('2d'); var rect = {}; var drag = false; var buttons_shown = false; var angle = 10; var rotate_angle = 0; var original_source = img.src; img.src = original_source; 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); document.addEventListener("keydown", keyDownPressed, false); }); } function keyDownPressed(e) { var keyCode = e.keyCode; var left_arrow = 37; var right_arrow = 39; var up_arrow = 38; var down_arrow = 40; if(keyCode === left_arrow) { onRotateLeft() } if(keyCode === right_arrow){ onRotateRight() } } function mouseDown(e) { rect.startX = e.offsetX; rect.startY = e.offsetY; drag = true; buttons_shown = false; buttons.classList.add("hide"); } function mouseUp() { drag = false; buttons_shown = true; } function onRemoveSelectionClick(e) { ctx.clearRect(0, 0, canvas.width, canvas.height); drag = false; buttons_shown = false; buttons.classList.add("hide"); } function onRotateLeft(){ rotate_angle = rotate_angle - angle; canvas.style.transform = 'rotate(' + rotate_angle + 'deg)'; } function onRotateRight(){ rotate_angle = rotate_angle + angle; canvas.style.transform = 'rotate(' + rotate_angle + 'deg)'; } function mouseMove(e) { if (drag) { ctx.clearRect(0, 0, canvas.width, canvas.height); rect.w = (e.pageX - this.offsetLeft) - rect.startX; rect.h = (e.pageY - this.offsetTop) - rect.startY; ctx.shadowBlur = 5; ctx.filter = 'blur(10px)'; ctx.fillRect(rect.startX, rect.startY, rect.w, rect.h); ctx.strokeRect(rect.startX, rect.startY, rect.w, rect.h); }else{ if(buttons_shown && buttons.classList.contains("hide")){ buttons.classList.remove("hide"); } } } // init(); 
 .hide{ display: none !important; } canvas{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; display:inline-block; background-color: yellow; } 
 <div style="position: relative; overflow: hidden;display:inline-block;"> <img id="photo" src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg"/> <canvas id="canvas"></canvas> </div> <div id="buttons" class="hide"> <button onclick="onRotateLeft()">Rotate Left</button> <button onclick="onRotateRight()">Rotate right</button><br /> <button onclick="onRemoveSelectionClick()">Remove Selection</button> </div> 

Thus, if an object is drawn, I show the buttons to rotate it left or right or to delete it. 因此,如果绘制了一个对象,我将显示向左或向右旋转或删除它的按钮。 If I click on for example Rotate Left button, it executes the next code: 例如,如果我单击“ Rotate Left按钮,它将执行下一个代码:

rotate_angle = rotate_angle - angle;
canvas.style.transform = 'rotate(' + rotate_angle + 'deg)';

But that rotates my whole canvas (yellow background) but I want to rotate only the object inside the canvas. 但这会旋转整个画布(黄色背景),但我只想旋转画布内的对象。

Any idea? 任何想法?

Use canvas transform not CSS transform. 使用画布转换而不是CSS转换。

You need to apply the transform in the canvas when you render the rectangle. 渲染矩形时,需要在画布上应用变换。

The snippet is a copy of your code with some changes. 该代码段是您的代码副本,但有一些更改。

  • The rendering is done via requestAnimationFrame so as not to have needless renders when the mouse moves. 渲染是通过requestAnimationFrame完成的,以便在鼠标移动时不会产生不必要的渲染。

  • A global flag update is set to true whenever there is need to update the canvas. 每当需要更新画布时,全局标志update均设置为true

  • An array of rectangles is used to store each rectangle. rectangles数组用于存储每个矩形。

  • The rectangle object also stores its rotation rect.rotate so that each rectangle has an independent rotation. 矩形对象还存储其旋转rect.rotate以便每个矩形具有独立的旋转。

  • The global variable rect holds the current rectangle. 全局变量rect保存当前矩形。

  • Events change the global rect object and set the update = true flag, they do not do any rendering. 事件会更改全局rect对象并设置update = true标志,它们不执行任何渲染。

  • The rectangle is rotated about its center 矩形围绕其中心旋转

  • Canvas context ctx.rotate uses radians not degrees 画布上下文ctx.rotate使用弧度而不是度

See code for more info. 请参阅代码以获取更多信息。

 var canvas = document.getElementById('canvas'); var buttons = document.getElementById('buttons'); var img = document.getElementById('photo'); var ctx = canvas.getContext('2d'); var rect = {}; var drag = false; var buttons_shown = false; var angle = 10 * (Math.PI / 180) ; var rotate_angle = 0; var update = true; // when true updates canvas var original_source = img.src; img.src = original_source; 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); document.addEventListener("keydown", keyDownPressed, 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); } // array of rectangles const rectangles = []; // adds a rectangle function addRectangle(rect){ rectangles.push(rect); } // draws a rectangle with rotation function drawRect(rect){ ctx.setTransform(1,0,0,1,rect.startX + rect.w / 2, rect.startY + rect.h / 2); ctx.rotate(rect.rotate); ctx.beginPath(); ctx.rect(-rect.w/2, -rect.h/2, rect.w, rect.h); ctx.fill(); ctx.stroke(); } // clears canvas sets filters and draws rectangles function drawCanvas(){ // restore the default transform as rectangle rendering does not restore the transform. ctx.setTransform(1,0,0,1,0,0); ctx.clearRect(0, 0, canvas.width, canvas.height); ctx.shadowBlur = 5; ctx.filter = 'blur(10px)'; rectangles.forEach(drawRect); } function keyDownPressed(e) { var keyCode = e.keyCode; var left_arrow = 37; var right_arrow = 39; var up_arrow = 38; var down_arrow = 40; if(keyCode === left_arrow) { onRotateLeft() } if(keyCode === right_arrow){ onRotateRight() } } // create new rect add to array function mouseDown(e) { rect = { startX : e.offsetX, startY : e.offsetY, w : 1, h : 1, rotate : 0, }; drag = true; buttons_shown = false; buttons.classList.add("hide"); addRectangle(rect); update = true; } function mouseUp() { drag = false; buttons_shown = true; update = true; } // removes top rectangle and sets next down as current or if none then hides controls function onRemoveSelectionClick(e) { rectangles.pop(); if(rectangles.length === 0){ drag = false; buttons_shown = false; buttons.classList.add("hide"); }else{ rect = rectangles[rectangles.length -1]; } update = true; } // rotate current rectangle function onRotateLeft(){ rect.rotate -= angle; update = true; } function onRotateRight(){ rect.rotate += angle; update = true; } function mouseMove(e) { if (drag) { rect.w = (e.pageX - this.offsetLeft) - rect.startX; rect.h = (e.pageY - this.offsetTop) - rect.startY; update = true; }else{ if(buttons_shown && buttons.classList.contains("hide")){ buttons.classList.remove("hide"); } } } // init(); 
 .hide{ display: none !important; } canvas{ position: absolute; left: 0; right: 0; top: 0; bottom: 0; display:inline-block; background-color: yellow; } 
 <div style="position: relative; overflow: hidden;display:inline-block;"> <img id="photo" src="http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg"/> <canvas id="canvas"></canvas> </div> <div id="buttons" class="hide"> <button onclick="onRotateLeft()">Rotate Left</button> <button onclick="onRotateRight()">Rotate right</button><br /> <button onclick="onRemoveSelectionClick()">Remove Selection</button> </div> 

You will need a separate canvas for the object; 您将需要一个单独的画布作为对象。 draw the object on this separate canvas and then, depending on what you actually intend to do, you can either: 在此单独的画布上绘制对象,然后根据您的实际意图执行以下操作:

  • Draw the auxiliary canvas' contents on the main one using context.rotate() combined with context.drawImage() ; 使用context.rotate()结合context.drawImage()在主画布上绘制辅助画布的内容;
  • Overlay one canvas on top of another using CSS. 使用CSS在一个画布上覆盖另一个画布。

Then again, perhaps you could just use context.rotate() then draw on the main canvas as cited in: HTML5 Canvas Rotate Image 再说一次,也许您可​​以只使用context.rotate()然后在主画布上进行绘制,如下所示: HTML5 Canvas Rotate Image

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM