Страницы

Поиск по вопросам

воскресенье, 15 декабря 2019 г.

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

#javascript #html5 #canvas #html5_canvas


Есть 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;
}






    


Ответы

Ответ 1



Здесь нужно пересчитывать координаты для текста с использованием матрицы поворота в двухмерном пространстве. 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) { //!!!! var x = viewportOffsetX * Math.cos(textObj.rotation) + viewportOffsetY * Math.sin(textObj.rotation); var y = -viewportOffsetX * Math.sin(textObj.rotation) + viewportOffsetY * Math.cos(textObj.rotation); ctx.fillText(textObj.text, textObj.x + x, textObj.y + y); } 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; }

Комментариев нет:

Отправить комментарий