UNPKG

@deck.gl/experimental-layers

Version:

Experimental layers for deck.gl

189 lines (171 loc) 5.69 kB
// Copyright (c) 2015 - 2017 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 } from '@deck.gl/core'; import TextMultiIconLayer from './text-multi-icon-layer'; /* global fetch */ const DEFAULT_COLOR = [0, 0, 0, 255]; // TODO: support these options... // const TEXT_ANCHOR = { // start: 1, // middle: 0, // end: -1 // }; // const ALIGNMENT_BASELINE = { // top: 1, // center: 0, // bottom: -1 // }; const defaultProps = { getText: x => x.text, getPosition: x => x.coordinates, getColor: x => x.color || DEFAULT_COLOR, getSize: x => x.size || 32, getAngle: x => x.angle || 0, getTextAnchor: x => x.textAnchor || 'middle', getAlignmentBaseline: x => x.alignmentBaseline || 'center', getPixelOffset: x => x.pixelOffset || [0, 0], fp64: false, fontTexture: null, fontInfo: null, fontSmoothing: 0.2 }; export default class AdvancedTextLayer extends CompositeLayer { initializeState() { this.state = { iconAtlas: this.props.fontTexture, iconMapping: null }; // TODO: fetch again if props change fetch(this.props.fontInfo).then(response => { response.json().then(json => this.parseFontInfo(json)); }); } parseFontInfo(json) { const iconMapping = {}; json.forEach(fontChar => { const charid = fontChar.charid, x = fontChar.x, y = fontChar.y, width = fontChar.width, height = fontChar.height, xadvance = fontChar.xadvance, xoffset = fontChar.xoffset, yoffset = fontChar.yoffset; iconMapping[String.fromCharCode(charid)] = { x, y, width, height, mask: true, xadvance, xoffset, yoffset }; }); this.setState({ iconMapping }); } updateState(_ref) { let props = _ref.props, oldProps = _ref.oldProps, changeFlags = _ref.changeFlags; if (changeFlags.dataChanged || changeFlags.updateTriggersChanged && (changeFlags.updateTriggersChanged.all || changeFlags.updateTriggersChanged.getText || changeFlags.updateTriggersChanged.getPosition)) { this.transformStringToLetters(); } } transformStringToLetters() { const _this$props = this.props, data = _this$props.data, getText = _this$props.getText, getPosition = _this$props.getPosition; if (data.length === 0) { return; } // TODO: auto-refresh when iconMapping is available const iconMapping = this.state.iconMapping; if (!iconMapping) { return; } const transformedData = data.map(val => { const text = getText(val); if (!text) { return []; } const position = getPosition(val); let xpos = 0; return Array.from(text).map((letter, index) => { const _this$state$iconMappi = this.state.iconMapping[letter], xadvance = _this$state$iconMappi.xadvance, xoffset = _this$state$iconMappi.xoffset, yoffset = _this$state$iconMappi.yoffset, width = _this$state$iconMappi.width, height = _this$state$iconMappi.height; const x = xpos + (width / 2.0 - xoffset); const y = height / 2.0 + yoffset; xpos += xadvance; return { icon: letter, position, x, y }; }); }).reduce((prev, curr) => [...prev, ...curr]); this.setState({ data: transformedData }); } renderLayers() { const _this$state = this.state, data = _this$state.data, iconAtlas = _this$state.iconAtlas, iconMapping = _this$state.iconMapping; if (!iconMapping || !iconAtlas || !data) { return null; } const _this$props2 = this.props, getColor = _this$props2.getColor, getSize = _this$props2.getSize, getAngle = _this$props2.getAngle, getPixelOffset = _this$props2.getPixelOffset, fontSmoothing = _this$props2.fontSmoothing, fp64 = _this$props2.fp64, sizeScale = _this$props2.sizeScale; return [new TextMultiIconLayer(this.getSubLayerProps({ id: 'adv-text-multi-icon-layer', data, iconAtlas, iconMapping, getColor, getSize, getAngle, getPixelOffset, fontSmoothing, fp64, sizeScale, updateTriggers: { getAngle, getColor, getSize } }))]; } } AdvancedTextLayer.layerName = 'AdvancedTextLayer'; AdvancedTextLayer.defaultProps = defaultProps; //# sourceMappingURL=advanced-text-layer.js.map