There are hundreds of tutorials, how one can crop an image by drawImage() on a canvas.
context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight);
However, I have a canvas that fills the user's browser. By exporting the canvas as an image I would like to export only an area of 640px*480px from (0|0).
Problem: How can I tell javascript to use only 640*480 of the canvas for the toDataURL()?
Here is what I have so far:
$("#submitGraphic").click( function(){
var canvas = document.getElementsByTagName("canvas");
// canvas context
var context = canvas[0].getContext("2d");
// get the current ImageData for the canvas
var data = context.getImageData(0, 0, canvas[0].width, canvas[0].height);
// store the current globalCompositeOperation
var compositeOperation = context.globalCompositeOperation;
// set to draw behind current content
context.globalCompositeOperation = "destination-over";
//set background color
context.fillStyle = "#FFFFFF";
// draw background/rectangle on entire canvas
context.fillRect(0,0,canvas[0].width,canvas[0].height);
// not working, seems to clear the canvas? browser hangs?
// seems that I can click a white image in the background
/*canvas[0].width = 640;
canvas[0].height = 480;*/
// not working either
/*canvas[0].style.width = '640px';
canvas[0].style.height = '480px';*/
// not working at all
/*context.canvas.width = 640;
context.canvas.height = 480;*/
// write on screen
var img = canvas[0].toDataURL("image/png");
document.write('<a href="'+img+'"><img src="'+img+'"/></a>');
})
PS: I do not want to resize or scale, just clipping/cropping to the fixed window. Here I read that you only specifiy canvas.width and canvas.height - but this clears the canvas.
The best way is to just create a temporary canvas to draw onto from the current canvas. The user will never see this temp canvas. Then you just need use toDataUrl()
on the temp canvas.
$("#submitGraphic").click( function(){
var canvas = document.getElementsByTagName("canvas");
// canvas context
var context = canvas[0].getContext("2d");
// get the current ImageData for the canvas
var data = context.getImageData(0, 0, canvas[0].width, canvas[0].height);
// store the current globalCompositeOperation
var compositeOperation = context.globalCompositeOperation;
// set to draw behind current content
context.globalCompositeOperation = "destination-over";
//set background color
context.fillStyle = "#FFFFFF";
// draw background/rectangle on entire canvas
context.fillRect(0,0,canvas[0].width,canvas[0].height);
var tempCanvas = document.createElement("canvas"),
tCtx = tempCanvas.getContext("2d");
tempCanvas.width = 640;
tempCanvas.height = 480;
tCtx.drawImage(canvas[0],0,0);
// write on screen
var img = tempCanvas.toDataURL("image/png");
document.write('<a href="'+img+'"><img src="'+img+'"/></a>');
})
I created a simple general purpose function that does the crop by returning a new canvas with the cropped area. While it doesn't do the crop "in place", it's simple. Remember to switch to the new context after the call.
const cropCanvas = (sourceCanvas,left,top,width,height) => {
let destCanvas = document.createElement('canvas');
destCanvas.width = width;
destCanvas.height = height;
destCanvas.getContext("2d").drawImage(
sourceCanvas,
left,top,width,height, // source rect with content to crop
0,0,width,height); // newCanvas, same size as source rect
return destCanvas;
}
For example...
let myCanvas = document.createElement('canvas');
myCanvas.width = 200;
myCanvas.height = 200;
let myContext = myCanvas.getContext("2d");
// draw stuff...
myCanvas = cropCanvas(myCanvas,50,50,100,100);
myContext = myCanvas.getContext("2d");
// now using the cropped 100x100 canvas
You make a second off-screen canvas, you copy the image from the first canvas to the second (using the first as your image object), then you export the second canvas.
Pure html5 canvas crop. You can check it out live here
$('document').ready( function(){
const divOffset = 1
var x1,x2,y1,y2, xDif, yDif = 0;
var isSelection,
isBottomRight,
isTopRight,
isTopLeft,
isBottomLeft = false
var r = document.getElementById('source').getBoundingClientRect();
var pos = [0, 0];
pos[0] = r.left;
pos[1] = r.top; //got position coordinates of canvas
var sel = document.getElementById('sel')
var canvasSource = document.getElementById("source");
var ctxSource = canvasSource.getContext("2d");
var img = new Image()
img.src = "http://bohdaq.name/assets/localImage.jpg"
img.onload = function(){
ctxSource.drawImage(img, 0, 0)
}
$( "#source" ).mousedown(function(event) {
isSelection = true
x1 = event.pageX - pos[0]
y1 = event.pageY - pos[1]
sel.style.setProperty('display', 'block')
sel.style.setProperty('left', event.pageX + "px")
sel.style.setProperty('top', event.pageY + "px")
sel.style.setProperty('width', '0px')
sel.style.setProperty('height', '0px')
});
$( "#source" ).mouseup(function(event) {
isSelection = false
if(isBottomRight){
x2 = event.pageX - pos[0]
y2 = event.pageY - pos[1]
xDif = x2-x1
yDif = y2-y1
} else if (isBottomLeft){
y2 = event.pageY - pos[1]
yDif = y2 - y1
xDif = x1 - x2
x1 = x1 - xDif
} else if(isTopRight){
x2 = event.pageX - pos[0]
xDif = x2 - x1
yDif = y1 - y2
y1 = y1 - yDif
} else if (isTopLeft){
xDif = x1 - x2
x1 = x1 - xDif
yDif = y1 - y2
y1 = y1 - yDif
}
sel.style.setProperty('display', 'none')
crop(x1, y1, xDif, yDif)
});
$('#source').mousemove(function(event){
if(isSelection){
x2 = event.pageX - pos[0]
y2 = event.pageY - pos[1]
if(x2>x1 && y2>y1){ //moving right bottom selection
isBottomRight = true
isBottomLeft = false
isTopLeft = false
isTopRight = false
xDif = x2 - x1
yDif = y2 - y1
sel.style.setProperty('width', xDif + 'px')
sel.style.setProperty('height', yDif + 'px')
} else if(x2<x1 && y2>y1){ //moving left bottom selection
isBottomLeft = true
isTopLeft = false
isTopRight = false
isBottomRight = false
xDif = x1 - x2
yDif = y2 - y1
sel.style.setProperty('left', x2 + 'px')
sel.style.setProperty('width', xDif + 'px')
sel.style.setProperty('height', yDif + 'px')
} else if(x2>x1 && y2<y1){
isTopRight = true
isTopLeft = false
isBottomLeft = false
isBottomRight = false
xDif = y1 - y2
yDif = x2 - x1
sel.style.setProperty('top', y2 + 'px')
sel.style.setProperty('width', yDif + 'px')
sel.style.setProperty('height', xDif + 'px')
} else if (x2<x1 && y2<y1){
isTopLeft = true
isTopRight = false
isBottomLeft = false
isBottomRight = false
yDif = y1 - y2
xDif = x1 - x2
sel.style.setProperty('left', x2 + pos[0] + divOffset + 'px')
sel.style.setProperty('top', y2 + pos[1] + divOffset + 'px')
sel.style.setProperty('width', xDif + 'px')
sel.style.setProperty('height', yDif + 'px')
}
}
})
function crop(x, y, xDif, yDif){
canvasSource.width = xDif
canvasSource.height = yDif
ctxSource.drawImage(img, x, y, xDif, yDif, 0, 0, xDif, yDif);
}
})
based on @GarySkiba answer:
// crop canvas function
const cropCanvas = (
canvas: any,
x: number,
y: number,
width: number,
height: number
) => {
// create a temp canvas
const newCanvas = document.createElement('canvas');
// set its dimensions
newCanvas.width = width;
newCanvas.height = height;
// draw the canvas in the new resized temp canvas
newCanvas
.getContext('2d')!
.drawImage(canvas, x, y, width, height, 0, 0, width, height);
return newCanvas
};
use it like:
// get canvas from somewhere
const canvas = ....;
// crop the left top 50x50 rect
const newCanvas = cropCanvas(canvas, 0, 0, 50, 50 );
// get the relative image
newCanvas.toDataURL('image/png')
来源:https://stackoverflow.com/questions/13073647/crop-canvas-export-html5-canvas-with-certain-width-and-height