I'v encountered a small problem while trying to create an easy-to-use image-editor, where you can add multiple draggable texts on an image and then save the edited image with texts by original resolution.
Everything else works fine, but I want to be able to edit full-hd images and bigger on a non-full-hd resolution canvas (like 800x600px)
I cant use resolutions like 1920x1080 or bigger on the canvas, since it will be to massive and go out of the borders of browser (scrollbars) and also wont be really so easy to manage.
I tried to use percentage value on canvas, and it looks OK, but the text hitbox wont follow the cursor when dragging around.
Any tips or tricks to handle this problem?
Here is a sample how it looks with 1920x1080 canvas & full-hd image. I would like to fit the image and functionality to a.. lets say 800x600 canvas but save the output as original full-hd.
<canvas id="canvas" width=1920 height=1080></canvas>
function draw() {
//ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(imageObj, 0, 0, 1920, 1080);
for (var i = 0; i < texts.length; i++) {
var text = texts[i];
ctx.fillText(text.text, text.x, text.y);
}
}
https://jsfiddle.net/n0mn7bcg/
// canvas related variables
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// variables used to get mouse position on the canvas
var $canvas = $("#canvas");
var canvasOffset = $canvas.offset();
var offsetX = canvasOffset.left;
var offsetY = canvasOffset.top;
var scrollX = $canvas.scrollLeft();
var scrollY = $canvas.scrollTop();
var imageObj = new Image();
imageObj.src = 'https://4.bp.blogspot.com/-lQwIDyafEbI/UxNch2499rI/AAAAAAAAogo/FfZxYSCIXxc/s0/Ships+in+from+the+bottle_2_HD.jpg';
// variables to save last mouse position
// used to see how far the user dragged the mouse
// and then move the text by that distance
var startX;
var startY;
// an array to hold text objects
var texts = [];
// this var will hold the index of the hit-selected text
var selectedText = -1;
// clear the canvas & redraw all texts
function draw() {
//ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.drawImage(imageObj, 0, 0, 1920, 1080);
for (var i = 0; i < texts.length; i++) {
var text = texts[i];
ctx.fillText(text.text, text.x, text.y);
}
}
// test if x,y is inside the bounding box of texts[textIndex]
function textHittest(x, y, textIndex) {
var text = texts[textIndex];
return (x >= text.x && x <= text.x + text.width && y >= text.y - text.height && y <= text.y);
}
// handle mousedown events
// iterate through texts[] and see if the user
// mousedown'ed on one of them
// If yes, set the selectedText to the index of that text
function handleMouseDown(e) {
e.preventDefault();
startX = parseInt(e.clientX - offsetX);
startY = parseInt(e.clientY - offsetY);
// Put your mousedown stuff here
for (var i = 0; i < texts.length; i++) {
if (textHittest(startX, startY, i)) {
selectedText = i;
}
}
}
// done dragging
function handleMouseUp(e) {
e.preventDefault();
selectedText = -1;
}
// also done dragging
function handleMouseOut(e) {
e.preventDefault();
selectedText = -1;
}
// handle mousemove events
// calc how far the mouse has been dragged since
// the last mousemove event and move the selected text
// by that distance
function handleMouseMove(e) {
if (selectedText < 0) {
return;
}
e.preventDefault();
mouseX = parseInt(e.clientX - offsetX);
mouseY = parseInt(e.clientY - offsetY);
// Put your mousemove stuff here
var dx = mouseX - startX;
var dy = mouseY - startY;
startX = mouseX;
startY = mouseY;
var text = texts[selectedText];
text.x += dx;
text.y += dy;
draw();
}
// listen for mouse events
$("#canvas").mousedown(function(e) {
handleMouseDown(e);
});
$("#canvas").mousemove(function(e) {
handleMouseMove(e);
});
$("#canvas").mouseup(function(e) {
handleMouseUp(e);
});
$("#canvas").mouseout(function(e) {
handleMouseOut(e);
});
$("#submit").click(function() {
// calc the y coordinate for this text on the canvas
var y = texts.length * 20 + 20;
// get the text from the input element
var text = {
text: $("#theText").val(),
x: 20,
y: y
};
// calc the size of this text for hit-testing purposes
ctx.font = "80px consolas";
text.width = ctx.measureText(text.text).width;
text.height = 80;
// put this new text in the texts array
texts.push(text);
// redraw everything
draw();
});
body {
background: #f3f3f3;
}
#canvas {
border: 1px solid red;
}
#theText {
width: 10em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h4>Add text to canvas and drag it</h4>
<input id="theText" type="text">
<button id="submit">Draw text on canvas</button>
<br>
<canvas id="canvas" width=1920 height=1080></canvas>