【问题标题】:Is it possible to create an HTML canvas without a DOM element?是否可以创建没有 DOM 元素的 HTML 画布?
【发布时间】:2011-09-30 08:11:27
【问题描述】:

我想要一个 HTML 画布上下文,我可以在屏幕外绘制和读取(在此示例中,编写文本和读取创建的形状,但这是一个普遍的问题)。我可能还想使用画布作为屏幕外帧缓冲区。

我想我可以创建一个隐藏的 DOM 元素,但我宁愿从 JavaScript 创建它(我可能想在运行时创建和销毁一些画布)。

可能吗?

【问题讨论】:

  • 使用document.createElement 创建元素很容易。但是我不知道如果没有将canvas 添加到 DOM(不可见)中是否可以操作。
  • 在某种程度上,我想要一个上下文而不是一个画布,如果这有意义的话(它可能没有)。
  • 嗯。我认为您肯定需要 DOM 元素,但您不必将其添加到 DOM 中。让我试试……
  • 别闹了,有空我自己试试。
  • @Vadzim,请阅读这个问题,这个问题与你提出的欺骗完全相反......还有你为什么要指出这个可怕的问题?

标签: javascript html html5-canvas


【解决方案1】:

CanvasRenderingContext2D 和 WebGLRenderingContext 类都有与它们关联的画布元素作为属性canvas;而且,和正常情况一样,当您的代码在运行时不再引用它们时,上下文实例及其画布都将被垃圾回收。

你可以使用这个函数来创建一个新的上下文

function newContext({width, height}, contextType = '2d') {
    const canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;
    return canvas.getContext(contextType);
}

const ctx = newContext({width: 100, height: 100});
console.log(ctx.canvas.width == 100) // true

通过使用解引用,您可以轻松地创建一个 DOM 画布的克隆,用于帧缓冲,如下所示:

const domCanvas = document.getElementById('myCanvas');

const frameBuffer = newContext(domCanvas);
frameBuffer.drawImage(domCanvas, 0, 0);

这将创建一个与传入的画布元素具有相同宽度和高度的上下文。您可以根据需要扩展该函数。

【讨论】:

    【解决方案2】:

    它很旧,但是如何使用 toDataURL 保存一个画布并使用 drawImage 复制到另一个画布。您还可以使用 save 和 restore 来制作帧缓冲区

    function createCanvas(width, height) {
        var c = document.createElement('canvas');
        c.setAttribute('width', width);
        c.setAttribute('height', height);
        return c;
    }
    
    function canvasImg(canvas) {
        var ctx = canvas.getContext('2d');
        ctx.fillRect(0,0,canvas.width, canvas.height);
        var img = canvas.toDataURL('image/png');
    
        return img;
    }
    
    function placeImage(canvas, img) {
        var ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0,0);
    }
    
    window.onload = function(){
        var canvas = createCanvas(400, 400);
        var hiddenCanvas = createCanvas(400,400);
        var i = canvasImg(hiddenCanvas);
        var img = new Image();
        img.src = i;
        placeImage(canvas, img);
        document.body.appendChild(canvas);
    }
    

    【讨论】:

    • 这个比较简单:c.width = width; c.height = height;
    【解决方案3】:

    显然有一个名为OffscreenCanvas 的新东西是专门为这个用例设计的。另一个好处是它也适用于 Web Workers。

    您可以在此处阅读规格:https://html.spec.whatwg.org/multipage/canvas.html#the-offscreencanvas-interface

    并在此处查看示例:https://developer.mozilla.org/en-US/docs/Web/API/OffscreenCanvas

    目前它仅被 Chrome 完全支持,并且在 Firefox 和 Opera 中可用,但您可以随时在此处查看支持的浏览器的最新信息:https://caniuse.com/#feat=offscreencanvas

    ps.:Google 也有专门的指南解释它在 Web Workers 中的使用:https://developers.google.com/web/updates/2018/08/offscreen-canvas

    【讨论】:

    • 谢谢,我去看看。让我们希望它超越 Chrome。
    【解决方案4】:

    您可以使用document.createElement 创建一个新的canvas 元素:

    var canvas = document.createElement('canvas');
    

    然后从中获取上下文。只要确保设置了widthheight。您不必将画布添加到树中即可使其工作:

    DEMO

    但您肯定必须创建该节点。不过,您可以为此创建一个函数:

    function createContext(width, height) {
        var canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        return canvas.getContext("2d");
    }
    

    但这就是我的能力结束的地方...我不知道您是否可以以某种方式将上下文转移到另一个上下文或画布...

    【讨论】:

    • 这和我想做的很相似。这是 7.99 的问题:哪个会更快:1)多次执行此操作(例如,与 mousemove 事件触发一样频繁),或 2)创建一次屏幕外画布并将其存储为全局变量(仍未添加到 DOM) ?
    • 我没有证据,但从表面上看,存储一个创建的画布肯定比每帧创建一个新的画布便宜很多
    猜你喜欢
    • 2010-09-15
    • 1970-01-01
    • 1970-01-01
    • 2019-06-09
    • 2016-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多