Skip to content
This repository has been archived by the owner on May 11, 2021. It is now read-only.

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
pbeshai committed Aug 10, 2019
0 parents commit afef7d8
Show file tree
Hide file tree
Showing 16 changed files with 6,368 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

# Matches multiple file types with brace expansion notation:
# and sets 2-space indentation
[*.{js,styl,json,yml,sql,scss}]
trim_trailing_whitespace = true
charset = utf-8
indent_style = space
indent_size = 2
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MapboxAccessToken=TODO Add your MapBox access key here (or in .env.local)
156 changes: 156 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
'use strict';

// prettier-ignore
var restrictedGlobals = ['addEventListener', 'blur', 'close', 'closed', 'confirm', 'defaultStatus', 'defaultstatus', 'event', 'external', 'find', 'focus', 'frameElement', 'frames', 'history', 'innerHeight', 'innerWidth', 'length', 'location', 'locationbar', 'menubar', 'moveBy', 'moveTo', 'name', 'onblur', 'onerror', 'onfocus', 'onload', 'onresize', 'onunload', 'open', 'opener', 'opera', 'outerHeight', 'outerWidth', 'pageXOffset', 'pageYOffset', 'parent', 'print', 'removeEventListener', 'resizeBy', 'resizeTo', 'screen', 'screenLeft', 'screenTop', 'screenX', 'screenY', 'scroll', 'scrollbars', 'scrollBy', 'scrollTo', 'scrollX', 'scrollY', 'self', 'status', 'statusbar', 'stop', 'toolbar', 'top', ];

module.exports = {
root: true,

// parser: 'babel-eslint',
globals: {
d3: true,
$: true,
google: true,
_: true,
topojson: true,
mapboxgl: true,
},

plugins: [],

env: {
browser: true,
commonjs: true,
es6: true,
jest: true,
node: true,
},

parserOptions: {
ecmaVersion: 2019,
sourceType: 'module',
ecmaFeatures: {
jsx: true,
generators: true,
},
},

rules: {
// http://eslint.org/docs/rules/
'array-callback-return': 'warn',
'default-case': ['warn', { commentPattern: '^no default$' }],
'dot-location': ['warn', 'property'],
eqeqeq: ['warn', 'allow-null'],
'new-parens': 'warn',
'no-array-constructor': 'warn',
'no-caller': 'warn',
'no-cond-assign': ['warn', 'except-parens'],
'no-const-assign': 'warn',
'no-control-regex': 'warn',
'no-delete-var': 'warn',
'no-dupe-args': 'warn',
'no-dupe-class-members': 'warn',
'no-dupe-keys': 'warn',
'no-duplicate-case': 'warn',
'no-empty-character-class': 'warn',
'no-empty-pattern': 'warn',
'no-eval': 'warn',
'no-ex-assign': 'warn',
'no-extend-native': 'warn',
'no-extra-bind': 'warn',
'no-extra-label': 'warn',
'no-fallthrough': 'warn',
'no-func-assign': 'warn',
'no-implied-eval': 'warn',
'no-invalid-regexp': 'warn',
'no-iterator': 'warn',
'no-label-var': 'warn',
'no-labels': ['warn', { allowLoop: true, allowSwitch: false }],
'no-lone-blocks': 'warn',
'no-loop-func': 'warn',
'no-mixed-operators': [
'warn',
{
groups: [
['&', '|', '^', '~', '<<', '>>', '>>>'],
['==', '!=', '===', '!==', '>', '>=', '<', '<='],
['&&', '||'],
['in', 'instanceof'],
],
allowSamePrecedence: false,
},
],
'no-multi-str': 'warn',
'no-native-reassign': 'warn',
'no-negated-in-lhs': 'warn',
'no-new-func': 'warn',
'no-new-object': 'warn',
'no-new-symbol': 'warn',
'no-new-wrappers': 'warn',
'no-obj-calls': 'warn',
'no-octal': 'warn',
'no-octal-escape': 'warn',
'no-redeclare': 'warn',
'no-regex-spaces': 'warn',
'no-restricted-syntax': ['warn', 'WithStatement'],
'no-script-url': 'warn',
'no-self-assign': 'warn',
'no-self-compare': 'warn',
'no-sequences': 'warn',
'no-shadow-restricted-names': 'warn',
'no-sparse-arrays': 'warn',
'no-template-curly-in-string': 'warn',
'no-this-before-super': 'warn',
'no-throw-literal': 'warn',
'no-undef': 'error',
'no-restricted-globals': ['error'].concat(restrictedGlobals),
'no-unexpected-multiline': 'warn',
'no-unreachable': 'warn',
'no-unused-expressions': [
'error',
{
allowShortCircuit: true,
allowTernary: true,
allowTaggedTemplates: true,
},
],
'no-unused-labels': 'warn',
'no-unused-vars': [
'warn',
{
args: 'none',
ignoreRestSiblings: true,
},
],
'no-use-before-define': [
'warn',
{
functions: false,
classes: false,
variables: false,
},
],
'no-useless-computed-key': 'warn',
'no-useless-concat': 'warn',
'no-useless-constructor': 'warn',
'no-useless-escape': 'warn',
'no-useless-rename': [
'warn',
{
ignoreDestructuring: false,
ignoreImport: false,
ignoreExport: false,
},
],
'no-with': 'warn',
'no-whitespace-before-property': 'warn',
'require-yield': 'warn',
'rest-spread-spacing': ['warn', 'never'],
strict: ['warn', 'never'],
'unicode-bom': ['warn', 'never'],
'use-isnan': 'warn',
'valid-typeof': 'warn',

'getter-return': 'warn',
},
};
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
.env.local
137 changes: 137 additions & 0 deletions DelayedPointLayer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import { ScatterplotLayer } from '@deck.gl/layers';

const fs = `
#define SHADER_NAME delayed-point-layer-fragment-shader
precision highp float;
uniform bool filled;
uniform float animationProgress;
varying vec4 vFillColor;
varying vec4 vLineColor;
varying vec2 unitPosition;
varying float innerUnitRadius;
varying float instanceAnimationProgress;
#ifndef PI
#define PI 3.141592653589793
#endif
// easing function
float backOut(float t) {
float f = 1.0 - t;
return 1.0 - (pow(f, 3.0) - f * sin(f * PI));
}
void main(void) {
// delay is a value between 0 and 1 indicating how delayed it should be
float t = instanceAnimationProgress;
// divide by 0.75 to say how long it should increase size by
// (size animation should be done at 75% through the animation, color anim continues)
float tSize = backOut(clamp(t / 0.75, 0.0, 1.0));
// our points actually render at half the size specified. This allows them
// to exceed their desired size before settling into it without clipping.
// In theory, we could modify the vertex shader to account for this, but
// easiser to just supply a bigger radius for now...
float maxSize = clamp(tSize * 0.5, 0.0, 1.0);
float distToCenter = length(unitPosition);
if (distToCenter > maxSize) { // @pbeshai edit - was 1.0
discard;
}
if (distToCenter > innerUnitRadius) {
gl_FragColor = vLineColor;
} else if (filled) {
gl_FragColor = vFillColor;
} else {
discard;
}
// use highlight color if this fragment belongs to the selected object.
gl_FragColor = picking_filterHighlightColor(gl_FragColor);
// use picking color if rendering to picking FBO.
gl_FragColor = picking_filterPickingColor(gl_FragColor);
// start at this color (white) and animate into the final color
vec4 enterColor = vec4(1.0);
// t * t to use quadratic-ish easing
gl_FragColor = mix(enterColor, gl_FragColor, t * t);
}
`;

class DelayedPointLayer extends ScatterplotLayer {
initializeState() {
super.initializeState();
this.getAttributeManager().addInstanced({
instanceDelayFactor: {
size: 1,
accessor: 'getDelayFactor',
},
});
}

// override getShaders to inject into vertex shader and add a new fragment shader
getShaders() {
return Object.assign({}, super.getShaders(), {
// inject: https://github.com/uber/luma.gl/blob/master/docs/api-reference/shadertools/assemble-shaders.md
inject: {
// inject at vertex shader (`vs`) declarations
'vs:#decl': `
attribute float instanceDelayFactor;
uniform float animationProgress;
uniform float numPoints;
uniform float pointDuration;
varying float instanceAnimationProgress;
float delayedAnimationProgress(float instanceDelayFactor, float animationProgress, float pointDuration) {
float delayProportion = 1.0 - pointDuration;
float delay = instanceDelayFactor * delayProportion;
// instanceDelayFactor = 0 => animationProgress: 0 to (1 - delayProportion) ===> 0 to 1
// instanceDelayFactor = 1 => animationProgress: delayProportion to 1 ===> 0 to 1
return clamp((animationProgress - delay) / pointDuration, 0.0, 1.0);
}
`,

// inject at vertex shader (`vs`) end of function
'vs:#main-end': `
instanceAnimationProgress = delayedAnimationProgress(instanceDelayFactor, animationProgress, pointDuration);
`,
},
// add new fragment shader (`fs`)
fs,
});
}

// override draw fucntion
draw(opts) {
// pointDuration = proportion of animation that is used to animate an individual (value between 0 and 1 where 1 is full duration)
// animationProgress = how far through the animation we are (value between 0 and 1)
const { animationProgress = 0.0, pointDuration = 0.25, data } = this.props;

// add uniforms
const uniforms = Object.assign({}, opts.uniforms, {
animationProgress,
pointDuration,
numPoints: data.length,
});
super.draw(Object.assign({}, opts, { uniforms }));
}
}

const defaultProps = {
// when a given point begins animating (value between 0 and 1)
// 0 = the first point to animate, 1 = the last point to animate
// the last point begins animating when animationProgress = 1 - pointDuration.
getDelayFactor: { type: 'accessor', value: 0.0 },
};

DelayedPointLayer.defaultProps = Object.assign(
{},
ScatterplotLayer.defaultProps,
defaultProps
);

export default DelayedPointLayer;
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# deck.gl point animation demo

A demo using deck.gl and MapBox to animate points. The dataset used is all public libraries in the United States.


## Start the demo

```
npm run start
```

Go to

- http://localhost:8080/ for the DelayedPointLayer demo (longitude wipe animation)
- http://localhost:8080/?target for the DelayedPointLayer demo (target ripple animation)
- http://localhost:8080/scatterplot.html for the ScatterplotLayer demo

1 change: 1 addition & 0 deletions data/libraries.json

Large diffs are not rendered by default.

Loading

0 comments on commit afef7d8

Please sign in to comment.