Improve Performance of Sidebar resize by implementing requestAnimationFrame #942

Merged
merged 16 commits into from Jun 13, 2012
@@ -23,7 +23,7 @@
/*jslint vars: true, plusplus: true, devel: true, nomen: true, indent: 4, maxerr: 50 */
-/*global define, $, document */
+/*global define, $, document, window */
define(function (require, exports, module) {
'use strict';
@@ -75,7 +75,7 @@ define(function (require, exports, module) {
if (typeof displayTriangle === "boolean") {
var display = (displayTriangle) ? "block" : "none";
- $sidebar.find(".triangle-visible").css("display", display);
+ $sidebar.find(".sidebar-selection-triangle").css("display", display);
}
if (isSidebarClosed) {
@@ -89,8 +89,6 @@ define(function (require, exports, module) {
// event that we can just call from anywhere instead of hard-coding it.
// waiting on a ProjectManager refactor to add that.
$sidebar.find(".sidebar-selection").width(width);
- $projectFilesContainer.triggerHandler("scroll");
- $openFilesContainer.triggerHandler("scroll");
@jasonsanjose
jasonsanjose May 26, 2012 Member

Do you think it's possible to change the shadow and triangle handlers to also use requestAnimationFrame?

@ryanstewart
ryanstewart May 26, 2012 Member

I took a look at it but I'm not sure how to differentiate that the scroll event is happening during a drag as opposed to a real scroll event. But the two events look like they have a totally different structure (one, I'm assuming being fired programmatically and the other from a real scroll event). But even if I can differentiate between those two events I'm not sure how to make sure it's a drag event and not another event that's calling .triggerHandler("scroll");

I'll do some more research.

if (width > 10) {
prefs.setValue("sidebarWidth", width);
@@ -101,7 +99,6 @@ define(function (require, exports, module) {
var text = (isSidebarClosed) ? Strings.CMD_SHOW_SIDEBAR : Strings.CMD_HIDE_SIDEBAR;
CommandManager.get(Commands.VIEW_HIDE_SIDEBAR).setName(text);
}
-
EditorManager.resizeEditor();
}
@@ -119,7 +116,6 @@ define(function (require, exports, module) {
var prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs);
prefs.setValue("sidebarClosed", isSidebarClosed);
-
_setWidth(width, true, !isSidebarClosed);
}
@@ -132,7 +128,9 @@ define(function (require, exports, module) {
$body = $(document.body),
prefs = PreferencesManager.getPreferenceStorage(PREFERENCES_CLIENT_ID, defaultPrefs),
sidebarWidth = prefs.getValue("sidebarWidth"),
- startingSidebarPosition = sidebarWidth;
+ startingSidebarPosition = sidebarWidth,
+ animationRequest = null,
+ isMouseDown = false;
$sidebarResizer.css("left", sidebarWidth - 1);
@@ -143,59 +141,85 @@ define(function (require, exports, module) {
}
$sidebarResizer.on("dblclick", function () {
- if ($sidebar.width() === 1) {
- // mousedown is fired first. Sidebar is already toggeled open to 1px.
+ if ($sidebar.width() < 10) {
+ //mousedown is fired first. Sidebar is already toggeled open to at least 10px.
_setWidth(null, true, true);
+ $projectFilesContainer.triggerHandler("scroll");
+ $openFilesContainer.triggerHandler("scroll");
} else {
- toggleSidebar();
+ toggleSidebar(sidebarWidth);
}
});
$sidebarResizer.on("mousedown.sidebar", function (e) {
- var startX = e.clientX;
+ var startX = e.clientX,
+ newWidth = Math.max(e.clientX, 0),
+ doResize = true;
+
+ isMouseDown = true;
+
+ // take away the shadows (for performance reasons during sidebarmovement)
+ $sidebar.find(".scroller-shadow").css("display", "none");
+
$body.toggleClass("resizing");
+
// check to see if we're currently in hidden mode
if (isSidebarClosed) {
toggleSidebar(1);
}
+
- $mainView.on("mousemove.sidebar", function (e) {
- var doResize = true,
- newWidth = Math.max(e.clientX, 0);
-
+ animationRequest = window.webkitRequestAnimationFrame(function doRedraw() {
+ // only run this if the mouse is down so we don't constantly loop even
+ // after we're done resizing.
+ if (!isMouseDown) {
+ return;
+ }
+
// if we've gone below 10 pixels on a mouse move, and the
// sidebar is shrinking, hide the sidebar automatically an
// unbind the mouse event.
if ((startX > 10) && (newWidth < 10)) {
toggleSidebar(startingSidebarPosition);
$mainView.off("mousemove.sidebar");
+
+ // turn off the mouseup event so that it doesn't fire twice and retoggle the
+ // resizing class
+ $mainView.off("mouseup.sidebar");
$body.toggleClass("resizing");
doResize = false;
- } else if (startX < 10) {
- // reset startX if we're going from a snapped closed position to open
- startX = startingSidebarPosition;
+ startX = 0;
+
+ // force isMouseDown so that we don't keep calling requestAnimationFrame
+ // this keeps the sidebar from stuttering
+ isMouseDown = false;
+
}
if (doResize) {
- // if we've moving past 10 pixels, make the triangle visible again
- // and register that the sidebar is no longer snapped closed.
- var forceTriangle = null;
-
- if (newWidth > 10) {
- forceTriangle = true;
- }
-
- _setWidth(newWidth, false, forceTriangle);
+ // for right now, displayTriangle is always going to be false for _setWidth
+ // because we want to hide it when we move, and _setWidth only gets called
+ // on mousemove now.
+ _setWidth(newWidth, false, false);
}
- if (newWidth === 0) {
- $mainView.off("mousemove.sidebar");
- $("body").toggleClass("resizing");
- }
-
+ animationRequest = window.webkitRequestAnimationFrame(doRedraw);
+ });
+
+ $mainView.on("mousemove.sidebar", function (e) {
+ newWidth = Math.max(e.clientX, 0);
+
e.preventDefault();
});
$mainView.one("mouseup.sidebar", function (e) {
+ isMouseDown = false;
+
+ // replace shadows and triangle
+ $sidebar.find(".sidebar-selection-triangle").css("display", "block");
+ $sidebar.find(".scroller-shadow").css("display", "block");
+
+ $projectFilesContainer.triggerHandler("scroll");
+ $openFilesContainer.triggerHandler("scroll");
$mainView.off("mousemove.sidebar");
$body.toggleClass("resizing");
startingSidebarPosition = $sidebar.width();