Wednesday, April 24, 2013

Show Preview Only in Viewport

‹prev | My Chain | next›

There are times that I will want several ICE Code Editor instances embedded on the same page. I definitely do not want each of the instances running its visualization at the same time—that's a good way to bring some machines to their proverbial knees. What would be ideal would be for the visualization to run only when in the viewport.

To decide if an element is in the viewport, I borrow from a StackOverflow solution and use:
function isElementInViewport(el) {
  var rect = el.getBoundingClientRect();

  return (
    rect.top >= 0 &&
    rect.left >= 0 &&
    rect.bottom <= window.innerHeight &&
    rect.right <= window.innerWidth
  );
}
Since the ICE Code Editor is intended to demonstrate Three.js visualizations (and WebGL visualizations in particular), there is no need to support older browsers or any version of IE. In other words, I can make use of the getBoundlingClientRect() method without worry.

Armed with that, I can build an addEventListeners() method for the ICE.Embedded class:
Embedded.prototype.addEventListeners = function() {
  var that = this;
  function showPreview() { /* ... */ }

  function hidePreview() { /* ... */ }

  document.addEventListener('scroll', showPreview);
  document.addEventListener('load', hidePreview);
  document.addEventListener('scroll', hidePreview);
};
I am not sold on the names for showPreview() and hidePreview(). Then again, these are internal to the method so the context is set. Besides, both sound better than show-preview-if-entirely-in-viewport.

I express the showPreview() function as:
  function showPreview() {
    if (!isElementInViewport(that.editor.preview_el)) return;
    if (!that.editor.isPreviewHidden()) return;
    that.editor.updatePreview();
  }
In other words, do not show if the preview is not in the view port; do not show if the preview is already showing; otherwise go ahead and show it.

The hidePreview() function is similar:
  function hidePreview() {
    if (isElementInViewport(that.editor.preview_el)) return;
    setTimeout(function(){that.editor.hidePreview();}, 100);
  }
I find that the timeout in there is necessary to account for load times of the previewed code's scripts.

With that, I have no preview when the editor is partially outside of the viewport:



But scrolling the editor into view fires up the preview:



I may eventually switch so that the editor only needs to be 80% of the way into the screen, but this is a reasonable first take.


Day #731

No comments:

Post a Comment