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