HTML5混合模式 - 绘图程序中的图层

时间:2015-08-04 13:20:56

标签: javascript html5 css3 canvas

我正在创建html5绘画应用程序,我目前正致力于混合图层。我想知道哪种方法是最好的(最快和gimp / photoshop)在这样的程序中构建。我的图层(画布)堆叠在一起。

  1. 通过CSS3属性更改混合模式(可能非常快 - 直接在图形卡上混合)
  2. 隐藏画布(图层)和一个画布以向用户显示展平图像。所以我们借鉴了这些隐藏的画布,并且有一些机制可以将每个隐藏的画布并将其绘制到用户可查看的画布(可能更慢,但每个context.drawImage(...)都在显卡上优化和计算)
  3. 隐藏的画布(图层)是真正的虚拟。根本没有隐藏的画布元素。相反,在内存中有一些模仿画布的结构。这些结构只保存在此虚拟层上执行的用户操作。然后,当需要重新绘制时,通过从每个虚拟层中获取每个操作并绘制它(真实绘制)来重建用户画布。操作必须正确排序是这样的虚拟层结构(这可能比第二种方法慢(但可能比第二种方法更快)(我们不浪费时间在层上绘制任何东西,只是存储选项我们将如何在真实层上绘制)?)
  4. 通过WebGL进行混合(可能很快)
  5. 手动计算每个像素并向用户显示分数(超慢?)
  6. 我正在使用第二种方法,但我不确定它是最好的(特别是对于更多层)。我想知道你知道任何其他方法,也许你会建议什么是更好的实现混合操作,使其像Gimp / Adob​​e Photoshop一样工作

1 个答案:

答案 0 :(得分:0)

我实现这一点的方法是拥有多个画布,每个画布都存储着自己的混合模式。但它只是虚拟画布(不适合用户使用)。然后每秒33次计时器(由RequestAnimationFrame制作)抓住所有这些画布,展平它们并将其绘制到视口。对于每个图层,我在视口画布上执行混合模式更改。它工作得很完美,因为drawImage(...)是在GPU上计算的,而且速度非常快。

我认为代码很容易理解并适用于自己的解决方案:

   Process(lm: dl.LayerManager) {
        var canvasViewPort = lm.GetWorkspaceViewPort();
        var virtualLayers = lm.GetAllNonTemporary();

        canvasViewPort.Save();
        canvasViewPort.Clear();
        canvasViewPort.SetBlendMode(virtualLayers[0].GetBlendMode());
        canvasViewPort.ApplyBlendMode();
        canvasViewPort.DrawImage(virtualLayers[0], 0, 0, canvasViewPort.Width(), canvasViewPort.Height(), 0, 0, canvasViewPort.Width(), canvasViewPort.Height());
        for (var i = 1; i < virtualLayers.length; ++i) {
            var layer = virtualLayers[i];
            var shift = other.GetShift();
            canvasViewPort.SetBlendMode(virtualLayers[i].GetBlendMode());
            canvasViewPort.ApplyBlendMode();
            canvasViewPort.DrawImage(layer, 0, 0, layer.Width(), layer.Height(), shift.x, shift.y, layer.Width(), layer.Height());
        }
        canvasViewPort.Restore();
    }

不要害怕这段代码。它保持底层画布,纯CanvasRenderingContext2D。

我将执行此类优化:在任何虚拟画布上发生更改之前,我不会重绘canvasViewPort。

我将执行下一个优化:获取所选图层,在当前图层之前和之后全部缓存。

所以它看起来像:

CurrentLayer:3(可能受某些工具影响)

[1]:L1
[2]:L2
[3]:L3
[4]:L4
[5]:L5
[6]:L6

使用适当的混合模式[1,2]到tmp1和[4,5,6]到tmp2绘制临时。 当第三层发生变化时,我只需重新绘制tmp1 + [3] + tmp2。 所以它只是2次迭代。超快。