LINUX.ORG.RU

Canvas в долбоскрипте...

 ,


0

1

Здравствуйте. Ковыряю некий скрипт, масштабирующий и кропящий картинки. Хочу добавить функционал вращения. С удивлением узнал, что канва вращается вместе с полем координат. Так как кропить надо и после вращения, нужно как-то сообщать реальные координаты функции кропа.

Вопрос: можно ли к объекту канвы добавить своё свойство (перегрузить, так сказать), в котором хранится угол поворота? Это бы сильно улучшило программу и мою карму по сравнению с созданием левой глобальной переменной.

В общем, написал с нуля сам, попутно разбираясь. 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>

★★★★★

Последнее исправление: Shadow (всего исправлений: 2)

Ответ на: комментарий от NightmareZombie

Я хочу хранить угол поворота объекта на канве в свойствах объекта. Что тут непонятного?

Просто взаимодействие с объектом - через координаты мыши, которые после вращения объекта не совпадают с полем координат объекта.

Shadow ★★★★★
() автор топика
Последнее исправление: Shadow (всего исправлений: 1)

можно ли к объекту канвы добавить своё свойство

Любой объект в JS, в т.ч. элемент DOM — это по сути ассоциативный массив (хэш), к нему спокойно можно добавлять любые соответствия «ключ : значение».

OldManClone ★★
()

С удивлением узнал, что канва вращается вместе с полем координат

Попробуй вращать не канву а рисунок.

ya-betmen ★★★★★
()

Так как кропить надо и после вращения, нужно как-то сообщать реальные координаты функции кропа.

Ну тогда вращай её обратно перед кропом или используй context.save и context.restore.

proud_anon ★★★★★
()
Ответ на: комментарий от proud_anon

restore у меня восстанавливает угол поворота в том числе. Может, есть где почитать про внутренности этого дела, чтобы понимать, кто кого вращает? А то примеры и спецификации это не объясняют.

Shadow ★★★★★
() автор топика
Ответ на: комментарий от Shadow

rotate вращает только верхний контекст в стеке.

save - кладёт новый контекст в стек.

restore - снимет верхний контекст со стека.

Я думал ты сам canvas крутишь.

ya-betmen ★★★★★
()
Ответ на: комментарий от Shadow

restore у меня восстанавливает угол поворота в том числе.

Ну да, разве тебе не это было надо? Или у тебя и то, что уже нарисовано, при этом поворачивается?

proud_anon ★★★★★
()
Последнее исправление: proud_anon (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.