在小屏幕上使用 canvas 为图像添加注释而不调整大小
Add annotation to image with canvas on small screen without resizing
希望你能帮我解决我的问题。我正在用 cordova 和 ionic 编写一个移动应用程序,我们需要一个函数来在上传图像之前对其进行注释。
我希望能够在不调整图像大小的情况下为图像添加注释(目前只有线条)。但是由于手机上的屏幕空间很小,我现在使用 2 canvas 直接放在彼此之上。
第一个我渲染我想注释的缩小图像,第二个我做注释。然后我在 3 canvas 上渲染原始图像并将注释放大到原始图像的大小。
var finalcanvas = document.createElement('canvas');
var ctxfinal = finalcanvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
finalcanvas.width = imageObj.width;
finalcanvas.height = imageObj.height;
ctxfinal.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
var canvaslines = document.getElementById("canvasdraw");
ctxfinal.drawImage(canvaslines, 0, 0, imageObj.width, imageObj.height);
$scope.editimage.image = finalcanvas.toDataURL("image/jpeg");
这很好用,但唯一的缺点是注释相当像素化。我假设一定有一个图书馆或其他东西可以让这样的事情变得更容易,但无论我搜索多少,我都找不到任何东西。但也许我使用了错误的关键字,因为我不是一个非常熟练的程序员,也不是母语人士。预先感谢您的所有帮助
编辑:这是我的代码 http://jsfiddle.net/q97szydq/14/
的一个 link
一个解决方案是将所有点存储到一个数组中,然后在新的 canvas 上重新绘制它们(在重新缩放点之后):
var drawnLines = [];
//in your start functions :
drawnLines.push(["m", x, y]);
//in your move functions :
drawnLines.push(["l", x, y]);
//then in your hideModal function :
var ratio = finalcanvas.width/document.getElementById("canvasdraw").width;
ctxfinal.lineWidth = 3*ratio;
for(i=0; i<drawnLines.length; i++){
var xm = drawnLines[i][1]*ratio;
var ym = drawnLines[i][2]*ratio;
switch (drawnLines[i][0]){
case "l" : ctxfinal.lineTo(xm, ym);
case "m" : ctxfinal.moveTo(xm, ym);
}
}
ctxfinal.stroke();
ctx = document.getElementById("canvasdraw").getContext("2d");
ctx2 = document.getElementById("canvasimg").getContext("2d");
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 3;
var imageObj = new Image();
imageObj.onload = function() { //ion-header-bar
var MAX_WIDTH = 300;
var MAX_HEIGHT = 500;
tempW = imageObj.width;
tempH = imageObj.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
document.getElementById("canvasdraw").height = tempH;
document.getElementById("canvasdraw").width = tempW;
document.getElementById("canvasimg").height = tempH;
document.getElementById("canvasimg").width = tempW;
ctx2.drawImage(imageObj, 0, 0, tempW, tempH);
};
imageObj.src = "http://images2.fanpop.com/image/photos/12900000/Cute-kittens-12929201-1600-1200.jpg";
// setup to trigger drawing on mouse or touch
drawTouch();
drawPointer();
drawMouse();
var drawnLines = [];
//all draw functions have minus 50px height to adjust for header
// prototype to start drawing on touch using canvas moveTo and lineTo
function drawTouch() {
var start = function(e) {
ctx.beginPath();
x = e.changedTouches[0].pageX;
y = e.changedTouches[0].pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
e.preventDefault();
x = e.changedTouches[0].pageX;
y = e.changedTouches[0].pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
};
document.getElementById("canvasdraw").addEventListener("touchstart", start, false);
document.getElementById("canvasdraw").addEventListener("touchmove", move, false);
};
// prototype to start drawing on pointer(microsoft ie) using canvas moveTo and lineTo
function drawPointer() {
var start = function(e) {
e = e.originalEvent;
ctx.beginPath();
x = e.pageX;
y = e.pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
e.preventDefault();
e = e.originalEvent;
x = e.pageX;
y = e.pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
};
document.getElementById("canvasdraw").addEventListener("MSPointerDown", start, false);
document.getElementById("canvasdraw").addEventListener("MSPointerMove", move, false);
};
// prototype to start drawing on mouse using canvas moveTo and lineTo
function drawMouse() {
var clicked = 0;
var start = function(e) {
clicked = 1;
ctx.beginPath();
x = e.pageX;
y = e.pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
if (clicked) {
x = e.pageX;
y = e.pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
}
};
var stop = function(e) {
clicked = 0;
};
document.getElementById("canvasdraw").addEventListener("mousedown", start, false);
document.getElementById("canvasdraw").addEventListener("mousemove", move, false);
document.addEventListener("mouseup", stop, false);
};
var hideModal = function() {
var finalcanvas = document.getElementById("finalcanvas");
var ctxfinal = finalcanvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
finalcanvas.width = imageObj.width;
finalcanvas.height = imageObj.height;
ctxfinal.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
ctxfinal.beginPath();
var ratio = finalcanvas.width / document.getElementById("canvasdraw").width;
ctxfinal.lineWidth = 3 * ratio;
for (i = 0; i < drawnLines.length; i++) {
var xm = drawnLines[i][1] * ratio;
var ym = drawnLines[i][2] * ratio;
switch (drawnLines[i][0]) {
case "l":
ctxfinal.lineTo(xm, ym);
case "m":
ctxfinal.moveTo(xm, ym);
}
}
ctxfinal.stroke();
//I then generate a a image from this final canvas. So now i have the image in the original size + the sadly a bit pixely annotations
//$scope.editimage.image = finalcanvas.toDataURL("image/jpeg");
};
imageObj.src = "http://images2.fanpop.com/image/photos/12900000/Cute-kittens-12929201-1600-1200.jpg";
};
canvas {
border: 1px solid #000;
}
<div id="page">
<div class="buttons" style="height:50px;">
<button class="button button-clear" onclick="hideModal()">save</button>
</div>
<canvas id="canvasimg" style="position:absolute;z-index:1;"></canvas>
<canvas id="canvasdraw" style="position:absolute;background:transparent;z-index:99;"></canvas>
</div>
<div style="position:absolute;top:300px;">
<canvas id="finalcanvas"></canvas>
希望你能帮我解决我的问题。我正在用 cordova 和 ionic 编写一个移动应用程序,我们需要一个函数来在上传图像之前对其进行注释。
我希望能够在不调整图像大小的情况下为图像添加注释(目前只有线条)。但是由于手机上的屏幕空间很小,我现在使用 2 canvas 直接放在彼此之上。
第一个我渲染我想注释的缩小图像,第二个我做注释。然后我在 3 canvas 上渲染原始图像并将注释放大到原始图像的大小。
var finalcanvas = document.createElement('canvas');
var ctxfinal = finalcanvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
finalcanvas.width = imageObj.width;
finalcanvas.height = imageObj.height;
ctxfinal.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
var canvaslines = document.getElementById("canvasdraw");
ctxfinal.drawImage(canvaslines, 0, 0, imageObj.width, imageObj.height);
$scope.editimage.image = finalcanvas.toDataURL("image/jpeg");
这很好用,但唯一的缺点是注释相当像素化。我假设一定有一个图书馆或其他东西可以让这样的事情变得更容易,但无论我搜索多少,我都找不到任何东西。但也许我使用了错误的关键字,因为我不是一个非常熟练的程序员,也不是母语人士。预先感谢您的所有帮助
编辑:这是我的代码 http://jsfiddle.net/q97szydq/14/
的一个 link一个解决方案是将所有点存储到一个数组中,然后在新的 canvas 上重新绘制它们(在重新缩放点之后):
var drawnLines = [];
//in your start functions :
drawnLines.push(["m", x, y]);
//in your move functions :
drawnLines.push(["l", x, y]);
//then in your hideModal function :
var ratio = finalcanvas.width/document.getElementById("canvasdraw").width;
ctxfinal.lineWidth = 3*ratio;
for(i=0; i<drawnLines.length; i++){
var xm = drawnLines[i][1]*ratio;
var ym = drawnLines[i][2]*ratio;
switch (drawnLines[i][0]){
case "l" : ctxfinal.lineTo(xm, ym);
case "m" : ctxfinal.moveTo(xm, ym);
}
}
ctxfinal.stroke();
ctx = document.getElementById("canvasdraw").getContext("2d");
ctx2 = document.getElementById("canvasimg").getContext("2d");
ctx.strokeStyle = "#ffffff";
ctx.lineWidth = 3;
var imageObj = new Image();
imageObj.onload = function() { //ion-header-bar
var MAX_WIDTH = 300;
var MAX_HEIGHT = 500;
tempW = imageObj.width;
tempH = imageObj.height;
if (tempW > tempH) {
if (tempW > MAX_WIDTH) {
tempH *= MAX_WIDTH / tempW;
tempW = MAX_WIDTH;
}
} else {
if (tempH > MAX_HEIGHT) {
tempW *= MAX_HEIGHT / tempH;
tempH = MAX_HEIGHT;
}
}
document.getElementById("canvasdraw").height = tempH;
document.getElementById("canvasdraw").width = tempW;
document.getElementById("canvasimg").height = tempH;
document.getElementById("canvasimg").width = tempW;
ctx2.drawImage(imageObj, 0, 0, tempW, tempH);
};
imageObj.src = "http://images2.fanpop.com/image/photos/12900000/Cute-kittens-12929201-1600-1200.jpg";
// setup to trigger drawing on mouse or touch
drawTouch();
drawPointer();
drawMouse();
var drawnLines = [];
//all draw functions have minus 50px height to adjust for header
// prototype to start drawing on touch using canvas moveTo and lineTo
function drawTouch() {
var start = function(e) {
ctx.beginPath();
x = e.changedTouches[0].pageX;
y = e.changedTouches[0].pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
e.preventDefault();
x = e.changedTouches[0].pageX;
y = e.changedTouches[0].pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
};
document.getElementById("canvasdraw").addEventListener("touchstart", start, false);
document.getElementById("canvasdraw").addEventListener("touchmove", move, false);
};
// prototype to start drawing on pointer(microsoft ie) using canvas moveTo and lineTo
function drawPointer() {
var start = function(e) {
e = e.originalEvent;
ctx.beginPath();
x = e.pageX;
y = e.pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
e.preventDefault();
e = e.originalEvent;
x = e.pageX;
y = e.pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
};
document.getElementById("canvasdraw").addEventListener("MSPointerDown", start, false);
document.getElementById("canvasdraw").addEventListener("MSPointerMove", move, false);
};
// prototype to start drawing on mouse using canvas moveTo and lineTo
function drawMouse() {
var clicked = 0;
var start = function(e) {
clicked = 1;
ctx.beginPath();
x = e.pageX;
y = e.pageY - 50;
ctx.moveTo(x, y);
drawnLines.push(["m", x, y]);
};
var move = function(e) {
if (clicked) {
x = e.pageX;
y = e.pageY - 50;
ctx.lineTo(x, y);
ctx.stroke();
drawnLines.push(["l", x, y]);
}
};
var stop = function(e) {
clicked = 0;
};
document.getElementById("canvasdraw").addEventListener("mousedown", start, false);
document.getElementById("canvasdraw").addEventListener("mousemove", move, false);
document.addEventListener("mouseup", stop, false);
};
var hideModal = function() {
var finalcanvas = document.getElementById("finalcanvas");
var ctxfinal = finalcanvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
finalcanvas.width = imageObj.width;
finalcanvas.height = imageObj.height;
ctxfinal.drawImage(imageObj, 0, 0, imageObj.width, imageObj.height);
ctxfinal.beginPath();
var ratio = finalcanvas.width / document.getElementById("canvasdraw").width;
ctxfinal.lineWidth = 3 * ratio;
for (i = 0; i < drawnLines.length; i++) {
var xm = drawnLines[i][1] * ratio;
var ym = drawnLines[i][2] * ratio;
switch (drawnLines[i][0]) {
case "l":
ctxfinal.lineTo(xm, ym);
case "m":
ctxfinal.moveTo(xm, ym);
}
}
ctxfinal.stroke();
//I then generate a a image from this final canvas. So now i have the image in the original size + the sadly a bit pixely annotations
//$scope.editimage.image = finalcanvas.toDataURL("image/jpeg");
};
imageObj.src = "http://images2.fanpop.com/image/photos/12900000/Cute-kittens-12929201-1600-1200.jpg";
};
canvas {
border: 1px solid #000;
}
<div id="page">
<div class="buttons" style="height:50px;">
<button class="button button-clear" onclick="hideModal()">save</button>
</div>
<canvas id="canvasimg" style="position:absolute;z-index:1;"></canvas>
<canvas id="canvasdraw" style="position:absolute;background:transparent;z-index:99;"></canvas>
</div>
<div style="position:absolute;top:300px;">
<canvas id="finalcanvas"></canvas>