在画布剪切路径中显示DIV

时间:2013-12-21 20:48:50

标签: html5 canvas

我有一个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>

2 个答案:

答案 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元素后面的任何内容。