Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/445.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 关于动力层的问题_Javascript_Performance_Canvas_Kineticjs - Fatal编程技术网

Javascript 关于动力层的问题

Javascript 关于动力层的问题,javascript,performance,canvas,kineticjs,Javascript,Performance,Canvas,Kineticjs,动力学层是如何合成的?如中所示,什么是实施 起初,我认为每一层都是自己的画布(文档暗示了这一点),但除非这些是屏幕外的画布元素,否则情况似乎并非如此。如果他们不在屏幕上,我仍然会得到违反直觉的性能点击 我有一个使用动能的组件,它有3层。称它们为backgroundLayer、activeLayer和selectionLayer。第一个在加载新文档时呈现一次;第二个很少更新,但有可能需要移动或添加/删除的元素;最后一个元素只有一个非常小的元素 让我惊讶的是,如果我有一个20fps的循环渲染,在循环

动力学层是如何合成的?如中所示,什么是实施

起初,我认为每一层都是自己的画布(文档暗示了这一点),但除非这些是屏幕外的画布元素,否则情况似乎并非如此。如果他们不在屏幕上,我仍然会得到违反直觉的性能点击

我有一个使用动能的组件,它有3层。称它们为backgroundLayer、activeLayer和selectionLayer。第一个在加载新文档时呈现一次;第二个很少更新,但有可能需要移动或添加/删除的元素;最后一个元素只有一个非常小的元素

让我惊讶的是,如果我有一个20fps的循环渲染,在循环渲染中,我显式地检查每个层是否有我自己的“脏标志”,并且仅在脏的情况下渲染该层,即使我只更新selectionLayer,即使该层的clearBeforeDraw设置为false,帧速率也会爬行。我可以确认此属性阻止清除,因为移动的选择会留下像素的痕迹

阶段通常类似于600x2000,但selectionLayer中的单个元素是一个大约为20x100的矩形

我怀疑正在发生的是,每一层都被渲染为屏幕外画布,但随后这些画布被合成到一个可见的画布中。可能我的selectionLayer在屏幕外更新很快(我可以添加清除旧的rect以保持快速),但在合成层时,它会有效地闪烁600x2000个透明像素(甚至更糟,导致未更新的两个层也合成在一起)

这对正在发生的事情准确吗?如果是这样的话,是否有其他方法可以保持渲染速度?我正在考虑使用一个单独的Kinetic.Stage(也就是canvas),但这是一个解决方案,它开始失去层的一些明显好处。如果层仅用于组织代码,但具有这种性能含义,我认为应该对此进行记录。每层都有屏幕上的画布元素也很好,尽管我意识到这将是对库的重大更改。但如果不是这样的话,看起来我需要在DOM/CSS级别上做额外的工作来协调我的层并获得我需要的性能目标

重新编辑以包含示例代码,并将问题归结为其本质:

在组件的init()中:

在组件的render()中:

请注意,只有PlayHeadler被设置为dirty,并且我已经确认只有该层被渲染。在Chrome的profiler flame图表中,我可以看到对render()的每次调用需要约100ms,其中约99ms将Kinetic.Context.drawImage()调用[context2d.]drawImage(),作为堆栈上的最终调用

那个电话在干什么?为什么?


我现在不关心我可能很想做的各种其他优化,包括使用单独的画布或将我的monster UI组件分割成更便于缓存的画布元素。我试图理解这个问题,因为它会影响我下一步要优化的内容。也就是说,我们非常感谢所有其他优化建议

关于KineticJS层

每个KineticJS层实际上是2张画布。一个画布用于可见显示,另一个画布用于屏幕外工作,如点击测试和拖动操作。所以你的3层实际上是3套画布(总共6张)

背景层

如果你的背景层从未改变,告诉它不要听事件。事件处理系统使用大量资源,因此这将为其他任务释放cpu时间。您甚至可以考虑将背景放在使用动态容器的CSS定位的图像元素上。这样KineticJS就不必为其分配任何资源

backgroundLayer.listening(false);
活动层

如果此层上的所有添加/删除/移动都是通过编程完成的,并且您不需要用户单击/拖动活动层上的任何元素,那么也可以在此层上设置监听

activeLayer.listening(false);
如果仍然需要侦听活动层事件,但不需要命中测试,请使用drawScene而不是draw。drawScene命令仅绘制可见画布,而不绘制屏幕外的命中画布

activeLayer.drawScene();
令人惊讶的是,您可能会发现让KineticJS清除/重画整个activeLayer比使用clearBeforeDraw进行微观管理更快。这是因为GPU可以更快地清除整个画布,而不是清除画布的一部分。画布有一个内部像素颜色数组,该数组很快被零填充以擦除整个画布。若要清除画布的一部分,浏览器必须计算起始像素位置并保持跟踪,因为零仅填充像素阵列的一部分

更新活动层上的多个节点时,请使用batchDraw(),它使用window.requestAnimationFrame“幕后”。R.A.F.将自身与显示硬件集成,因此降低了绘图被显示刷新中断的可能性

activeLayer.batchDraw();
选择层

如果选择层上的节点未旋转或缩放,则可以禁用此节点的变换,以大大提高性能

myNode.transformsEnabled(“none”);

如果选择层上的节点不是图像,请考虑将其缓存到图像中。图像大部分可以通过GPU进行点显,而重新绘制形状也需要CPU付出相当大的努力

myNode.cache({…});
其他性能材料

…而且,n-e-v-e-r使用阴影。阴影需要KineticJS和本机html画布进行特别昂贵的处理。如果需要阴影节点,请执行以下操作:

  • 绘制节点
  • 应用阴影
  • 将节点缓存为图像(包括阴影)
如果你是
activeLayer.batchDraw();
myNode.transformsEnabled(“none”);
myNode.cache({…});