要在很长的区域(画布)上渲染多个对象?
我需要显示一个非常长的区域(没有定义的长度),其中包含许多多边形(简单的形状 - 圆形、正方形、一些文本)。显然我一次只需要可见的小片段。主要问题是高效滚动和处理鼠标事件。我用 GWT 编写。到目前为止我考虑的事情:
1)画布。创建一个具有可见区域大小的画布。创建大于可见区域的缓冲区画布。渲染到缓冲区(仅更改 - 如果可见区域中发生某些更改或滚动期间右/左的新部分)。当需要时,将缓冲区的适当部分渲染到可见画布。这似乎工作得足够快。但!我必须实现这种智能缓冲,决定哪些部分需要重新渲染,哪些部分不需要。我需要记住所有对象来检测鼠标点击和鼠标悬停(它应该是一些不错的结构,例如区间树或线段树,因为鼠标悬停检查非常频繁 - 但这已经在浏览器中实现了,听起来像是重新发明轮子) - 这是大量的工作! 也许有什么准备好了?
2) html (div/images) - 因此,我们的想法是用 div 和图像渲染所有元素(图像可以首先在画布上生成,但这并不重要)。将它们绝对放置在长 div 上,并使用浏览器滚动来滚动 div。一直有效,直到您到达这个长 div 的末尾,并且您需要重新定位所有内容,以便有更多的滚动空间(这将冻结滚动一段时间)。因此,也许可以同时在第二个 div 中渲染,然后切换它们。它可能会起作用,但这听起来像是一个 hack,并且一次可见多个对象可能会出现严重问题。另外还有在浏览器中实现的鼠标事件。
3)SVG - 我没有尝试过,但我想我会遇到与 html/div 相同的性能问题(当滚动到右/左时)
有什么想法吗?哪种方法最好?有更好的吗? WebGL(它不能在 IE 中工作,并且移植到 IE 会很困难)。我应该如何实施这个?
I need to display a very long area (without defined length) with many polygons (simple shapes - circles, squares, some text). Obviously I need only small fragment visible at a time. Main problems are efficient scrolling and handing mouse events. I write in GWT. Things i considered so far:
1) canvas. create a canvas with the size of visible area. Create buffer canvas larger then visible area. Render to the buffer (only changes - if something is changed in the visible area or new parts to the right/left during scrolling). And when required, render proper part of the buffer to visible canvas. This seems to work fast enough. But! I have to implement this smart buffering, decide which part needs to be rerendered and which not. And I need to remember all object to detect mouse clicks and mouseovers (and it should be some nice structure like interval tree or segment tree, as mouseover checks are very frequent - but this is already implemented in the browser, sounds like reinventing the wheel) - this is A LOT OF WORK!
Maybe there is something ready?
2) html (divs/images) - so, the idea is to render all elements with divs and images (images can be generated on canvas first, doesn't metter). Position them absolutely on a long div and use browser scrolling to scroll the div. Works until you reach the end of this long div and you need to reposition everything so there is more space to scroll (and this will freeze scrolling for some time). So maybe it would be possible to render in a second div in the meanwhile and then switch them.. It might work, but this sounds like a hack and it will probably have serious problems with multiple objects visible at a time. Plus for mouse events implemented in the browser.
3) SVG - I haven't tried, but I think I will run into the same performance problems as with html/divs (when scrolling to right/left)
Any ideas? Which approach is the best? Is there anything better? WebGL (it won't work in IE and porting to IE would be hard prob). How should I implement this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您似乎了解优点/缺点。 Canvas 速度更快,但级别较低,因此编码更困难。 DOM 速度较慢,但由于其事件处理和对象访问而更易于编码。如果 DOM 太慢,你就必须求助于 canvas。
一种可能的折衷方案是渲染整个画布并使用
overflow:hidden
对其进行剪辑。这就是我在正在处理的波形显示上所做的。对于形状来说,SVG 应该比 DOM 更容易。由于 SVG 不完全跨浏览器,因此您应该使用类似 http://raphaeljs.com/ 的内容
You seem to understand the pros/cons. Canvas is faster, but it's lower level, so it's harder to code. DOM is slower but easier to code because of its event handling and object access. If DOM is too slow, you have to resort to canvas.
One possible compromise is to render the full canvas and clip it using
overflow:hidden
. That's what I did on a waveform display I am working on.SVG should be easier than the DOM for shapes. Since SVG is not completely cross browser, you should use something like http://raphaeljs.com/
我会选择画布,因为它相对较快。
至于离屏定位、鼠标事件和重新渲染——这一切都可以通过使用画布库来处理,例如 Fabric.js。查看演示。
事件检查器演示 & 使用事件教程可能会很有用。
默认情况下会处理离屏(非)渲染。只需将对象放置在屏幕外坐标处,它们就不会可见。
I would go with canvas as it's relatively fast.
As far as off-screen positioning, mouse events, and re-rendering — it could be all taken care of by using canvas library like Fabric.js. Take a look at the demos.
Event inspector demo & working with events tutorial might come in useful.
Off-screen (not) rendering is taken care of by default. Just position objects at off-screen coordinates and they won't be visible.