2012-10-25 7 views
9

Es gibt Hunderte von Tutorials, wie man ein Bild von drawImage() auf einer Leinwand zuschneiden kann.Crop Canvas/Export html5 Leinwand mit bestimmter Breite und Höhe

context.drawImage(imageObj, sourceX, sourceY, sourceWidth, sourceHeight, destX, destY, destWidth, destHeight); 

Allerdings habe ich eine Leinwand, die den Browser des Benutzers füllt. Durch den Export der Leinwand als Bild möchte ich nur einen Bereich von 640px * 480px aus (0 | 0) exportieren.

Problem: Wie kann ich JavaScript sagen, nur 640 * 480 des Canvas für die toDataURL() zu verwenden?

Hier ist, was ich bisher:

$("#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: Ich will nicht, oder Maßstab, um die Größe, nur Clipping/zum festen Fenster beschneiden. Here Ich lese, dass Sie nur canvas.width und canvas.height angeben - aber das löscht die Leinwand.

Antwort

18

Der beste Weg besteht darin, nur einen temporären Canvas zu erstellen, auf den aus dem aktuellen Canvas gezeichnet werden kann. Der Benutzer wird diesen temporären Canvas nie sehen. Dann brauchen Sie nur toDataUrl() auf der temporären Leinwand.

Live Demo

$("#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>'); 
})​ 
+1

Super, funktioniert sehr gut!/Das einzige, was mich irritiert, ist, dass Firefox das Laden der Seite anzeigt (Tab zeigt den Wendekreis), wenn das Bild bereits angezeigt wurde. Ein Klick auf ESC zeigt wyciwyg: // in der URL !? ... "wyciwyg ist ein internes URI-Schema, das verwendet wird, um document.write-Ergebnisseiten darzustellen"/Aber wie auch immer, glücklich, dass Sie mir eine funktionierende Lösung gegeben haben! –

+3

Die Variable "data" wird zugewiesen, aber nie verwendet ... –

+2

noch die Variable compositeOperation –

1

Sie erstellen eine zweite Offscreen-Leinwand, Sie kopieren das Bild von der ersten Leinwand in die zweite (mit der ersten als Ihr Bildobjekt), dann exportieren Sie die zweite Leinwand.

1

Reines html5 Leinwand Ernte. Sie können es live ausprobieren 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); 
} 

})