首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何提高具有大量对象的画布fabric.js性能

如何提高具有大量对象的画布fabric.js性能
EN

Stack Overflow用户
提问于 2017-03-31 11:17:01
回答 1查看 4.5K关注 0票数 6

我需要一个应用程序,有大约30k对象,用户可以潘,缩放或“选择点击”任何这些对象。正在使用Fabric.js画布

我使用svg和svg-pan-缩放插件(没有画布元素)做了同样的工作,取得了更好的效果。

问题:在单击缩放、摇摄或对象时,存在明显的滞后。

  1. 删除Fabric.js会提高性能吗?
  2. 切换到WebGL会提高性能吗?

已经尝试过织物的特定选项

代码语言:javascript
运行
复制
fabric.Object.prototype.objectCaching = false;
fabric.Object.prototype.statefullCache = false;
fabric.Object.prototype.noScaleCache = true;
fabric.Object.prototype.needsItsOwnCache = false;

更新将更新小提琴

供参考:

  1. 画布-vs vs 堆栈过流
  2. 堆栈过流
EN

回答 1

Stack Overflow用户

发布于 2017-04-01 05:28:03

不要在IO事件中呈现!

虽然没有完全修正更新速度,但这个答案将是交互速度的两倍。

鼠标和与画布(和DOM)的事件交互所犯的一个常见的、几乎是标准的错误是将呈现委托给鼠标/触摸事件。这是非常糟糕的做法,因为鼠标事件以比显示器所能显示的更高的速度发射。当您的呈现时间很长时,当您排队处理鼠标事件(伪呈现事件)并对鼠标的每一个移动执行重新呈现时,情况会变得更糟。

备注阻塞代码将停止鼠标事件,但一旦引擎空闲,鼠标将再次以完全速度启动。

使用鼠标事件来获取鼠标状态。使用与显示器同步的动画循环,仅在需要时才呈现,并且有可用的时间。像轮子和鼠标运动的三角洲应该被累计记录下来。

代码语言:javascript
运行
复制
mouse.dx += event.movementX; 
mouse.dy += event.movementY; 
mouse.wheel += event.wheelDelta;

然后在主渲染循环中消耗它们..。

代码语言:javascript
运行
复制
function update(){

    // ... code to use mouse
    // consume deltas
    mouse.x = mouse.y = mouse.wheel = 0;

...this确保在呈现更新之间可能有许多鼠标事件时,鼠标状态会被准确地遵循。

例如,将事件与呈现分离。

更改您提供的小提琴代码如下,在我的机器上,它的渲染速度大约翻了一倍(这仍然非常慢)。

代码语言:javascript
运行
复制
// from just after the function applyZoom replace all the code 
var mouse = {  // holds the mouse state
    x : 0,
    y : 0,
    down : false,
    w : 0,
    delta : new fabric.Point(0,0),
}
// event just track mouse state
function zoom(e) {
    if(e != null) { e.preventDefault() }
    var evt=window.event || e;
    mouse.x = e.offsetX;
    mouse.y = e.offsetY;
    mouse.w += evt.detail? evt.detail*(-120) : evt.wheelDelta;
    return false;
}
canvas.on('mouse:up', function (e) { mouse.down = false });
canvas.on('mouse:out', function (e) { mouse.down = false });
canvas.on('mouse:down', function (e) { mouse.down = true });
canvas.on('mouse:move', function(e) {
    if (e && e.e) {
        mouse.delta.x += e.e.movementX;
        mouse.delta.y += e.e.movementY;
    }
});
// main animation loop
function update(){
    if(mouse.w !== 0){  // if the wheel has moved do zoom
        var curZoom = canvas.getZoom();
         canvas.zoomToPoint(
             { x : mouse.x, y: mouse.y }, 
             canvas.getZoom() + mouse.w / 4000
         );
         mouse.w = 0; // consume wheel delta
    }else if(mouse.down) {  // if mouse button down
         canvas.relativePan(mouse.delta);
    }
    // consume mouse delta
    mouse.delta.x = 0;
    mouse.delta.y = 0;
    requestAnimationFrame(update);
}
requestAnimationFrame(update);
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43139328

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档