最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Detect browser graphics performance? - Stack Overflow

programmeradmin2浏览0评论

I have a graphically intensive website. It has all kinds of CSS3 animations running over a blurred video background. It looks great on my desktop and on GPU-enabled MacBook Pros, but it runs like junk on my laptop and MacBook Air.

So basically, I want to know if there is a way to detect Browser graphics performance with Javascript (or anything) and then only apply the CSS animations if the performance reaches a threshold. The site has a loading screen, so I have some time to test for performance.

I know I can detect WebGL with Modernizr, but unfortunately even my laptop tests positive for WebGL even though performance is very poor so I need an alternative.

Thanks

I have a graphically intensive website. It has all kinds of CSS3 animations running over a blurred video background. It looks great on my desktop and on GPU-enabled MacBook Pros, but it runs like junk on my laptop and MacBook Air.

So basically, I want to know if there is a way to detect Browser graphics performance with Javascript (or anything) and then only apply the CSS animations if the performance reaches a threshold. The site has a loading screen, so I have some time to test for performance.

I know I can detect WebGL with Modernizr, but unfortunately even my laptop tests positive for WebGL even though performance is very poor so I need an alternative.

Thanks

Share Improve this question asked Feb 25, 2015 at 21:03 mike_freeganmike_freegan 3681 gold badge6 silver badges22 bronze badges 2
  • 1 Look at using window.requestAnimationFrame with your animations. This is a recursive method that fires only once every time the puter's screen refreshes. – Blazemonger Commented Feb 25, 2015 at 21:06
  • From Mozilla MDN (developer.mozilla/en-US/docs/Web/API/window/…) "The Window.requestAnimationFrame() method tells the browser that you wish to perform an animation and requests that the browser call a specified function to update an animation before the next repaint". Just didn't feel that "fires only once every time the puter's screen refreshes" was a really good explanation. – Johan Sundén Commented Feb 25, 2015 at 21:25
Add a ment  | 

2 Answers 2

Reset to default 3

This is an old question, but I'll give my 2 cents since I dealt with something similar recently.

I did something similar using GreenSock to measure frame drops. But I'm sure it's very similar if you want to implement it with requestAnimationFrame.

The following code works as follows:

  1. listen to animation frame

    Since I'm using GSAP, I'm listening to the TweenLite.ticker 'tick' event. For requestAnimationFrame, you can do the same with window.requestAnimationFrame(callback);

  2. measure the number of frames every second and update additional data like lowestFrameRate & numberOfDrops

  3. if the condition applies, simplify the calculations to improve FPS

    The condition can either be the lowest FPS for the site (lowestFrameRate), or the number of times a frame drop occurred (numberOfDrops). It depends on your specific strategy

FPS(true /* showDebugBox */ );

function FPS(showDebugBox) {

  // SHOW FRAMERATE UI FOR DEBUGGING
  if (showDebugBox) {
    $('body').append([
      '<div class="hud">',
      'FPS: <span id="framerate">0</span>; ',
      'lowest FPS: <span id="lowest">null</span>; ',
      'DROPS Below 30: <span id="drops">0</span>',
      '</div>'
    ].join(''));
  }

  var $framerate = showDebugBox ? document.querySelector("#framerate") : {};
  var $lowest = showDebugBox ? document.querySelector("#lowest") : {};
  var $drops = showDebugBox ? document.querySelector("#drops") : {};
  var prevTime = 0;
  var frames = 0;
  var ticker = TweenLite.ticker;

  var fps;

  // will keep the lowest framerate the site was rendered at
  // keep in mind that the first render is almost always lower
  // than the average framerate later
  var lowestFrameRate = -1;
  // will keep tab on the number of drops below 30fps.
  // when this happens, disable some animations in order to
  // keep the requestAnimationFrame cycle short
  var numberOfDrops = 0;

  ticker.addEventListener("tick", update);

  function update() {

    var current = ticker.time;

    frames++;

    if (current > prevTime + 1) {
      fps = Math.round(frames / (current - prevTime));
      $framerate.textContent = fps;
      prevTime = current;
      frames = 0;

      // initialize lowestFrameRate with first fps value
      if (lowestFrameRate === -1) {
        lowestFrameRate = fps;

        $lowest.textContent = lowestFrameRate;
        console.info('lowest framrate initialized', lowestFrameRate);
      }

      // update lowest frame rate
      if (fps < lowestFrameRate) {
        lowestFrameRate = fps;

        $lowest.textContent = lowestFrameRate;
        console.info('lowest framerate', lowestFrameRate);
      }

      // update number of times frame rate dropped below 30
      if (fps < 30) {
        numberOfDrops++;

        // you can reduce the plexity of the animations
        // here if you want to base it on a drop below a threshold

        $drops.textContent = numberOfDrops;
        console.info('framerate dropped below 30');
      }

      // if there were more than 2 drops
      if (numberOfDrops >= 2) {
        // you can reduce the plexity of the animations here
        // if you want to base it on the number of drops.

        // you also need to define an end scenario for this thing
        // what happens if the frames continue to drop?
      }
    }
  }
}
.hud {
  position: fixed;
  top: 0;
  left: 0;
  font-family: "Lucida Console", Monaco, monospace;
  letter-spacing: 1px;
  line-height: 1.6;
  font-size: 10px;
  padding: 4px 8px;
  background: rgba(0, 0, 0, 0.3);
  pointer-events: none;
  user-select: none;
  z-index: 5000;
}

body {
  height: 500vh;
}
<script src="https://cdnjs.cloudflare./ajax/libs/gsap/1.19.0/TweenMax.min.js"></script>
<script src="https://cdnjs.cloudflare./ajax/libs/jquery/3.2.1/jquery.min.js"></script>

As suggested by @blazemonger you can use window.requestAnimationFrame to detect the current FPS rate. Presumably if the FPS rate drops below a certain value you could automatically disable animations.

I also remend having a "Stop animations" button placed somewhere conspicious on your website for the benefit of those of us who prefer static websites for readability's sake, in addition to those who don't want to drain their laptop batteries more than usual.

Here is a crude example of something that will stop any animations if the frame-rate drops below 30Hz:

var start = null;
var last  = null;
window.requestAnimationFrame(fpsMeasureLoop);
function fpsMeasureLoop(timestamp) {
    if( start == null ) {
        last = start = timestamp;
        return;
    }
    var dTime = timestamp - last;
    if( dTime > 33 ) {
        // If more than 33ms since last frame (i.e. below 30fps)
        document.getElementsByTagName("body")[0].className = "paused";
    }
    window.requestAnimationFrame(fpsMeasureLoop);
}

You'll need this CSS:

.paused{
    -webkit-animation-play-state:paused;
    -moz-animation-play-state:paused;
    -o-animation-play-state:paused; 
    animation-play-state:paused;
}

It's buggy because if the framerate drops below 30Hz for any reason it will stop them. Adding logic to spot trending framerates is an exercise for the reader.

发布评论

评论列表(0)

  1. 暂无评论