1000words.js allows interactive graphical views to be built declaratively. This means the application
only needs to specify what it wants to achieve and the library is tasked with how to achieve it.
Application responsibilities:
The library does the heavy lifting of:
1. Concepts
2. Shape Types
3. Shape Position
4. Shape Detail Level
5. Layers
6. Creating Views
7. Events
8. Modifying Shape Attributes
9. Modifying Shape Position
10. Drilldown
11. Complete Example
12. API
13. Misc
14. Development Workflow
Interactive scenes (Views) are instantiated by 1000Words.js in a DOM element specified by the application.
Views contain Shapes.
Shapes are instances of Shape Types.
The application specifies each shape's position (x, y) expressed as a percentage of the view's width and height.
The definition of what a shape looks like is defined once per Shape Type in the form of SVG (string snippets).
Views can be configured to publish events when a shape is clicked, comes into focus, the viewport changes etc. The application can subscribe to these events.
Shape Groups contain one or more shape instances, of one or more shape types, and are used to configure:
Drilldown into shapes is supported. When a user dives into (zooms in) a shape configred for drilldown, a new sub-view is opened up. One or more shapes in the new view can, in turn, be configured for drilldown (recursive).
Infinite Canvas can be used for very large screens. A summary or Overview is provide to accompany the Primary View. The overview provides a quick look at what part of the main view is currently visible. It comes with a Viewport Controller which users can drag to quickly pan across the primary view as desired.
▸ HomeA shape type (e.g. Car, Circle, House, Hospital) is expressed as a class that extends the library's built-in shape class
const DomainShape = $1000Words.import('DomainShape');
export default class Car extends DomainShape {
renderContents(node, detailLevel) {...} // shape svg string injection
}
// The standardized definition of a shape should render inside a box with
// 0x0 and 100x100 as the top-left and bottom-right corners.
// NOTE: The shape definition is independent of how 'large' shape
// instances are or 'where' they are placed on the scene.
// square
<rect x="0" y="0" width="100" height="100" stroke="red"></rect>
// circle
<circle cx="50" cy="50" r="50" stroke="blue"></circle>
// shape with a bunch of paths
<g>
<path d="m22.16 ..." stroke="green"></path>
<path ...></path>
<path ...></path>
</g>
The position is specified in percentage terms when the shape is created.
$1000Words.createShape(Car, "car-fred", view, options, 10, 8);
$1000Words.createShape(Car, "car-jimmy", view, options, 85, 90);
$1000Words.createShape(Truck, "company-truck", view, options, 50.21, 60.07);
For graphical scenes, things typically get more detailed as the user zooms in. When using 1000Words.js, it isn't strictly necessary to show shapes in greater level of detail as the user zooms in. However the UX design of the scene can often involve showing shapes at different amounts of detail, depending on the zoom level.
const ShapeConfigurations = $1000Words.import('ShapeConfigurations');
const configs = new ShapeConfigurations( {
shapeTypes: [], // optional - use when svg referenced elements are used
groups: [{
name: 'trees',
existences: {1 : 0.5, 20 : 0}, // covered in the 'layers' section
resolutions: {1 : 'low', 3: 'medium', '8': 'high' },
// show the high fidelity version of tree when zoom level goes to 8
// and above and medium fidelity version when zoom level goes below 8
...
}]
})
...
$1000Words.createView('Main View', container, configs, onEvent, eventsOfInterest)
.then( view => {...} )
resolutions: {1 : 'low', 2: 'medium', '8': 'high'}
resolutions: {1 : 'low', 3: 'medium', '4': 'high', '12': 'superhigh'}
resolutions: {1 : 'far away', 9': 'clear sight', '14': 'rubbing noses'}
resolutions: {1 : 'standard'} // fixed resolution, independent of zoom level
// 1000Words.js will determine when it is time to display a shape at a different detail
// level and ask the shape for the SVG that corresponds to that level (e.g. 'clear sight')
low
medium
high
Layers allow groups of shapes to come into or go out of existence. Scene designers can find many creative uses for layers. Two, out of potentially many, potential uses are outlined below:
const ShapeConfigurations = $1000Words.import('ShapeConfigurations');
const configs = new ShapeConfigurations( {
shapeTypes: [], // optional - use when svg referenced elements are used
groups: [{
name: 'big',
existences: {1: 20, 10 : 0}, // the shapes included in the
// 'big' group will be visible in the beginning (zoom = 1) with a size
// of 20% of the view and will be hidden when the user zooms past 10
resolutions: {1 : 'standard'}
...
},
{
name: 'medium',
existences: {12 : 10, 15: 0}, // 10% of viewport when zoom is 12
resolutions: {4 : 'standard' }
...
},
{
name: 'small',
existences: {150 : 7, 30: 0},
resolutions: {20 : 'standard' }
},
{name: 'tiny ...}, {name: 'miniscule ...}, {microscopic ...}
})
...
$1000Words.createView('Main View', container, configs, onEvent, eventsOfInterest)
.then( view => {...} )
const ShapeConfigurations = $1000Words.import('ShapeConfigurations');
const configs = new ShapeConfigurations( {
shapeTypes: [], // optional - use when svg referenced elements are used
groups: [{
name: 'settings-marker',
existences: {1 : 1, 20 : 0},
resolutions: {1 : 'standard'}
...
},
{
name: 'settings',
existences: {20 : 8},
resolutions: {20 : 'standard' }
...
}]
})
...
$1000Words.createView('Main View', container, configs, onEvent, eventsOfInterest)
.then( view => {...} )
Views are created inside a placeholder DOM element created by the application. Views need to be created prior to creating individual shapes. View creation takes the following inputs:
const ShapeConfigurations = $1000Words.import('ShapeConfigurations');
const EventType = $1000Words.import('EventType');
const ShapeEventType = $1000Words.import('ShapeEventType');
const onEvent = (event) => console.log(event);
const container = document.getElementById("my-view-container");
// see 'Layers' & 'Shape Detail Level' for details on shape configs
const configs = new ShapeConfigurations( {...} );
const events = [ShapeEventType.IN_FOCUS, ShapeEventType.SELECT, EventType.VIEWPORT];
$1000Words.createView(viewName, container, configs, onEvent, events)
.then( view => {
const shape1 = $1000Words.createShape(type1, id1, view, options, x1, y1);
const shape2 = $1000Words.createShape(type2, id2, view, options, x2, y2);
view.initialize(...);
});
Applications can subscribe to various events of interest, emitted by the library.
const ShapeConfigurations = $1000Words.import('ShapeConfigurations');
const EventType = $1000Words.import('EventType');
const ShapeEventType = $1000Words.import('ShapeEventType');
const onEvent = (event) => console.log(event);
const events = [ ShapeEventType.IN_FOCUS, ShapeEventType.SELECT,
EventType.VIEWPORT_EVENT ];
$1000Words.createView(viewName, container, configs, onEvent, events)
.then( view => {...}
para para should be serif?
coming soon...
coming soon...
coming soon...
coming soon...
<path
style="fill:#edc496..."
d="m 9.544... z"
id="path3191-9" />
should be rewritten as
<path
style="fill:#edc496..."
d="m 9.544... z">
</path>
coming soon...