在画布剪切路径中显示DIV [英] Displaying DIV inside a Canvas clipping path

查看:88
本文介绍了在画布剪切路径中显示DIV的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个DIV容器,我想放置在Canvas元素内,如何设置#canvasContents的剪切路径到Canvas形状?

 < canvas id =myCanvaswidth =500height =400>< / canvas> 

< div id =canvasContentswidth =500height =400>画布内容< / 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>


解决方案

canvas元素中的内容只会在浏览器不支持canvas的情况下显示。



您可以尝试使用SVG通过包装SVG的内联代码来放置div,但是有一些与外部内容相关的限制。



您需要构建一个内联SVG,如下所示:

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

我们的HTMLgoesHere +

'< / foreignObject>< / svg>';

然后将其转换为blob和url:

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

现在您可以将其设置为图片源,加载后再绘制到画布。 p>

为了简单起见,我做了这个功能做所有的辛勤工作(详情请看上面的链接)。文本可以是任何HTML,包括您需要包装的div。只记得它不能包含指向外部内容(图片,CSS,字体等)的链接:

  / ** 
*画布扩展:drawHTMLText(txt,options)
*由Ken Fyrstenberg,Epistemex
* http://epistemex.com/
*
*使用:
* myContext.drawHTMLText(txt [,options]);
*
* var options = {x:startPosition,
* y:startPosition,
* width:maxWidth,
* height:maxHeight,
* callback:myFunction,
* callbackError:myErrorFunction}
*
*每个单独的选项在自身中是可选的。成功时的回调
*包含一个引用result的对象和
* originalText。错误回调与错误对象一起提供。
*
*许可证:MIT
* /
CanvasRenderingContext2D.prototype.drawHTMLText = function(txt,options){

///确保我们有一个对象,如果没有提供
options = options || {};

var ctx = this,

/// build inline SVG
iSVG =

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

'height = '+
(options.height?options.height:ctx.canvas.height)+
'>< foreignObject width =100%height =100%& b
$ b'< div xmlns =http://www.w3.org/1999/xhtmlstyle =font:'+
ctx.font +'; color:'+ ctx .fillStyle +'>'+

txt +

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

///创建内嵌SVG的Blob
svg = new Blob([iSVG],{type:image / svg + xml; charset = utf-8}),

///创建URL(句柄前缀版本)
domURL = self.URL || self.webkitURL || self,
url = domURL.createObjectURL(svg),

/// create Image
img = new Image;

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

///绘制SVG到画布
ctx.drawImage ,
(options.x?options.x:0),
(options.y?options.y:0));

domURL.revokeObjectURL(url);

///调用回调(如果提供)
if(typeof options.callback ==='function')
options.callback({result:img,
originalText : 文本});
};

///处理潜在错误
img.onerror = function(e){
if(typeof options.callbackError ==='function'){
options .callbackError(e);
} else {
console.log(e);
}
}

img.src = url;
}

如果你需要剪辑,只需使用 context.clip()


I have a DIV container that I want to place inside a Canvas element, how do I set the clipping path of the #canvasContents to the Canvas shape?

<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>

解决方案

You can't place anything inside a canvas element. The content inside a canvas element will only show if canvas is not supported in a browser. In other cases it's ignored.

You can try to use SVG to place a div inside by wrapping the code inlined for the SVG but there are some restrictions related to external content.

You need to build an inline SVG like this:

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

   ourHTMLgoesHere +

   '</foreignObject></svg>';

Then convert it to blob and url:

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

Now you can set this as an image source, load it and then draw it to canvas.

For simplicity I made this function to do all the hard work (please see link above for details). Text can be any HTML including the div you need to wrap inside. Just remember it cannot contain links to external content (images, css, fonts etc.):

/**
 *    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;
}

If you need clipping just add that to the canvas itself using context.clip() after defining a path.

这篇关于在画布剪切路径中显示DIV的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆