Здравствуйте. Ковыряю некий скрипт, масштабирующий и кропящий картинки. Хочу добавить функционал вращения. С удивлением узнал, что канва вращается вместе с полем координат. Так как кропить надо и после вращения, нужно как-то сообщать реальные координаты функции кропа.
Вопрос: можно ли к объекту канвы добавить своё свойство (перегрузить, так сказать), в котором хранится угол поворота? Это бы сильно улучшило программу и мою карму по сравнению с созданием левой глобальной переменной.
В общем, написал с нуля сам, попутно разбираясь. save() и restore() с растром в контексте не работают, нужно двигать центр координат через translate и СОХРАНЯТЬ УГОЛ ПОВОРОТА в отдельной переменной, чтобы по ней пересчитывать координаты мыши. При этом при последующем вращении к вращаемому контексту всё тот же угол ДОБАВЛЯЕТСЯ к текущему состоянию (это важно при перепозиционировании контекста после поворота), а при пересчёте координат мыши нужно рассчитывать полный суммарный угол.
Код:
<!DOCTYPE html>
<html>
<HEAD>
<STYLE type="text/css">
/* Core component styles */
.image-crop {
align: left;
width: 300px;
margin: 0 auto;
position: relative;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
-o-user-select: none;
user-select: none;
}
/* rotate handle */
.image-crop .rotate-handle {
display: block;
position: absolute;
bottom: 6px;
right: 2px;
background: rgba(255,255,255,0.7);
width: 50px;
height: 50px;
cursor: pointer;
border-radius: 50px 50px;
}
.image-crop .rotate-handle > span {
text-align: center;
color: rgba(0, 0, 0, 0.5);
font-size: 34pt;
display: block;
position: relative;
top: -10px;
}
/* zoomin handle */
.image-crop .zoomin-handle {
display: block;
position: absolute;
bottom: 6px;
left: 2px;
background: rgba(255,255,255,0.7);
width: 50px;
height: 50px;
cursor: pointer;
border-radius: 50px 50px;
}
.image-crop .zoomin-handle > span {
text-align: center;
color: rgba(0, 0, 0, 0.5);
font-size: 34pt;
display: block;
position: relative;
top: -10px;
}
/* zoomout handle */
.image-crop .zoomout-handle {
display: block;
position: absolute;
bottom: 6px;
left: 56px;
background: rgba(255,255,255,0.7);
width: 50px;
height: 50px;
cursor: pointer;
border-radius: 50px 50px;
}
.image-crop .zoomout-handle > img {
text-align: center;
color: rgba(0, 0, 0, 0.5);
font-size: 34pt;
display: block;
position: relative;
top: 8px;
left: 8px;
}
</STYLE>
</HEAD>
<body>
<div class="image-crop"><canvas id="example" width="300" height="300" style="border:1px solid #d3d3d3;" onmousedown="onCanvasMouseDown(event)" onmousemove="onCanvasMouseMove(event)" onmouseup="onCanvasMouseUp(event)">
Your browser does not support the HTML5 canvas tag.</canvas>
<div class="zoomin-handle" onclick="zoomin(event)"><img src="zoomin.svg"></div>
<div class="zoomout-handle" onclick="zoomout(event)"><img src="zoomout.svg"></div>
<div class="rotate-handle" onclick="rotate(event)"><img src="curved2.svg"></div>
</div>
<script>
var currentX = 0, currentY = 0, dragging = false, startX = 0, startY = 0, zooming = false;
zoom = 1;
var minXPos = 0, maxXPos = 50, minYPos = 0, maxYPos = 50, xangle = 0;
var height = 300, width = 300;
function reset() {
files = [];
zoom = 1;
ctx.clearRect(0, 0, $canvas.width, $canvas.height);
$input.value = null;
$img.src = '';
}
function zoomin() {
zoom = zoom * 1.1;
var newXPos = currentX * zoom;
var newYPos = currentY * zoom;
moveImage(currentX, currentY);
}
function zoomout() {
zoom = zoom / 1.1;
var newXPos = currentX * zoom;
var newYPos = currentY * zoom;
moveImage(currentX, currentY);
}
function moveImage(x, y) {
var xcos = Math.round(Math.cos(xangle * Math.PI));
var xsin = Math.round(Math.sin(xangle * Math.PI));
x2 = x * xcos + y * xsin;
y2 = y * xcos - x * xsin;
targetX = x;
targetY = y;
ctx.clearRect(0, 0, $canvas.width, $canvas.height);
ctx.drawImage($img, x2, y2, $img.width * zoom, $img.height * zoom);
}
function updateDragBounds() {
minXPos = $canvas.width - ($img.width * zoom);
minYPos = $canvas.height - ($img.height * zoom);
}
onCanvasMouseUp = function(e) {
startX = 0;
startY = 0;
dragging = false;
currentX = targetX;
currentY = targetY;
};
onCanvasMouseDown = function(e) {
startX = e.clientX;
startY = e.clientY;
zooming = false;
dragging = true;
};
onCanvasMouseMove = function(e) {
if (!dragging) {
return;
}
var diffX = startX - e.clientX;
var diffY = startY - e.clientY;
moveImage(currentX - diffX, currentY - diffY);
};
rotate = function(e) {
ctx.translate(150, 150);
ctx.rotate(0.5 * Math.PI);
ctx.translate(-150, -150);
xangle = xangle + 0.5;
var tX = currentX;
var tY = currentY;
currentX = -tY;
currentY = tX;
targetX = -tY;
targetY = tX;
moveImage(currentX, currentY);
};
var $canvas = document.getElementById('example'),
ctx = $canvas.getContext('2d'),
$img = new Image();
$canvas.height = 300;
$canvas.width = 300;
$img.src = '488132.jpg';
newWidth = $img.width * zoom;
newHeight = $img.height * zoom;
$img.onload = function () {
ctx.drawImage($img, 0, 0);
}
</script>
</body>
</html>