showcases/graph/graph-layer/graph-layer.js (110 lines of code) (raw):
// Copyright (c) 2016 Uber Technologies, Inc.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import {CompositeLayer, IconLayer, LineLayer, ScatterplotLayer, COORDINATE_SYSTEM} from 'deck.gl';
const defaultProps = {
offset: {x: 0, y: 0},
coordinateSystem: COORDINATE_SYSTEM.IDENTITY,
getLinkPosition: link => ({
sourcePosition: [link.source.x, link.source.y],
targetPosition: [link.target.x, link.target.y]
}),
getLinkWidth: link => 2,
getLinkColor: link => [179, 173, 158, 255],
getNodePosition: node => [node.x, node.y, 0],
getNodeColor: node => node.color || [18, 147, 154, 255],
getNodeSize: node => node.radius || 8,
nodeIconAccessors: {}
};
/**
* GraphLayer renders a collection of nodes and links between them,
* for e.g. displaying a force-directed network graph.
* As it only handles the rendering, the layout and data must be managed
* by an adaptor component.
*
* It is a composite layer, comprising:
* - a LineLayer for drawing links
* - a ScatterplotLayer for drawing nodes, or node icon backgrounds if icons are specified
* - an IconLayer for drawing node icons, if icons are specified
*/
export default class GraphLayer extends CompositeLayer {
initializeState() {
this.state = {
nodes: {},
links: {}
};
}
updateState({oldProps, props, changeFlags}) {
if (changeFlags.dataChanged) {
const {data} = props;
if (data) {
this.state.nodes = data.nodes;
this.state.links = data.links;
this.state.layoutTime = props.layoutTime;
}
}
}
renderLayers() {
const {id} = this.props;
const {nodes, links, layoutTime} = this.state;
// Accessor props for underlying layers
const {
getLinkPosition,
getLinkColor,
getLinkWidth,
getNodePosition,
getNodeColor,
getNodeSize,
nodeIconAccessors
} = this.props;
const {getIcon, iconAtlas, iconMapping, sizeScale} = nodeIconAccessors || {};
// base layer props
const {opacity, pickable, visible} = this.props;
// viewport props
const {coordinateSystem} = this.props;
const drawLinks = links && links.length > 0;
const drawNodes = nodes && nodes.length > 0;
// only draw icons if all required accessors are present
const drawIcons = drawNodes && getIcon && iconAtlas && iconMapping;
const linksLayer =
drawLinks &&
new LineLayer({
id: `${id}-link-layer`,
data: links,
getSourcePosition: d => getLinkPosition(d).sourcePosition,
getTargetPosition: d => getLinkPosition(d).targetPosition,
getColor: e => (e.highlighting ? [255, 0, 0, 200] : getLinkColor(e)),
strokeWidth: getLinkWidth(),
opacity,
pickable,
coordinateSystem,
updateTriggers: {
getSourcePosition: layoutTime,
getTargetPosition: layoutTime,
getColor: layoutTime
}
});
const nodesLayer =
drawNodes &&
new ScatterplotLayer({
id: `${id}-${drawIcons ? 'node-bg-layer' : 'node-layer'}`,
data: nodes,
getPosition: getNodePosition,
getRadius: getNodeSize,
getFillColor: n => (n.highlighting ? [255, 255, 0, 255] : getNodeColor(n)),
opacity,
pickable,
coordinateSystem,
updateTriggers: {
getPosition: layoutTime,
getFillColor: layoutTime
},
visible
});
const nodeIconsLayer =
drawIcons &&
new IconLayer({
id: `${id}-node-icon-layer`,
data: nodes,
getColor: getNodeColor,
getIcon,
getPosition: getNodePosition,
getSize: getNodeSize,
iconAtlas,
iconMapping,
opacity,
pickable,
coordinateSystem,
sizeScale,
updateTriggers: {
getPosition: layoutTime
},
visible
});
return [linksLayer, nodesLayer, nodeIconsLayer];
}
}
GraphLayer.layerName = 'GraphLayer';
GraphLayer.defaultProps = defaultProps;