如何以正确的方式旋转画布
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何以正确的方式旋转画布相关的知识,希望对你有一定的参考价值。
我有一个想要裁剪的图像。
因此,我用较暗的背景创建了canvas as overlay
然后在鼠标移动时我在画布上绘制了一个rect
,在那个矩形中我清除了黑暗的背景。看起来如下:
因此,将裁剪没有背景的区域。
我的代码如下:
var canvas = document.getElementById('canvas');
var img = document.getElementById('photo');
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var update = true; // when true updates canvas
var original_source = img.src;
img.src = original_source;
var deg = 0;
var image_rotate_angle = 90;
document.getElementById('right').addEventListener("click", rotateRight, false);
document.getElementById('left').addEventListener("click", rotateLeft, false);
function rotateRight(){
deg = deg + image_rotate_angle;
img.style.transform = "rotate(" + deg + "deg)";
canvas.style.transform = "rotate(" + deg + "deg)";
}
function rotateLeft(){
deg = deg - image_rotate_angle;
img.style.transform = "rotate(" + deg + "deg)";
canvas.style.transform = "rotate(" + deg + "deg)";
}
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.clearRect(rect.startX, rect.startY, rect.w, rect.h);
}
// clears canvas sets filters and draws rectangles
function drawCanvas(){
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(32, 32, 32, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawRect()
}
// create new rect add to array
function mouseDown(e) {
rect = {
startX : e.offsetX,
startY : e.offsetY,
w : 1,
h : 1
};
drag = true;
}
function mouseUp() { drag = false; 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;
}
}
init();
canvas{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
display:inline-block;
background:rgba(0,0,0,0.3);
}
<div style="margin-bottom: 15px;">
<button id="left">Rotate Reft</button>
<button id="right">Rotate Right</button>
</div>
<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>
我还有两个用于旋转图像的按钮。我有问题。解决方案可能很明显,但我没有看到。
- 如果我绘制一个矩形然后旋转图像,我也旋转图像和画布,然后旋转后矩形停留在同一个地方。这就是我想要的,并且工作正常。
- 问题是如果我先旋转图像,然后尝试绘制一个矩形。然后矩形不是应该绘制的,它朝相反的方向。
知道怎么解决吗?
答案
根据图像的大小,你可能只是得到数学来找到新的x和y所在的位置,但我想在画布上实际绘制所有内容并旋转其变换矩阵将更易于管理。
但这意味着您的代码会发生一些变化:
您必须使用合成(或使用'偶数'填充规则,like I already shown you)绘制图像。
您还必须使drawCanvas
功能更复杂,以便仅在需要时(当用户单击“旋转”按钮时)旋转您的孔。
var canvas = document.getElementById('canvas');
var img = new Image();
var ctx = canvas.getContext('2d');
var rect = {};
var drag = false;
var update = true; // when true updates canvas
var angle = 0;
document.getElementById('right').addEventListener("click", rotateRight, false);
document.getElementById('left').addEventListener("click", rotateLeft, false);
function rotateRight() {
angle += Math.PI / 2;
drawCanvas(true); // let know we're from rotate function
}
function rotateLeft() {
angle -= Math.PI / 2;
drawCanvas(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(false); // don't rotate the rectangle here
update = false;
}
requestAnimationFrame(updateCanvas);
}
// draws a rectangle with rotation
function drawRect() {
ctx.clearRect(rect.startX, rect.startY, rect.w, rect.h);
}
// clears canvas sets filters and draws rectangles
function drawCanvas(fromRotate) {
// reset the transformation matrix to its defaults
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'rgba(32, 32, 32, 0.7)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
// for the rectangle, rotate only if we are using previously set rect
if (fromRotate) {
// Move to center
ctx.setTransform(1, 0, 0, 1, canvas.width / 2, canvas.height / 2);
// rotate by the current angle
ctx.rotate(angle);
// move back to what is now top right corner
ctx.translate(-canvas.width / 2, -canvas.height / 2);
}
drawRect();
// draw the image behind the overlay
ctx.globalCompositeOperation = 'destination-over';
// rotate the whole context every time for the image
ctx.setTransform(1, 0, 0, 1, canvas.width / 2, canvas.height / 2);
// rotate by the current angle
ctx.rotate(angle);
// draw the image, from center
ctx.drawImage(img, -img.width / 2, -img.height / 2);
}
// create new rect add to array
function mouseDown(e) {
rect = {
startX: e.offsetX,
startY: e.offsetY,
w: 1,
h: 1
};
drag = true;
}
function mouseUp() {
drag = false;
update = true;
}
function mouseMove(e) {
if (drag) {
rect.w = (e.offsetX - this.offsetLeft) - rect.startX;
rect.h = (e.offsetY - this.offsetTop) - rect.startY;
update = true;
}
}
init();
img.src = 'https://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
<div style="margin-bottom: 15px;">
<button id="left">Rotate Reft</button>
<button id="right">Rotate Right</button>
</div>
<div style="position: relative; overflow: hidden;display:inline-block;">
<canvas id="canvas"></canvas>
</div>
以上是关于如何以正确的方式旋转画布的主要内容,如果未能解决你的问题,请参考以下文章