我有一个DIV容器,我想放在Canvas元素中,如何将#canvasContents的剪切路径设置为Canvas形状?
<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 :(得分: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>';
然后将其转换为blob和url:
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 :(得分: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
,它将显示在canvas元素后面的任何内容。