UNPKG

@deck.gl/core

Version:

deck.gl core library

122 lines 4.88 kB
// deck.gl // SPDX-License-Identifier: MIT // Copyright (c) vis.gl contributors // deck.gl, MIT license import GPUInterpolationTransition from "../../transitions/gpu-interpolation-transition.js"; import GPUSpringTransition from "../../transitions/gpu-spring-transition.js"; import log from "../../utils/log.js"; const TRANSITION_TYPES = { interpolation: GPUInterpolationTransition, spring: GPUSpringTransition }; export default class AttributeTransitionManager { constructor(device, { id, timeline }) { if (!device) throw new Error('AttributeTransitionManager is constructed without device'); this.id = id; this.device = device; this.timeline = timeline; this.transitions = {}; this.needsRedraw = false; this.numInstances = 1; } finalize() { for (const attributeName in this.transitions) { this._removeTransition(attributeName); } } /* Public methods */ // Called when attribute manager updates // Check the latest attributes for updates. update({ attributes, transitions, numInstances }) { // Transform class will crash if elementCount is 0 this.numInstances = numInstances || 1; for (const attributeName in attributes) { const attribute = attributes[attributeName]; const settings = attribute.getTransitionSetting(transitions); // this attribute might not support transitions? if (!settings) continue; // eslint-disable-line no-continue this._updateAttribute(attributeName, attribute, settings); } for (const attributeName in this.transitions) { const attribute = attributes[attributeName]; if (!attribute || !attribute.getTransitionSetting(transitions)) { // Animated attribute has been removed this._removeTransition(attributeName); } } } // Returns `true` if attribute is transition-enabled hasAttribute(attributeName) { const transition = this.transitions[attributeName]; return transition && transition.inProgress; } // Get all the animated attributes getAttributes() { const animatedAttributes = {}; for (const attributeName in this.transitions) { const transition = this.transitions[attributeName]; if (transition.inProgress) { animatedAttributes[attributeName] = transition.attributeInTransition; } } return animatedAttributes; } /* eslint-disable max-statements */ // Called every render cycle, run transform feedback // Returns `true` if anything changes run() { if (this.numInstances === 0) { return false; } for (const attributeName in this.transitions) { const updated = this.transitions[attributeName].update(); if (updated) { this.needsRedraw = true; } } const needsRedraw = this.needsRedraw; this.needsRedraw = false; return needsRedraw; } /* eslint-enable max-statements */ /* Private methods */ _removeTransition(attributeName) { this.transitions[attributeName].delete(); delete this.transitions[attributeName]; } // Check an attributes for updates // Returns a transition object if a new transition is triggered. _updateAttribute(attributeName, attribute, settings) { const transition = this.transitions[attributeName]; // an attribute can change transition type when it updates // let's remove the transition when that happens so we can create the new transition type // TODO: when switching transition types, make sure to carry over the attribute's // previous buffers, currentLength, startIndices, etc, to be used as the starting point // for the next transition let isNew = !transition || transition.type !== settings.type; if (isNew) { if (transition) { this._removeTransition(attributeName); } const TransitionType = TRANSITION_TYPES[settings.type]; if (TransitionType) { this.transitions[attributeName] = new TransitionType({ attribute, timeline: this.timeline, device: this.device }); } else { log.error(`unsupported transition type '${settings.type}'`)(); isNew = false; } } if (isNew || attribute.needsRedraw()) { this.needsRedraw = true; this.transitions[attributeName].start(settings, this.numInstances); } } } //# sourceMappingURL=attribute-transition-manager.js.map