Raphael.js 导致 "Forced synchronous layout" 瓶颈

Raphael.js causing "Forced synchronous layout" bottleneck

我在 chrome 中监控了我网站的页面加载时间(使用时间轴),并收到数百条警告,指出所有 Raphael.js 调用的 "Forced synchronous layout is a possible performance bottleneck":

我不知道如何解决这个问题:/

关于去哪里看有什么想法吗?

以下是我通常在页面上创建文本的方式:

currentPaper.text(width,height,"text")
            .attr({opacity:.8, fill: "#333", 'font-size':10})
            .id = "someId";

//Or, to be exact:

currentPaper.text(x_pos+(width/2), 
                  y_pos-height/8, 
                  lopaLayoutArray.x[s].y1[r].y2[x])
            .attr({opacity:.8, fill: "#333", 'font-size':(10*size)})
            .id = seatName+"-textLabel";

谢谢!

问题:

这个问题叫做“Layout Thrashing”,它的发生是因为浏览器试图在每次 Raphael 绘图后立即刷新/重绘。

例如,这会导致布局抖动:

var a = document.getElementById('element-a');
var b = document.getElementById('element-b');

a.clientWidth = 100;
var aWidth = a.clientWidth;

b.clientWidth = 200;
var bWidth = b.clientWidth;

"In this simple example, the browser will update the whole layout twice. This is because after setting the first element's width, you are asking to retrieve an element's width. When retrieving the css property, the browser know's it needs updated data, so it then goes and updates the whole DOM tree in memory. Only then, it will continue to the next line, which will soon after cause another update because of the same reasons."

这可以简单地通过更改代码的顺序来解决,如下所示:

var a = document.getElementById('element-a');
var b = document.getElementById('element-b');

a.clientWidth = 100;
b.clientWidth = 200;

var aWidth = a.clientWidth;
var bWidth = b.clientWidth;

"Now, the browser will update both properties one after the other without updating the tree."

来源:

https://blog.idrsolutions.com/2014/08/beware-javascript-layout-thrashing/

http://www.codeproject.com/Articles/758790/Debugging-and-solving-the-Forced-Synchronous-Layou

http://www.stubbornella.org/content/2009/03/27/reflows-repaints-css-performance-making-your-javascript-slow/

https://dev.opera.com/articles/efficient-javascript/?page=3#reflow

灵魂:

解决这个问题的一种方法(一种非常快速和肮脏的方法)是隐藏()你正在绘制的div,然后,当你完成时,显示()它。我在拉斐尔的作品中遇到过失败的结果,而且这种方式一直很奇怪。 但是更快...

"When an element has its display style set to none, it will not need to repaint, even if its contents are changed, since it is not being displayed. This can be used as an advantage. If several changes need to be made to an element or its contents, and it is not possible to combine these changes into a single repaint, the element can be set to display:none, the changes can be made, then the element can be set back to its normal display."

结果如下:

这种方式对我有用!