npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vr-super-stats

v1.4.1

Published

Modern stats component for A-Frame WebXR projects that shows stats while in VR itself

Downloads

1

Readme

loading-bar sample-report-3

features

  • get stats component data in VR, while you're actually using your app
  • high performance, just one canvas/image draw-call texture for all stats (though each graph is its own canvas/image/draw-call, if you include those)
  • uses existing stats component under the hood, so same numbers, no re-inventing the wheel
  • pick which stats you want to track, reduce clutter
  • throttle to as smooth or as performance sensitive as you want
  • pick background color, including optional opacity
  • include some, all, or no graphs
  • attaches to camera by default, but can attach anywhere in-scene you want
  • default behavior is to display when enter-vr, and hide and show stats when exit-vr, but behavior can be specified with options
  • set targets for maximum or minimum stats values, which will cause numbers to be red or green accordingly
  • by default, shows all stats and graphs and has some opacity, and some default target values for the major stats
  • if you prefer the lightest weight option instead, just set performancemode='true;' and showlabels:fps,raf; (or exactly whatever stats you want to track).
  • track live performance and view in-VR reports on caverage/high/low within sample period at a sample rate you determine
  • helper components for activating on events (e.g. buttondown event from tracked-controller)

yet another necro component pulled into service

I've wanted this for a while, but I googled, found this, and then found a library that used to do what I wanted 5 years ago (and hadn't been touched since) in an older version of A-Frame. I've spent some time--arguably too much time--almost completely rewriting it, improving it, making it faster, lighter, and adding features.

You can access it through jsdelivr's cdn here: https://cdn.jsdelivr.net/gh/kylebakerio/[email protected]/vr-super-stats.js

vr-super-stats orange some-graphs-only allgraphs-opacity sample-report-2

Installation

Browser

Install and use by directly including the browser file:

<head>
  <title>My A-Frame Scene</title>
  <script src="https://aframe.io/releases/1.2.0/aframe.min.js"></script>
  <script src="https://cdn.jsdelivr.net/gh/kylebakerio/[email protected]/vr-super-stats.js"></script>
</head>

<body>
  <a-scene vr-super-statsr></a-scene>
</body>

Usage Examples

default behavior:

when you enter VR, full stats get attached to your face, about half a meter down and forward from you. When you are not in VR, you see the normal 2d stats.

<a-scene vr-super-stats></a-scene>

just want fps and triangles and raf, and graphs for only the first two

<a-scene vr-super-stats="showlabels:fps,raf,triangles; showgraphs:fps,raf"></a-scene>

no graphs, just numbers please

takes up less space and reduces overhead

<a-scene vr-super-stats="showgraphs:null;"></a-scene>

high performance mode defaults?

bare minimum makes for the lighest tick, producing the purest readings possible

<a-scene vr-super-stats="performancemode:true;"></a-scene>

no targets

improves performance

<a-scene vr-super-stats="targetmax:{};targetmin:{}"></a-scene>

custom targets

shoot high, or shoot low, based on your platform

<a-scene vr-super-stats='targetmin:{"fps":59};targetmax:{"raf":30}'></a-scene>

only fps graph, but all numbers

since all labels and graphs are enabled by default, this overrides this existing graph list

<a-scene vr-super-stats="showgraphs:fps;"></a-scene>

advanced examples

enable default auto-report (600 ticks after enter-vr, display for 30 seconds before disappearing)

runs and displays a report on stats collected from 600 ticks

<a-scene vr-super-stats='samplereport:{"autostart":true};'></a-scene>

start sampling manually

<a-scene vr-super-stats></a-scene>
<script>
         // ... at the appropriate moment... 
         const samplesToTake = 200
         const timeToShowResults = 10000
         document.querySelector('[vr-super-stats]').components['vr-super-stats'].sample(samplesToTake).then(() => {
            document.querySelector('[vr-super-stats]').components['vr-super-stats'].showSampleCanvas(timeToShowResults)
         })
</script>

attach translucent stats to your left hand when you enter vr:

    <a-scene vr-super-stats="anchorel:#left-hand; position:0 -.5 0; backgroundcolor:rgba(255, 255, 255, 0.8);">
      <a-entity id="rig" position="0 0 0">
        <a-camera camera position="0 1.6 0" look-controls></a-camera>
        <a-entity hand-controls="hand: left" id="left-hand"></a-entity>
        <a-entity hand-controls="hand: right">              </a-entity>
      </a-entity>
    </a-scene>

make stats appear on your right controller when you press button on your right controller, run sampling when you press button on left controller

<a-scene vr-super-stats="anchorel:#right-hand; position:0 -.5 0;" >
      <a-entity id="rig" position="0 0 0">
        <a-entity camera id="the-cam" position="0 1.6 0"></a-entity>
        <a-entity sample-on-event id="left-hand" hand-controls="hand: left"></a-entity>
        <a-entity stats-on-event id="right-hand" hand-controls="hand: right"></a-entity>
      </a-entity>

make the stats panel a fixed item in your scene's space, remaining there whether in vr or not:

stick a VR panel somewhere you want in the scene, and make it stay there, whether you're in VR or not.

<a-scene vr-super-stats="anchorel:#the-box;position:0 .4 0; alwaysshow3dstats:true; show2dstats:false;" >
     <a-circle id="floor" rotation="-90 0 0" radius="400" color="#7BC8A4"></a-circle>
     <a-box id="the-box" position="-1 0.5 -6" rotation="0 45 0" color="red"></a-box>
</a-scene>

Demo

Glitch workspace (May show work-in-progress) Or, see the examples in this repo.

params


  schema: {
    enabled: { type: "boolean", default: true },
    debug: { type: "boolean", default: false },

    position: { type: "string", default: "0 -1.1 -.5" },
    rotation: { type: "string", default: "-20 0 0" },
    scale: { type: "string", default: "1 .8 1" },

    performancemode: { type: "boolean", default: false }, // set of defaults to focus on making it as light of impact as possible
    throttle: { type: "number", default: 50 }, // how many ms between recalc, has biggest effect on performance (which, here, you can easily see for yourself! hah.)

    backgroundcolor: { type:"color", default: "orange"}, // you can specify semi-transparent colors using css style rgba(r,g,b,a) color declarations as well.

    show2dstats: { type: "boolean", default: true },  // show the built-in 'stats' component when not in VR
    alwaysshow3dstats: { type: "boolean", default: false },  // show this component even when not in VR
    anchorel: { type: "selector", default: "[camera]" }, // anchor in-vr stats to something other than the camera

    showlabels: {type: 'array', default:['raf','fps','geometries','programs','textures','calls','triangles','points','entities','load time']}, // please give all inputs in lowercase
    showgraphs: {type: 'array', default:['raf','fps','geometries','programs','textures','calls','triangles','points','entities','load time']}, // this will be auto-filtered down to match above, but you can filter down further if you want, say, 4 values in text, but only 1 in graph form. you can also select `null` or `false` or `[]` to turn off all graphs.

    //
    // advanced options:
    // 
    
    // targetmax
    // targetmin
    // samplereport
    // ^ these three are defined below as custom schema options--basically, they take in JSON (if serializing or if defining in HTML, see examples) or straight up JS objects (if adding to scene programatically)    
    
    samplereport: {
      // all numbers in ms
      default: JSON.stringify({
        autostart: false, // if false, can be programtically started by e.g. a button press by calling 
                          // if true, will fire every time `enter-vr` event is triggered
        /*
          const ticksToSample = 600;
          const durationToShowVRSampleReport = 20000 // 20 seconds
          document.querySelector('[vr-super-stats]').components['vr-super-stats'].sample(ticksToSample).then(() => {
              document.querySelector('[vr-super-stats]').components['vr-super-stats'].showSampleCanvas(durationToShowVRSampleReport)
          })
        */
        delay: 0, // if autostart true, how long after app launch to auto-start sampling
        samples: 200, // if autostart true, how many samples to take
        displayDuration: 30000, // how long to leave report up in VR before auto-closing
      }),
      parse: json => {
        return typeof json === "string" ? JSON.parse(json) : json; 
      },
      stringify: JSON.stringify
    },
    
    // thrown in are some sane defaults. This library is written/expects all stats to be given in lowercase everywhere, they will be uppercased as needed.
    // note that you can only have one or the other defined for a given property; for performance, only one will be checked per property. to maximize performance, set no targets.
    targetmax: {
      default: JSON.stringify({
        calls: 200, // too many draw calls kills responsiveness
        raf: 15, // needed to keep responsiveness around 60fps
        triangles: 100000, // rough limit for mobile experiences to be smooth
        "load time": 3000, // subjective
        points: 15000, // unsure, I've heard 20000 is a drag, but likely lower than that
        entities: 200, // unsure, I'm more familiar with draw calls, suggested improved number here welcome
        // you can specify your own targets for any stats props, and they'll turn red when they rise above target
        // this does come with a small performance penalty
      }),
      capLabels: ['geometries','programs','textures','calls','triangles','points','entities','load'], // these props are auto-uppercased once for faster processing in tick handler
      parse: json => {
        const output = typeof json === "string" ? JSON.parse(json) : json; 
        
        const capitalizeWord = function(word) {
          return word[0].toUpperCase() + word.slice(1,word.length)
        }
        Object.keys(output).forEach(label => {
          output[capitalizeWord(label)] = output[label]
        })
        output['Load Time'] = output['Load Time'] || output['load time'] || output['load']; // || output['loadtime'] || output['load_time'] || output['Load'] || output['Load time'] || output['load-time'] ||
        return output;
      },
      stringify: JSON.stringify
    },
    targetmin: {// inverse of targetmax, for values where lower is better
      default: JSON.stringify({
        fps: 75, // phones cap at 60, quest 1 aimed for 75.
        // you can specify targets for any stats props, and they'll turn red when they fall below target
        // this does come with a small performance penalty
      }),
      capLabels: ['geometries','programs','textures','calls','triangles','points','entities','load'], // these props are auto-uppercased once for faster processing in tick handler
      parse: json => {
        const output = typeof json === "string" ? JSON.parse(json) : json; 
        
        const capitalizeWord = function(word) {
          return word[0].toUpperCase() + word.slice(1,word.length)
        }
        Object.keys(output).forEach(label => {
          output[capitalizeWord(label)] = output[label]
        })
        output['Load Time'] = output['Load Time'] || output['load time'] || output['load']; // || output['loadtime'] || output['load_time'] || output['Load'] || output['Load time'] || output['load-time'] ||
        return output;
      },
      stringify: JSON.stringify
    }
  },