Поворот текста на Canvas

291
06 марта 2018, 06:00

Есть Canvas, на котором отрисовывается изображение. На изображение можно накладывать текст. Можно выбирать угол наклона текста. Изображение можно перемещать по канвасу. Суть в том, что перемещение изображения работает нормально, но текст должен перемещаться вместе с ним. Однако, так как canvas.context в момент отрисовки текста под углом повернут, оси x и y для текста получаются смещенными. То есть, если повернуть текст на 90 градусов, а потом потянуть картинку вниз/вверх, то текст уедет вправо/влево.

Как можно это исправить? Чтобы текст перемещался вместе с картинкой?

Отрисовка изображения:

    ctx.drawImage(img, 0, 0, canvas.width, canvas.height, viewportOffsetX, viewportOffsetY, img.width, img.height);

Отрисовка текста поверх изображения:

    ctx.save();
    var offsetX = textObj.x;
    var offsetY = textObj.y;
    ctx.translate(offsetX, offsetY);
    ctx.rotate(textObj.rotation);
    ctx.translate(-offsetX, -offsetY);
    ctx.font = textObj.fontSize + 'px ' + textObj.font;
    ctx.fillStyle = textObj.color;
    ctx.fillText(textObj.text, textObj.x, textObj.y);
    textObj.x -= viewportOffsetX;
    textObj.y -= viewportOffsetY;
    ctx.restore();

Изменение viewportOffsetX/viewportOffsetY происходит при драге в mousemove.

viewportOffsetX += deltaX; // смещение по X
viewportOffsetY += deltaY; // смещение по Y

var textInput = null; 
var canvasImage = null; 
var canvas = null; 
var ctx = null; 
 
var renderingInterval = null; 
var textComponents = []; 
 
var scale = 1; 
var viewportOffsetX = 0; 
var viewportOffsetY = 0; 
var drag = false; 
var img = null; 
 
var text = null; 
var font = 'arial'; 
var fontSize = 20; 
var color = '#000'; 
var textRotation = 0; 
 
var originX = 0; 
var originY = 0; 
 
$(document).ready(function(){ 
	img = new Image(); 
  img.src = "http://www.catster.com/wp-content/uploads/2018/01/Cat-flehmen-response.jpg"; 
  canvas = document.getElementById('canvas'); 
  ctx = canvas.getContext("2d"); 
   
  textComponents.push({text: 'Test', x: 0, y: 0, saved: true, font: 'arial', fontSize: 30, color: 'red', rotation: Math.PI / 2}); 
   
  canvas.addEventListener('mousemove', onMouseMove); 
  canvas.addEventListener('touchmove', onMouseMove); 
  canvas.addEventListener('mouseup', onMouseUp); 
  canvas.addEventListener('touchend', onMouseUp); 
  canvas.addEventListener('touchstart', onMouseDown); 
  canvas.addEventListener('mousedown', onMouseDown); 
   
  img.onload = function(){ 
    renderTextCanvas(); 
  }; 
}); 
 
function renderTextCanvas() { 
    ctx.clearRect(0, 0, img.width, img.height); 
    ctx.scale(scale, scale); 
    ctx.drawImage(img, 0, 0, canvas.width, canvas.height, viewportOffsetX, viewportOffsetY, img.width, img.height); 
 
    textComponents.forEach(function (textObj) { 
        ctx.save(); 
        ctx.font = textObj.fontSize + 'px ' + textObj.font; 
        ctx.fillStyle = textObj.color; 
        ctx.rotate(textObj.rotation); 
        if (textObj.saved) { 
            ctx.fillText(textObj.text, textObj.x + viewportOffsetX, textObj.y + viewportOffsetY); 
        } 
        else { 
            ctx.fillText(textObj.text, textObj.x, textObj.y); 
            textObj.saved = true; 
            textObj.x -= viewportOffsetX; 
            textObj.y -= viewportOffsetY; 
        } 
        ctx.restore(); 
    }); 
 
} 
 
    function onMouseUp(e) { 
        drag = false; 
    } 
 
    function onMouseDown(event) { 
        originX = event.pageX; 
        originY = event.pageY; 
 
        if (event.touches) { 
            var touches = event.touches[0]; 
            originX = touches.pageX; 
            originY = touches.pageY; 
        } 
 
        if (textInput) { 
            var rect = canvas.getBoundingClientRect(); 
            var x = originX - rect.left; 
            var y = originY - rect.top; 
            registerTextComponent(textInput, x, y); 
            textInput = null; 
            return; 
        } 
        drag = true; 
    } 
 
 
    function onMouseMove(e) { 
        if (drag) { 
            var pageX = e.pageX; 
            var pageY = e.pageY; 
 
            if (e.touches) { 
                var touches = e.touches[0]; 
                pageX = touches.pageX; 
                pageY = touches.pageY; 
            } 
 
            var deltaX = pageX - originX; 
            var deltaY = pageY - originY; 
 
            if (Math.abs(viewportOffsetX) < Math.abs(img.width / 2)) { 
                viewportOffsetX += deltaX; 
            } 
            else { 
                if (viewportOffsetX < 0) { 
                    viewportOffsetX += 1; 
                } 
                else { 
                    viewportOffsetX -= 1; 
                } 
            } 
            if (Math.abs(viewportOffsetY) < Math.abs(img.height / 2)) { 
                viewportOffsetY += deltaY; 
            } 
            else { 
                if (viewportOffsetY < 0) { 
                    viewportOffsetY += 1; 
                } 
                else { 
                    viewportOffsetY -= 1; 
                } 
            } 
            originX = pageX; 
            originY = pageY; 
            renderTextCanvas(); 
        } 
    }
#canvas{ 
  background: #ffe; 
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> 
 
<canvas width = "600" height = "400" id = "canvas"></canvas>

READ ALSO
отобразить 10 персонажей swapi.co

отобразить 10 персонажей swapi.co

Не получается подтянуть 10 персонажей, получается одного либо всех, помогите плеас

237
Как закрепить всплывающую подсказку floatTip?

Как закрепить всплывающую подсказку floatTip?

Добрый день! Скачал пример всплывающей подсказки с форума, но беда в том, что она у меня прыгает (точнее мерцает) и двигается вправо-влевоХотелось...

412
работа setTimeout()

работа setTimeout()

ЗдравствуйтеНе получается самостоятельно разобраться с setTimeout

228
Отсортировать статьи по дате

Отсортировать статьи по дате

Есть такой код, нужно отсортировать статьи по дате при нажатии на кнопку Sort by date, но без jQuery, всяких плагинов и тд

291