#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; }
Комментариев нет:
Отправить комментарий