glsl-transition-vignette-grid
Version:
renders a grid of glsl-transition-vignette efficiently (cached + pull of WebGL canvas)
160 lines (140 loc) • 4.69 kB
JavaScript
import React from "react";
import difference from "lodash/array/difference";
import find from "lodash/collection/find";
import Vignette from "glsl-transition-vignette";
import SharedCanvas from "glsl-transition-vignette/SharedCanvas";
const PropTypes = React.PropTypes;
var VignetteGrid = React.createClass({
propTypes: {
/**
* style the root element.
* Typical use-case: define a width that will constraints the grid. You can also use margin: "0 auto"
*/
style: PropTypes.object,
/**
* size of each vignette.
* Be sure the images you give matches the same ratio.
*/
vignetteWidth: PropTypes.number.isRequired,
vignetteHeight: PropTypes.number.isRequired,
/**
* Define margins on each vignette.
* if a 4-length array is provided, it is applied to: [top, right, bottom, left]
* if a [h,w] array is provided, [h,w,h,w] is used (like in CSS).
* if a number X is provided, [X,X,X,X] is used.
*/
vignetteMargin: PropTypes.oneOfType([ PropTypes.array, PropTypes.number ]),
/**
* Images URLs to use for the vignettes.
* Provide at least 2 images.
*/
images: PropTypes.array.isRequired,
/**
* the `transitions` array MUST not mutate.
* ALL transitions are displayed,
* up to you to splice your collection and handle pagination.
*/
transitions: PropTypes.array.isRequired,
/**
* renderVignette: (props, transition) => <Vignette {...props} /> element
* You should give props to Vignette. You can enhance them.
*/
renderVignette: PropTypes.func,
/**
* an optional configuration for the Canvas Cache to use.
* the cache system is a pull of WebGL Canvas to use for rendering the vignettes.
*/
cache: PropTypes.shape({
resolution: PropTypes.number, // the number of frames to display when caching the frames.
delay: PropTypes.number // delay a bit the cache computation to not block the page (this is multiplied by the vignette (index+1))
})
},
getDefaultProps () {
return {
style: {},
vignetteMargin: 0,
dpr: window.devicePixelRatio || 1,
renderVignette: props => <Vignette {...props} />,
cache: {
resolution: 64,
delay: 30
}
};
},
componentWillMount() {
const { transitions, vignetteWidth, vignetteHeight, dpr } = this.props;
this.cache = SharedCanvas.create(vignetteWidth, vignetteHeight, dpr);
transitions.forEach(t => this.cache.createTransitionDrawer(t.id, t.glsl, t.uniforms));
},
componentWillUnmount() {
this.cache.destroy();
this.cache = null;
},
componentWillUpdate (nextProps) {
const {
transitions,
width,
height,
dpr
} = this.props;
if (nextProps.dpr !== dpr || nextProps.width !== width || nextProps.height !== height) {
this.cache.resize(nextProps.width, nextProps.height, nextProps.dpr);
}
if (nextProps.transitions !== transitions) {
var cache = this.cache;
var data = nextProps.transitions;
var beforeIds = cache.getAllIds();
var afterIds = data.map(t => t.id);
var deleted = difference(beforeIds, afterIds);
var created = difference(afterIds, beforeIds);
deleted.forEach(id => cache.removeTransitionDrawer(id));
created.forEach(id => {
var transition = find(data, function (t) { return t.id === id; });
cache.createTransitionDrawer(id, transition.glsl, transition.uniforms);
});
}
},
render: function () {
const {
style,
transitions,
images,
renderVignette,
vignetteMargin,
vignetteWidth,
vignetteHeight,
cache,
dpr
} = this.props;
const vignetteMarginCSS =
(typeof vignetteMargin === "number" ? [vignetteMargin] : vignetteMargin)
.map(m => m+"px")
.join(" ");
const items = transitions.map((transition, i) => {
var cacheConfig = {
drawer: this.cache.getTransitionDrawer(transition.id),
resolution: cache.resolution,
delay: (i+1) * cache.delay
};
return renderVignette({
style: {
display: "inline-block",
margin: vignetteMarginCSS
},
width: vignetteWidth,
height: vignetteHeight,
dpr: dpr,
images: images,
glsl: transition.glsl,
uniforms: transition.uniforms,
id: transition.id,
key: transition.id,
name: transition.name,
owner: transition.owner,
cache: cacheConfig
}, transition);
});
return <div style={style}>{items}</div>;
}
});
export default VignetteGrid;