Socket
Socket
Sign inDemoInstall

gg-aframe

Package Overview
Dependencies
382
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

    gg-aframe

A Grammar of Graphics for Virtual Reality Data Visualization using A-Frame


Version published
Weekly downloads
1
Maintainers
1
Install size
395 kB
Created
Weekly downloads
 

Readme

Source

gg-aframe

npm Dowloads npm Version JavaScript Style Guide

A Grammar of Graphics for Virtual Reality Data Visualization using A-Frame.

Simple Example Plot

View the examples page

News

0.2.0

  • layer-point
    • Now uses geometry instancing for 90FPS performance with 10,000+ points
    • Rotation speed of each point now mappable with new aesthetic spin
  • mod-oscillate - add additional dimensions to layer-point by animating marks between two points in space
  • scale-shape - automatically map raw values into usable geometry names
  • data-binding updated to debounce calls to update handlers when multiple properties of a component are bound

Data Binding

The data-binding component and system help get data from any source into gg-aframe plots and keep it synchronized for interactive plots. It can be thought of as a simplified, specialized version of the A-Frame state component that only handles array data. This allows you to have one central data repository for the scene with a list of arrays that can be mapped and synced to any A-Frame component's array properties. The central repository simplifies the process of bringing data in from other libraries and sources, as you only need to update in one place to affect the entire scene. Arrays in the store can be reused to map to multiple entities and components without any duplication of data, and updates will cascade changes to mapped components.

data-binding system

The data-binding system holds a central data store, receives updates to that store through events, and notifies bindees of updates. It is activated automatically if data-binding component is added to any entity in a scene, but it can also be forced to initialize by adding the data-binding attribute to the scene entity.

Updating data

Data is added or updated by emitting the 'update-data' event with a data object that contains arrays as members within the event detail object.

document.querySelector('a-scene').emit('update-data', {data: {array1: [...], array2: [...]}})

Each array will be added to the store if new or updated if it already exists, and updates will propagate to any bound components. Any data store arrays not included in the update will be left as-is.

data-binding component

Add this component to bind arrays from the central store to components on an entity. Multiple bindings can be added to an entity with the data-binding__id="" syntax, where id is a unique identifier for each data-binding component instance.

PropertyDescriptionDefault Value
sourceName of an array in the data store''*
targetName of schema property, as 'component.property', on a sibling component to bind (optional)''

* If source is omitted, will attempt to use the component multiple id as the source name. Note: this only works for source names that are all lower case.

Once bound, the target property will be assigned to be the same array object as the data store. data-binding will ensure the target component's update method is called whenever the data store is updated. Alternatively, omit target property and access the boundData property of the component or in the details of data-changed events.

Treat the bound data as read-only. If modified in the target component or bound-data component, changes will be reflected across the entire system to all bindees, but they will not be notified of the change, causing loss of sync. Instead, use the update-data event on the system to make changes to the data.

Event TypeDescriptionDetails object
'data-changed'Update received from the data-binding systemboundData: the bound array

Plot Container

The plot container holds all other plot elements as children, and handles some high level management and defaults.

plot

Place the plot component on the parent entity containing all layers, guides, et cetera.

At present, it merely manages the locations of any guide-legend entities. In the future, it will also be able to set default theme values and aesthetic mappings for all children.

plot adds a collision zone that covers the plot area itself (not including the guides) to support interactivity. This consists of box geometry and static-body components.

Layers

A plot can have one or more layers which add the visual aspects to a plot by mapping data to aesthetic properties to create marks such as points or lines. Aesthetic properties are always arrays. Required aesthetics for a layer must have a value for each mark and have the same length. Optional aesthetics can either have one value for each mark or a single default value that will be used for all marks. If not specified, optional aesthetic default values will be determined by the theme. Layers expect aesthetic data to already be scaled, e.g. x, y, and z in a range of 0 to 1.

layer-point

layer-point creates a 3D scatterplot by placing primitive geometries as marks at x, y, and z coordinates.

Aesthetic PropertyDescriptionDefault Value
xx coordinatesRequired
yy coordinatesRequired
zz coordinatesRequired
shapeGeometry primitive for each mark[]
sizeSize of each mark (scaling percentage)[]
colorColor of each mark[]
spinRotation speed of each mark (radians per second)[]

More layers to come...

Modifiers

This is an experimental API for layer add-ons. Modifier components can be added to entities alongside layers to add additional functionality or alter behavior.

mod-oscillate

Add additional dimensions to a layer by animating a positional aesthetic back-and-forth between two values.

PropertyDescriptionDefault
layerName of layer component to modify'layer-point'
xx coordinates to oscillate towards[]
yy coordinates to oscillate towards[]
zz coordinates to oscillate towards[]
durationMilliseconds per movement1000

Compatible layers: layer-point

Guides

Guides explain the scaling and mapping in a plot.

guide-axis

Add ticks, labels, title, and interaction zones for a positional aesthetic.

PropertyDescriptionDefault Value
axisx, y, or z axis'x'
titleArray of length 1. Name of axis mapping.['']
breaksArray. Positions along the axis for ticks.[]
labelsArray. Text to display at each break.[]

title, breaks, and labels are arrays and can be bound with data-binding.

guide-axis adds collision zones to its entity to support interactivity. These consist of a plane geometry and box static-body for the axis planes on each side of the plot. These can be interactively highlighted by toggling the visible property of material on the guide-axis entity, and the color and texture are set by the highlightColor and highlightTexture properties of theme (textures are rotated so that the top of the image aligns with larger values on the axis).

guide-legend

Add a legend for a non-positional aesthetic

PropertyDescriptionDefault Value
aestheticcolor, shape, or size'color'
titleArray of length 1. Name of axis mapping.['']
breaksArray. Aesthetic values to display[]
labelsArray. Text to display at each break[]

title, breaks, and labels are arrays and can be bound with data-binding.

guide-legend adds collision a zone to its entity consisting of a plane geometry and box static-body set just behind the labels and marks of the guide. This can be interactively highlighted by toggling the visible property of material on the guide-axis entity, and the color and texture are set by the highlightColor and highlightTexture properties of theme.

Scales

Scales map from raw data into aesthetic values. Scales are added to the plot entity and will perform data mapping for all layers and guides which utilize the aesthetic.

scale-shape

Map data into geometric shapes for the shape aesthetic.

API

scale-shape takes a single property naming the set of shapes to use from the list below.

NameDescriptionMax Levels
identityDoes no mapping. Use when the data in the shape variable has already been mapped to geometry names.
primitivesDefault. Map up to 10 levels using all available primitive geometries10: sphere, box, cone, torus, torusKnot, cylinder, tetrahedron, octahedron, dodecahedron, and icosahedron
spinnableShapes which can clearly portray rotation for the spin aesthetic6: tetrahedron, box, octahedron, dodecahedron, icosahedron, torus
sizableShapes which are scaled to have equivalent volume in order to accurately portray variations in the size aesthetic6: sphere, box, icosahedron, dodecahedron, octahedron, tetrahedron
platonicThe platonic solids in increasing order of complexity. Suitable for ranked/ordered scales and best graphical performance5: tetrahedron, box, octahedron, dodecahedron, icosahedron

Additional scales

While additional scales are still in development, use your favorite visualization library to scale the data before passing it in. See my adit application for an example of doing this using ggplot2 in R.

Themes

Themes determine the values to use for properties that aren't mapped to data, such as label font size, as well as default values to use for optional aesthetics.

theme

Layers, guides, and the plot container all have the theme component attached.

PropertyDescriptionDefault Value
sizeSize of geometric marks, approximately equal to radius0.01
shapePrimitive shape for geometric marks'sphere'
colorColor of geometric marks'black'
spinRotation speed of geometric marks (radians per second)0
fontA-Frame text component font specification'roboto'
fontScaleText scale factor'0.75'
fontColorText color'#000'
guideWidthSize of legends'0.3'
guideHeightSize of legends'0.3'
guideMarginPadding within legends'0.1'

Installation

Browser

Install and use by directly including the browser files:

<head>
  <title>My A-Frame Scene</title>
  <script src="https://aframe.io/releases/0.7.0/aframe.min.js"></script>
  <script src="https://unpkg.com/gg-aframe/dist/gg-aframe.min.js"></script>
  <script>
    window.onload = () => {
      document.querySelector('a-scene').emit('update-data', {data: {
        x: [0.05, 0.25, 0.5, 0.75, 0.95],
        y: [0.05, 0.25, 0.5, 0.75, 0.95],
        z: [0.05, 0.25, 0.5, 0.75, 0.95],
        size: [1, 2, 3, 4, 5],
        spin: [0.1, 2, 4, 6, 8],
        breaks: [0.25, 0.5, 0.75],
        labels: ['1/4', 'half', '3/4'],
        shape: [1, 2, 3, 4, 5],
        color: ['red', '#0F0', '#0FF', 'black', '#777'],
        xtitle: ['X Axis'],
        ytitle: ['Y Axis'],
        ztitle: ['Z Axis'],
        colorbreaks: ['red', '#0F0', '#0FF', 'black', '#777'],
        sizebreaks: [ 0.01, 0.02, 0.03, 0.04],
        sizelabels: ['tiny', 'small', 'medium', 'large'],
        colortitle: ['Color Legend Title'],
        shapetitle: ['Shape title'],
        sizetitle: ['Size title']
      }})
    }
  </script>
</head>
<body>
  <a-scene>
    <a-assets></a-assets>
    <!-- plot container location and appearance -->
    <a-entity plot scale-shape="platonic"
              geometry material="color: red; transparent: true; opacity: 0.5; side: back"
              position="0 1.6 -1.25" rotation="0 35 0">
      <!-- when the data-binding instance id matches the data store name, source is optional -->
      <a-entity layer-point
        data-binding__x="target: layer-point.x"
        data-binding__y="target: layer-point.y"
        data-binding__z="target: layer-point.z"
        data-binding__size="target: layer-point.size"
        data-binding__shape="target: layer-point.shape"
        data-binding__color="target: layer-point.color"
        data-binding__spin="target: layer-point.spin"></a-entity>
      <a-entity guide-axis="axis: x" theme="fontColor: #777"
        data-binding__breaks="target: guide-axis.breaks"
        data-binding__labels="target: guide-axis.labels"
        data-binding__xtitle="target: guide-axis.title"></a-entity>
      <a-entity guide-axis="axis: y"
        data-binding__breaks="target: guide-axis.breaks"
        data-binding__labels="target: guide-axis.labels"
        data-binding__ytitle="target: guide-axis.title"></a-entity>
      <a-entity guide-axis="axis: z"
        data-binding__breaks="target: guide-axis.breaks"
        data-binding__labels="target: guide-axis.labels"
        data-binding__ztitle="target: guide-axis.title"></a-entity>
      <a-entity guide-legend="aesthetic: color"
        data-binding__colortitle="target: guide-legend.title"
        data-binding__colorbreaks="target: guide-legend.breaks"></a-entity>
      <a-entity guide-legend="aesthetic: shape"
        data-binding__shapetitle="target: guide-legend.title"></a-entity>
      <a-entity guide-legend="aesthetic: size"
        data-binding__sizetitle="target: guide-legend.title"
        data-binding__sizelabels="target: guide-legend.labels"
        data-binding__sizebreaks="target: guide-legend.breaks"></a-entity>
    </a-entity>
  </a-scene>
</body>
npm

Install via npm:

npm install --save gg-aframe

Then require and use.

require('aframe');
require('gg-aframe');

Keywords

FAQs

Last updated on 24 Nov 2017

Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc