2013-12-21 28 views
0

我有一個DIV容器,我想放置在Canvas元素中,如何將#canvasContents的剪切路徑設置爲Canvas形狀?在畫布剪輯路徑中顯示DIV

<canvas id="myCanvas" width="500" height="400"></canvas> 

<div id="canvasContents" width="500" height="400">canvas contents</div> 

<script> 
var canvas = document.getElementById('myCanvas'); 
var context = canvas.getContext('2d'); 
var x = 120, y = 70; 
context.beginPath(); 
context.moveTo(x, y); 
context.bezierCurveTo(x, y, x + 6, y - 82, x + 98, y - 25); 
context.bezierCurveTo(x + 210, y - 5, x + 325, y + 2, x + 283, y + 78); 
context.bezierCurveTo(x + 244, y + 173, x + 237, y + 270, x + 138, y + 235); 
context.bezierCurveTo(x - 29, y + 185, x - 145, y + 154, x - 65, y + 99); 
context.closePath(); 
context.lineWidth = 1; 
context.fillStyle = '#FFF'; 
context.fill(); 
context.strokeStyle = '#000'; 
context.stroke(); 
</script> 
+0

您可以看到放置在canvas元素內的元素的唯一方式是當瀏覽器不支持canvas元素時。 – Loktar

回答

2

你不能把畫布元素內任何東西。只有在瀏覽器中不支持canvas時,canvas元素中的內容纔會顯示。在其他情況下,它被忽略。

您可以嘗試使用SVG通過爲SVG內聯內聯代碼來放置div,但是存在與外部內容相關的一些限制。

你需要建立一個內聯SVG是這樣的:

var inlineSVG = 
    '<svg xmlns="http://www.w3.org/2000/svg" width="50" height="50">' + 
    '<foreignObject width="100%" height="100%">' + 

    ourHTMLgoesHere + 

    '</foreignObject></svg>'; 

然後將其轉換成團塊和網址:

var svg = new Blob([inlineSVG], {type:"image/svg+xml;charset=utf-8"}); 
var url = URL.createObjectURL(svg); 

現在你可以設置爲圖像源,加載它,然後將其繪製到畫布上。

爲了簡單起見,我讓這個功能做了所有的辛苦工作(請參閱上面的鏈接瞭解詳情)。文本可以是任何HTML,包括您需要包裝的div。只要記住它不能包含鏈接到外部的內容(圖片,CSS,字體等):

/** 
* Canvas extension: drawHTMLText(txt, options) 
* By Ken Fyrstenberg, Epistemex 
* http://epistemex.com/ 
* 
* USAGE: 
*  myContext.drawHTMLText(txt [, options]); 
* 
* var options = {x: startPosition, 
*     y: startPosition, 
*     width: maxWidth, 
*     height: maxHeight, 
*     callback: myFunction, 
*     callbackError: myErrorFunction} 
* 
* Each individual option is optional in themself. The callback 
* on success contains an object with reference to result and 
* originalText. Error callback is provided with the error object. 
* 
* License: MIT 
*/ 
CanvasRenderingContext2D.prototype.drawHTMLText = function(txt, options) { 

    /// make sure we have an object if none was provided 
    options = options || {}; 

    var ctx = this, 

     /// build inline SVG 
     iSVG = 

     '<svg xmlns="http://www.w3.org/2000/svg" width="' + 
     (options.width ? options.width : ctx.canvas.width) + 

     '" height="' + 
     (options.height ? options.height : ctx.canvas.height) + 
     '"><foreignObject width="100%" height="100%">' + 

     '<div xmlns="http://www.w3.org/1999/xhtml" style="font:' + 
     ctx.font + ';color:' + ctx.fillStyle + '">' + 

     txt + 

     "</div></foreignObject></svg>", 

     /// create Blob of inlined SVG 
     svg = new Blob([iSVG],{type:"image/svg+xml;charset=utf-8"}), 

     /// create URL (handle prefixed version) 
     domURL = self.URL || self.webkitURL || self, 
     url = domURL.createObjectURL(svg), 

     /// create Image 
     img = new Image; 

    /// handle image loading 
    img.onload = function() { 

     /// draw SVG to canvas 
     ctx.drawImage(img, 
         (options.x ? options.x : 0), 
         (options.y ? options.y : 0)); 

     domURL.revokeObjectURL(url); 

     /// invoke callback if provided 
     if (typeof options.callback === 'function') 
      options.callback({result: img, 
           originalText: txt}); 
    }; 

    /// handle potential errors 
    img.onerror = function(e) { 
     if (typeof options.callbackError === 'function') { 
      options.callbackError(e); 
     } else { 
      console.log(e); 
     } 
    } 

    img.src = url; 
} 

如果你需要裁剪只想補充一點,給自己定義的路徑後使用context.clip()畫布。

+1

+1不錯的答案,絕對是開箱即用的想法:) – Loktar

+1

@Loktar是的,這是非常漂亮的svg可以在畫布上做什麼。我最初編寫這個函數只是(自動)將文本包裝在畫布上,但它比那更強大。 – K3N

0

Live Demo

下面是完成它的一種方式,首先,我把canvas元素在DIV只是使用絕對定位,像這樣

canvas { 
    position:absolute 
} 
#canvasContents { 
    position:absolute; 
    background:blue; 
    width:500px; 
    height:400px; 
    line-height:400px; 
    text-align:center 
} 

然後我填的是帆布和使用裁剪到顯示效果。

var canvas = document.getElementById('myCanvas'); 
var context = canvas.getContext('2d'); 
var x = 120, 
    y = 70; 
context.fillRect(0, 0, canvas.width, canvas.height); 

context.save(); 
context.beginPath(); 
context.moveTo(x, y); 
context.bezierCurveTo(x, y, x + 6, y - 82, x + 98, y - 25); 
context.bezierCurveTo(x + 210, y - 5, x + 325, y + 2, x + 283, y + 78); 
context.bezierCurveTo(x + 244, y + 173, x + 237, y + 270, x + 138, y + 235); 
context.bezierCurveTo(x - 29, y + 185, x - 145, y + 154, x - 65, y + 99); 
context.closePath(); 
context.clip(); 
context.clearRect(0, 0, canvas.width, canvas.height); 
ctx.restore(); 

剪輯的關鍵是保存上下文,繪製您的路徑,然後調用剪輯。之後,您可以進行填充,或者在此示例中爲clearRect,它將顯示位於畫布元素後面的任何內容。

+0

DIV容器需要進入畫布內部,而不是在它後面。 – PMG

+0

@PaulGeronca元素不能放置在畫布元素內部並顯示。如果瀏覽器不支持canvas(IE8及以下版本),您將看到放置在canvas元素中的元素的唯一方法。您最好的選擇是將畫布元素放在您想展示的任何位置。 – Loktar