Есть 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;
}
Ответ
Здесь нужно пересчитывать координаты для текста с использованием матрицы поворота в двухмерном пространстве.
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;
}
Комментариев нет:
Отправить комментарий