diff --git a/.eslintrc b/.eslintrc index 5e3beddb305..87b8f43bd83 100644 --- a/.eslintrc +++ b/.eslintrc @@ -30,10 +30,7 @@ } ], "constructor-super": 2, - "func-style": [ - 2, - "declaration" - ], + "func-style": 0, "generator-star-spacing": [ 2, { diff --git a/example/main.js b/example/main.js index 09f2f5c555d..2c085125333 100644 --- a/example/main.js +++ b/example/main.js @@ -114,13 +114,9 @@ function reducer(state = INITIAL_STATE, action) { const p1 = coordString.indexOf(')'); const coords = coordString.slice(p0, p1).split(','); return { - position: { - x: Number(coords[1]), - y: Number(coords[0]), - z: 0 - }, + position: [Number(coords[1]), Number(coords[0]), 0], color: [88, 9, 124], - radius: (Math.random() * (15 - 5 + 1) + 5) / 10 // [0.5, 1.5] + radius: (Math.random() * (15 - 5 + 1) + 5) / 10 }; }); @@ -192,7 +188,8 @@ function pointsToArcs(points) { return points.map((point, i) => { if (i === points.length - 1) { return { - position: {x0: 0, y0: 0, x1: 0, y1: 0}, + sourcePosition: [0, 0], + targetPosition: [0, 0], color: [35, 81, 128] }; } @@ -201,10 +198,8 @@ function pointsToArcs(points) { const target = points[i + 1]; return { - position: { - x0: source.position.x, y0: source.position.y, - x1: target.position.x, y1: target.position.y - }, + sourcePosition: source.position, + targetPosition: target.position, color: [ i % 255, 255 - i % 255, @@ -218,7 +213,8 @@ function pointsToLines(points) { return points.map((point, i) => { if (i === points.length - 1) { return { - position: {x0: 0, y0: 0, x1: 0, y1: 0}, + sourcePosition: [0, 0], + targetPosition: [0, 0], color: [35, 81, 128] }; } @@ -227,10 +223,8 @@ function pointsToLines(points) { const target = points[i + 1]; return { - position: { - x0: source.position.x, y0: source.position.y, - x1: target.position.x, y1: target.position.y - }, + sourcePosition: source.position, + targetPosition: target.position, color: [0, 0, 255] }; }); diff --git a/src/layers/arc-layer/arc-layer.js b/src/layers/arc-layer/arc-layer.js index af5c35710e3..531ed034699 100644 --- a/src/layers/arc-layer/arc-layer.js +++ b/src/layers/arc-layer/arc-layer.js @@ -22,8 +22,11 @@ import BaseLayer from '../base-layer'; import {Model, Program, Geometry} from 'luma.gl'; const glslify = require('glslify'); -const RED = [255, 0, 0]; -const BLUE = [0, 0, 255]; +const DEFAULT_COLOR = [0, 0, 255]; + +const defaultGetSourcePosition = x => x.sourcePosition; +const defaultGetTargetPosition = x => x.targetPosition; +const defaultGetColor = x => x.color; export default class ArcLayer extends BaseLayer { /** @@ -31,19 +34,21 @@ export default class ArcLayer extends BaseLayer { * ArcLayer * * @class - * @param {object} opts + * @param {object} props */ constructor({ strokeWidth = 1, - color0 = RED, - color1 = BLUE, - ...opts + getSourcePosition = defaultGetSourcePosition, + getTargetPosition = defaultGetTargetPosition, + getColor = defaultGetColor, + ...props } = {}) { super({ strokeWidth, - color0, - color1, - ...opts + getSourcePosition, + getTargetPosition, + getColor, + ...props }); } @@ -58,14 +63,11 @@ export default class ArcLayer extends BaseLayer { instancePositions: {size: 4, update: this.calculateInstancePositions}, instanceColors: {size: 3, update: this.calculateInstanceColors} }); - - this.updateColors(); } willReceiveProps(oldProps, nextProps) { super.willReceiveProps(oldProps, nextProps); this.state.model.userData.strokeWidth = nextProps.strokeWidth; - this.updateColors(); } createModel(gl) { @@ -97,34 +99,30 @@ export default class ArcLayer extends BaseLayer { }); } - updateColors() { - this.setUniforms({ - color0: this.props.color0, - color1: this.props.color1 - }); - } - calculateInstancePositions(attribute) { - const {data} = this.props; + const {data, getSourcePosition, getTargetPosition} = this.props; const {value, size} = attribute; let i = 0; - for (const arc of data) { - value[i + 0] = arc.position.x0; - value[i + 1] = arc.position.y0; - value[i + 2] = arc.position.x1; - value[i + 3] = arc.position.y1; + for (const object of data) { + const sourcePosition = getSourcePosition(object); + const targetPosition = getTargetPosition(object); + value[i + 0] = sourcePosition[0]; + value[i + 1] = sourcePosition[1]; + value[i + 2] = targetPosition[0]; + value[i + 3] = targetPosition[1]; i += size; } } calculateInstanceColors(attribute) { - const {data} = this.props; + const {data, getColor} = this.props; const {value, size} = attribute; let i = 0; - for (const point of data) { - value[i + 0] = point.color[0]; - value[i + 1] = point.color[1]; - value[i + 2] = point.color[2]; + for (const object of data) { + const color = getColor(object) || DEFAULT_COLOR; + value[i + 0] = color[0]; + value[i + 1] = color[1]; + value[i + 2] = color[2]; i += size; } } diff --git a/src/layers/choropleth-layer/choropleth-layer.js b/src/layers/choropleth-layer/choropleth-layer.js index 6dbc94a27e2..9dc95aa03e4 100644 --- a/src/layers/choropleth-layer/choropleth-layer.js +++ b/src/layers/choropleth-layer/choropleth-layer.js @@ -54,8 +54,8 @@ export default class ChoroplethLayer extends BaseLayer { positions: {size: 3, update: this.calculatePositions}, colors: {size: 3, update: this.calculateColors}, // Instanced attributes - pickingColors: {size: 3, update: this.calculatePickingColors, - noAlloc: true} + pickingColors: + {size: 3, update: this.calculatePickingColors, noAlloc: true} }); this.setUniforms({opacity: this.props.opacity}); @@ -98,9 +98,42 @@ export default class ChoroplethLayer extends BaseLayer { }); } - calculatePositions(attribute) { - const vertices = flattenDeep(this.state.groupedVertices); - attribute.value = new Float32Array(vertices); + extractChoropleths() { + const {data} = this.props; + const normalizedGeojson = normalize(data); + + this.state.choropleths = normalizedGeojson.features.map(choropleth => { + let coordinates = choropleth.geometry.coordinates[0]; + // flatten nested polygons + if (coordinates.length === 1 && coordinates[0].length > 2) { + coordinates = coordinates[0]; + } + return { + properties: choropleth.properties, + coordinates + }; + }); + + this.state.groupedVertices = this.state.choropleths.map( + choropleth => choropleth.coordinates.map( + coordinate => [coordinate[0], coordinate[1], 0] + ) + ); + this.state.groupedVerticesColors = this.state.choropleths.map( + choropleth => choropleth.coordinates.map( + coordinate => choropleth.properties.color || [128, 128, 128] + ) + ); + } + + calculateContourIndices(numVertices) { + // use vertex pairs for gl.LINES => [0, 1, 1, 2, 2, ..., n-1, n-1, 0] + let indices = []; + for (let i = 1; i < numVertices - 1; i++) { + indices = [...indices, i, i]; + } + return [0, ...indices, 0]; + } calculateIndices(attribute) { @@ -129,10 +162,17 @@ export default class ChoroplethLayer extends BaseLayer { this.state.model.setVertexCount(attribute.value.length / attribute.size); } + calculatePositions(attribute) { + const vertices = flattenDeep(this.state.groupedVertices); + attribute.value = new Float32Array(vertices); + } + calculateColors(attribute) { const colors = this.state.groupedVerticesColors.map( colors => colors.map( - color => this.props.drawContour ? [0, 0, 0] : [color[0], color[1], color[2]] + color => this.props.drawContour ? + // TODO - why destructure and rebuild array? + [0, 0, 0] : [color[0], color[1], color[2]] ) ); @@ -153,44 +193,6 @@ export default class ChoroplethLayer extends BaseLayer { attribute.value = new Float32Array(flattenDeep(colors)); } - extractChoropleths() { - const {data} = this.props; - const normalizedGeojson = normalize(data); - - this.state.choropleths = normalizedGeojson.features.map(choropleth => { - let coordinates = choropleth.geometry.coordinates[0]; - // flatten nested polygons - if (coordinates.length === 1 && coordinates[0].length > 2) { - coordinates = coordinates[0]; - } - return { - properties: choropleth.properties, - coordinates - }; - }); - - this.state.groupedVertices = this.state.choropleths.map( - choropleth => choropleth.coordinates.map( - coordinate => [coordinate[0], coordinate[1], 0] - ) - ); - this.state.groupedVerticesColors = this.state.choropleths.map( - choropleth => choropleth.coordinates.map( - coordinate => choropleth.properties.color || [128, 128, 128] - ) - ); - } - - calculateContourIndices(numVertices) { - // use vertex pairs for gl.LINES => [0, 1, 1, 2, 2, ..., n-1, n-1, 0] - let indices = []; - for (let i = 1; i < numVertices - 1; i++) { - indices = [...indices, i, i]; - } - return [0, ...indices, 0]; - - } - onHover(info) { const {color} = info; const index = color[0] + color[1] * 256 + color[2] * 256 * 256 - 1; diff --git a/src/layers/hexagon-layer/hexagon-layer.js b/src/layers/hexagon-layer/hexagon-layer.js index 3fa5ff4fe17..049bfb1f723 100644 --- a/src/layers/hexagon-layer/hexagon-layer.js +++ b/src/layers/hexagon-layer/hexagon-layer.js @@ -17,15 +17,15 @@ // 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. -/* eslint-disable func-style */ - import BaseLayer from '../base-layer'; import {Model, Program, CylinderGeometry} from 'luma.gl'; const glslify = require('glslify'); +const DEFAULT_COLOR = [255, 0, 0]; + const _getCentroid = x => x.centroid; const _getElevation = x => x.elevation || 0; -const _getColor = x => x.color || [255, 0, 0]; +const _getColor = x => x.color || DEFAULT_COLOR; const _getVertices = x => x.vertices; export default class HexagonLayer extends BaseLayer { diff --git a/src/layers/line-layer/line-layer.js b/src/layers/line-layer/line-layer.js index 37615d45c74..4395727fe1a 100644 --- a/src/layers/line-layer/line-layer.js +++ b/src/layers/line-layer/line-layer.js @@ -22,8 +22,11 @@ import BaseLayer from '../base-layer'; import {Model, Program, Geometry} from 'luma.gl'; const glslify = require('glslify'); -const ATTRIBUTES = { -}; +const DEFAULT_COLOR = [0, 255, 0]; + +const defaultGetSourcePosition = x => x.sourcePosition; +const defaultGetTargetPosition = x => x.targetPosition; +const defaultGetColor = x => x.color || DEFAULT_COLOR; export default class LineLayer extends BaseLayer { /** @@ -35,10 +38,16 @@ export default class LineLayer extends BaseLayer { */ constructor({ strokeWidth = 9, + getSourcePosition = defaultGetSourcePosition, + getTargetPosition = defaultGetTargetPosition, + getColor = defaultGetColor, ...opts } = {}) { super({ strokeWidth, + getSourcePosition, + getTargetPosition, + getColor, ...opts }); } @@ -87,26 +96,29 @@ export default class LineLayer extends BaseLayer { } calculateInstancePositions(attribute) { - const {data} = this.props; + const {data, getSourcePosition, getTargetPosition} = this.props; const {value, size} = attribute; let i = 0; - for (const line of data) { - value[i + 0] = line.position.x0; - value[i + 1] = line.position.y0; - value[i + 2] = line.position.x1; - value[i + 3] = line.position.y1; + for (const object of data) { + const sourcePosition = getSourcePosition(object); + const targetPosition = getTargetPosition(object); + value[i + 0] = sourcePosition[0]; + value[i + 1] = sourcePosition[1]; + value[i + 2] = targetPosition[0]; + value[i + 3] = targetPosition[1]; i += size; } } calculateInstanceColors(attribute) { - const {data} = this.props; + const {data, getColor} = this.props; const {value, size} = attribute; let i = 0; - for (const point of data) { - value[i + 0] = point.color[0]; - value[i + 1] = point.color[1]; - value[i + 2] = point.color[2]; + for (const object of data) { + const color = getColor(object); + value[i + 0] = color[0]; + value[i + 1] = color[1]; + value[i + 2] = color[2]; i += size; } } diff --git a/src/layers/scatterplot-layer/scatterplot-layer.js b/src/layers/scatterplot-layer/scatterplot-layer.js index 6ffbf4bf615..6a5216e886c 100644 --- a/src/layers/scatterplot-layer/scatterplot-layer.js +++ b/src/layers/scatterplot-layer/scatterplot-layer.js @@ -17,11 +17,16 @@ // 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 BaseLayer from '../base-layer'; import {Model, Program, Geometry} from 'luma.gl'; const glslify = require('glslify'); +const DEFAULT_COLOR = [255, 0, 255]; + +const defaultGetPosition = x => x.position; +const defaultGetRadius = x => x.radius; +const defaultGetColor = x => x.color || DEFAULT_COLOR; + export default class ScatterplotLayer extends BaseLayer { /* * @classdesc @@ -31,8 +36,18 @@ export default class ScatterplotLayer extends BaseLayer { * @param {object} props * @param {number} props.radius - point radius */ - constructor(props) { - super(props); + constructor({ + getPosition = defaultGetPosition, + getRadius = defaultGetRadius, + getColor = defaultGetColor, + ...props + }) { + super({ + getPosition, + getRadius, + getColor, + ...props + }); } initializeState() { @@ -94,31 +109,6 @@ export default class ScatterplotLayer extends BaseLayer { }); } - calculateInstancePositions(attribute) { - const {data} = this.props; - const {value, size} = attribute; - let i = 0; - for (const point of data) { - value[i + 0] = point.position.x; - value[i + 1] = point.position.y; - value[i + 2] = point.position.z; - value[i + 3] = point.radius || 1; - i += size; - } - } - - calculateInstanceColors(attribute) { - const {data} = this.props; - const {value, size} = attribute; - let i = 0; - for (const point of data) { - value[i + 0] = point.color[0]; - value[i + 1] = point.color[1]; - value[i + 2] = point.color[2]; - i += size; - } - } - calculateRadius() { // use radius if specified if (this.props.radius) { @@ -135,4 +125,31 @@ export default class ScatterplotLayer extends BaseLayer { this.state.radius = Math.max(Math.sqrt(dx * dx + dy * dy), 2.0); } + calculateInstancePositions(attribute) { + const {data, getPosition, getRadius} = this.props; + const {value, size} = attribute; + let i = 0; + for (const point of data) { + const position = getPosition(point); + const radius = getRadius(point) || 1; + value[i + 0] = position[0]; + value[i + 1] = position[1]; + value[i + 2] = position[2]; + value[i + 3] = radius; + i += size; + } + } + + calculateInstanceColors(attribute) { + const {data, getColor} = this.props; + const {value, size} = attribute; + let i = 0; + for (const point of data) { + const color = getColor(point); + value[i + 0] = color[0]; + value[i + 1] = color[1]; + value[i + 2] = color[2]; + i += size; + } + } } diff --git a/test/layers-spec.js b/test/layers-spec.js index f2de93a74a1..78494878f3f 100644 --- a/test/layers-spec.js +++ b/test/layers-spec.js @@ -66,8 +66,8 @@ const FIXTURE = { choropleths: [], // CHOROPLETHS, hexagons: [], - points: [{position: [100, 100], color:[255, 0, 0]}], - arcs: [{startPosition: [0, 0], targetPosition: [1, 3], color:[255, 0, 0]}] + points: [{position: [100, 100]}], + arcs: [{sourcePosition: [0, 0], targetPosition: [1, 3]}] };