2016-11-24 36 views
1

我已創建2畫布,加載兩個不同的圖像,我想合併兩個畫布,然後顯示它作爲圖像在<div id="test"></div>標記。畫布不合並,導致只顯示背景圖像

這裏是我的代碼:

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <title>canvas to image</title> 
</head> 
<body> 
<div> 
    <canvas id="card_canvas" width="800" height="500"></canvas> 
    <canvas id="card_canvas2" width="800" height="500"></canvas> 
</div> 
<div id="test"></div> 
<button onclick="canvasToImage()">canvas to image</button> 
<script> 
    var img1 = new Image(); 
     img1.src = "images/img1.jpg"; 
    var cuimg; 
    function canvasToImage(){ 
     var canvass1 = document.getElementById("card_canvas"); 
     var canvass2 = document.getElementById("card_canvas2"); 
     var ctx1 = canvass1.getContext('2d'); 
     var ctx2 = canvass2.getContext('2d'); 
     ctx1.drawImage(img1, 0, 0); 
     cuimg = new Image(); 
     cuimg.onload = function(){ 
      ctx2.drawImage(cuimg, 7, 92); 
     } 
     cuimg.src = "images/img2.jpg"; 
     ctx1.drawImage(canvass2, 0, 0); 
     var imgdata = canvass1.toDataURL('image/png'); 
     var mergeimg = document.createElement("img"); 
     mergeimg.src = imgdata; 
     document.getElementById("test").appendChild(mergeimg); 
    } 
</script> 
</body> 
</html> 

這裏是img1.jpg:

img1.jpg

這裏是img2.jpg:

img2.jpg

此代碼結束僅顯示背景圖像:

result

我期待:

expected

+0

要調用ctx1.drawImage(canvas2)和canvas1.toDataURL(),而你還沒有畫上canvas2圖像:你把它畫到畫布上,這使得這個之前正確使用圖像的onload事件操作異步。此操作發生後,您需要調用邏輯跟蹤。 – Kaiido

回答

0

這可以通過簡單的設置canvas2以下樣式實現:

<canvas id="card_canvas2" style="position:absolute; left:0px; top:0px;"></canvas> 

https://jsfiddle.net/jkjqd7gz/

+0

這隻會重疊畫布並顯示它,我將無法將其另存爲圖像。 – user123456987

+0

在你的小提琴中,做一個右鍵單擊和查看圖像它只顯示lee9圖像,但我希望它合併黃色背景和lee9圖像,然後使其成爲一個圖像,然後顯示它。所以基本上,當右鍵單擊並查看圖像時,它應該顯示黃色背景和lee9徽標。 – user123456987

+0

請檢查這個鏈接[鏈接](http://www.html5canvastutorials.com/tutorials/html5-canvas-image-loader/) – Sudarsh

1

我一直fiddlin g和你的代碼一起,我想我已經找出了這個問題。在大多數人都不知道的時候,JavaScript有一個有趣的執行順序。您的onload lambda函數正在導致您遇到的一些問題。基本上,你需要移動你的ctx1.drawImage(canvass2,0,0);在ctx2.drawImage(cuimg,7,92)之後,在你的lambda函數內部行;要理解我的意思是打開你的代碼並點擊畫布上的圖像按鈕兩次。第一次填充兩個畫布,第二次將canvass2的內容放到canvass1上。我大概可以從執行順序的角度解釋發生了什麼,但是這個解釋涉及到關於並行性,交換緩衝區和競爭條件的一些難以理解的概念。

簡而言之,無論您調用ctx2.drawImage的函數是什麼,您都需要使用ctx1.drawImage來跟蹤它。坦率地說,製作合成圖像的最佳方法是創建一個精靈類,如果需要,它可以存儲圖像,位置和圖層信息。然後使用動態數組來存儲精靈。每次在繪製之前總是先清除畫布,然後遍歷數組的內容,然後在各自的畫布上按層次順序繪製每個精靈。最後,我將使用一組函數來填充畫布,第二組將它們合併。

<!DOCTYPE html> 
<html> 
<head> 
    <meta charset="UTF-8"> 
    <title>canvas to image</title> 
</head> 
<body> 
<div> 
    <canvas id="card_canvas" width="800" height="500"></canvas> 
    <canvas id="card_canvas2" width="800" height="500"></canvas> 
</div> 
<div id="test"></div> 
<button onclick="popCanvas()">Populate Canvasses</button> 
<button onclick="canvasToImage()">Canvas Combine</button> 
<script> 
    var img1 = new Image(); 
     img1.src = "images/img1.jpg"; 
    var cuimg = new Image(); 
    var canvass1 = document.getElementById("card_canvas"); 
    var canvass2 = document.getElementById("card_canvas2"); 
    function popCanvas(){ 
     var ctx1 = canvass1.getContext('2d'); 
     var ctx2 = canvass2.getContext('2d'); 
     ctx1.clear() 
     ctx2.clear() 
     ctx1.drawImage(img1, 0, 0); 
     cuimg.onload = function(){ 
      ctx2.drawImage(cuimg, 7, 92); 
     } 
     cuimg.src = "images/img2.jpg"; 
    } 
    function canvasToImage(){ 
     var ctx1 = canvass1.getContext('2d'); 
     var ctx2 = canvass2.getContext('2d'); 
     ctx1.drawImage(canvass2, 0, 0); 
     var imgdata = canvass1.toDataURL('image/png'); 
     var mergeimg = document.createElement("img"); 
     mergeimg.src = imgdata; 
     document.getElementById("test").appendChild(mergeimg); 
    } 
</script> 
</body> 
</html> 
+0

你遇到了這個問題,但我需要一個單一的按鈕來實現這一點單擊。 – user123456987

+0

@ user123456987是否需要在onload函數中將圖像繪製到第二個畫布? – user2904660

+0

編號可以在畫布上繪製圖像1.即先在canvas1中繪製img1.jpg,然後在canvas1中繪製img2.jpg。這可以做到。但最終的圖像應該是img1在背景中,img2在前景重疊img1。我關心的是最終的形象,而不是畫布或畫布的數量。 – user123456987