0.10.8 • Published 7 years ago

ember-frost-viz v0.10.8

Weekly downloads
1
License
MIT
Repository
github
Last release
7 years ago

DEPRECATED This addon has been deprecated in favor of ember-frost-chart

ember-frost-viz

Travis Coveralls NPM

ember-frost-viz lets you build charts and graphs out of combinations of Ember components.

Background

This addon provides a visualization generator framework, which currently works something like this:

  1. You provide an array to a chart component
  2. Inside the chart, you define a transform for the data
    • The transform accepts dataBindings, which tell the framework what attributes to expect in each element in the data
    • The bindings accept dimensions, which create a mapping between the attribute value and some value to be displayed
  3. Inside the transform, you optionally specify one or more scales, which explain to the viewer what values area associated with positions within the transform
  4. Inside the transform, you specify one or more plots, which draw a visual representation of each element in the input array
  5. Inside the plot, you specify one or more elements, which accept a transformed array element and draw themselves.

A fairly simple example of this is in the dummy app, at /scatter.

History (TL;DR)

The viz framework originated as a visualization helper grammar within Ember, implemented using a single component with many properties. The properties expected generic data structure helpers like hash and array. The first iteration was interesting in that it was easy to express relationships with data, but suffered from several issues:

  • Modifying the appearance of a chart was difficult, because the appearance was expressed with attributes instead of components.
  • Some helpers were very heavy constructs because they needed to collect state from n-children and push updates back to parent components. The line between component and helper was blurred.

The component was rewritten in a different way: a visualization is expressed as nested components. Data bindings and formats are still expressed using helpers, but the helpers can have both scoped and global effects. With so many linked components, succinct data binding became a challenge.

Component Pattern

With a proliferation of different nested components, a simplified API based on positional parameters was implemented:

  1. Components take a positional parameter, usually an instance of a scope.
  2. Components yield as their first parameter, an instance of the object needed for the usual child component.

Components

Component and scope visual overview

array - [chart component]
[chart component] --> Scope
Scope - [transform component]
[transform component] --> TransformScope
TransformScope - [scale component]
TransformScope - [plot component]
[plot component] --> PlotElement
PlotElement - [element component]

cloud {
  AnyScope - [scope component]
  [scope component] --> AnyScope
}

chart

An ember-frost-viz chart.

This component creates the root scope for the visualization. It may be used to set the size of the visualization, and create shared dimension objects that are available for use in bindings through all scopes.

Positional Parameters

NameTypeDescription
dataarrayData to chart

Properties

NameTypeRequired?Description
widthnumberno (element width)Forced width. If absent, width is set by looking at the element after first render.
heightnumberno (element height)Forced height. If absent, height is set by looking at the element after first render.
dimensionsobjectno ({})A hash of dimensions to include in all child scopes.

Yields

NameTypeDescription
scopeobjectChart scope object

transform

A component that defines the area in which elements are to be drawn, and provides a coordinate transform from some system to the x and y of its area.

This component defines transformation of two coordinate systems -- the input system, which is specific to the transform component, and the output system, which is always (x right, y down).

If this component has peer scale components, it will automatically resize its child area to make room for the scale components along its edges.

Positional Parameters

NameTypeDescription
scopeobjectAny viz scope

Properties

NameTypeRequired?Description
dataBindingsobjectyesSets the bindings for input dimensions to the transform. A Cartesian transform expects

at least one value for x and y, e.g. {x: binding, y: binding}. Multiple bindings can be provided, e.g. {x: [bindings], ...} | data | array | no (scope.data) | Overrides the data provided to the component. Child components and bindings will see this data, not the data in the parent scope. | area | Rectangle | no (scope.area) | Overrides the transform's area rectangle provided in the scope. The area provided to child components is the component's own innerArea, calculated based on the its area and any padding. | width | number | no (area.width) | Overrides only the width from the scope. | height | number | no (area.height) | Overrides only the height from the scope.

Yields

NameTypeDescription
scopeobjectScope object including coordinateTransforms mapping function constructors.

plot

A component that takes an array of input data and creates items to be displayed.

A plot takes a client area and transformation functions, and applies dimensions and bindings to each element in the scope data provided to generate output elements. A plot can output one element per item in the array, as in the case of a scatter plot, or it can combine elements for continuous plots, such as smoothed lines. Where a binding does not resolve a value, e.g. it is bound to an attribute missing from a data element, often the element is skipped. The effect of skipping an element depends on the plot.

Positional Parameters

NameTypeDescription
scopeobjectAny viz scope

Properties

NameTypeRequired? (default)Description
selectedBindingsobjectno (if unambiguous: {x: scope.dataBindings.x, y: scope.dataBindings.y})If the scope

has multiple bindings for one of its transform dimensions, this property selects a binding, e.g. {x: scope.dataBindings.x[0]} | area | Rectangle | no (scope.area) | Sets the transform's area rectangle, overriding the area provided in the scope. The area provided to child components is the component's own innerArea, calculated based on the its area and any padding. | width | number | no (area.width) | Overrides only the width from the scope. | height | number | no (area.height) | Overrides only the height from the scope. | x | number | no (area.x) | Overrides the left edge for the plot. | y | number | no (area.y) | Overrides the top edge for the plot. | dimensions | object | no | If specified, provides additional dimensions for elements. These aren't transformed, but can be used for additional element attributes (e.g. radius, color). | coordinateTransforms | constructor | no (scope.coordinateTransforms) | Overrides the parent coordinate transforms provided. This must be a function(area) that returns { x: function(coord), y: function(coord) }. | dataBindings | object | no (scope.dataBindings) | Overrides the parent coordinate transforms provided. | allowSparseElements | boolean | no (false) | Overrides whether sparse elements are rendered

Takes a scope with a transform. Yields items to be rendered.

Yields

NameTypeDescription
elementobjectAn element item to render. The element's structure is like `{x: 0, y: 0,

element: { / original array element / }, data: / original array / }`

element

Takes an item and draws it.

The API for an element varies by element, but the attribute binding is conventional Ember. A circle element expects cx, cy and r, which can come from element.x, element.y and a constant or additional dimension.

scope component

Accepts and yields a scope.

A scope is a powerful concept, and the existing components provide many opportunities to override properties from the parent scope. Not all properties are exposed, and peer components (e.g. multiple plotters) might want to share the same overrides. This is where a scope component can help.

The scope component exposes a single property, inject. All properties in inject will override any properties in the incoming scope, and will be yielded to child scopes.

Positional Parameters

NameTypeDescription
scopeobjectAny viz scope

Properties

NameTypeRequired? (default)Description
injectobjectno ({})Overrides the incoming scope properties with all provided properties.

Yields

NameTypeDescription
scopeobjectScope object including all injected overrides.

Helpers

frost-viz/dimension

TODO Better documentation format

A dimension takes a scope, and optionally domain and range attributes.

The domain by default is the extrema of all bindings using this dimension. That is, if multiple bindings use the same dimension object, the automatically calculated domain is [ <min of all bound values>,<max of all bound values> ].

The range by default is [0, 1]. For built-in dimensions, the range can optionally be objects, colors, ...

See the documentation for d3-scale.

frost-viz/dimension/linear

A dimension that defines a linear mapping from domain to range.

frost-viz/dimension/log

A dimension that defines a logarithmic mapping from domain to range. Note that lg(0) = -∞, so any domain that incorporates 0 will automatically be adjusted in the direction of the other extreme of the domain: to a small positive value if the domain is positive, and to a small negative value if the domain is negative. This adjustment is primarily intended to support auto-domain calculation.

frost-viz/dimension/date

A dimension that defines a linear mapping from a Gregorian calendar domain to a range.

frost-viz/binding

TODO Better documentation format

A binding selects an attribute from the elements in the chart data array. The binding takes a dimension (declared inline or previously).

The syntax of a binding is the same as that for Ember.get. If each array element is an object containing a value attribute, bind to that attribute using (frost-viz/binding dimension 'value'). If each array element is an array, bind to the second element of the inner array using (frost-viz/binding dimension '[1]')

frost-viz/math

Accepts parameters and returns a calculated result.

Examples: (frost-viz/math 21 '*' 2) --> 42 (frost-viz/math 'round' 41.911386) --> 42

As shown above, all operators with arity 2 are assumed to be infix, e.g.

  • 6 '+' 3 === 9
  • 6 'min' 2 === 2

TODO Math functions with arity 2 should be prefix.

All operators of other arity are assumed to be prefix, e.g.

  • '!' false === true
  • '?' true 'foo' 'bar' === 'foo'

Operators

NOTE: If none of the builtin operators below correspond to the supplied operator, the helper will attempt to use the Math object method with the same name as the given operator, e.g. (math 'round' 41.911386) will return the result of Math.round(41.911386).

NameArityOrderNotes
identity0Any non-operator on its own returns its own value
-1prefixNumerically negates the operand
!1prefixLogically inverts the operand
+2infixSums the operands
-2infixSubtracts the operands
*2infixMultiplies the operands
/2infixDivides the first operand by the second
%2infixReturns first operand modulo second operand
&&2infixReturns first operand logical and second operand
||2infixReturns first operand logical or second operand
^^2infixReturns first operand logical xor second operand
&2infixReturns first operand bitwise and second operand. Operands are converted to 32-bit integers first
|2infixReturns first operand bitwise or second operand. Operands are converted to 32-bit integers first
^2infixReturns first operand bitwise xor second operand. Operands are converted to 32-bit integers first
?3prefixReturns operand-2 if operand-1; else operand-3.

Installation

  • git clone <repository-url> this repository
  • cd ember-frost-viz
  • npm install && bower install

Running

Running Tests

  • npm test (Runs ember try:each to test your addon against multiple Ember versions)
  • ember test
  • ember test --server

Building

  • ember build

For more information on using ember-cli, visit http://ember-cli.com/.

0.10.8

7 years ago

0.10.7

7 years ago

0.10.6

7 years ago

0.10.5

7 years ago

0.10.4

7 years ago

0.10.3

7 years ago

0.10.2

7 years ago

0.10.1

7 years ago

0.10.0

7 years ago

0.9.2

7 years ago

0.9.1

7 years ago