@carto/airship-bridge
Version:
Airship bridge to other libs (CARTO VL, CARTO.js)
181 lines (180 loc) • 7.06 kB
JavaScript
import { select } from '../../util/Utils';
/**
* This class is an orchestrator for Time Series widgets. It does not extend BaseFilter because for all intents
* and purposes, we can use a numerical histogram. This class is only responsible of particular Time Series event
* handling with regards to VL.
*
* The provided layer Viz object *must have* a variable called `@animation`
*
* @export
* @class TimeSeries
*/
var TimeSeries = /** @class */ (function () {
/**
* Creates an instance of TimeSeries.
* @param {*} carto CARTO VL namespace
* @param {*} layer A CARTO VL layer
* @param {any | string} timeSeries An Airship TimeSeries HTML element, or a selector
* @param {() => void} readyCb A callback to be called when we're done configuring internals
* @memberof TimeSeries
*/
function TimeSeries(carto, layer, column, timeSeries, readyCb, duration, fade, variableName, propertyName, autoplay) {
var _this = this;
if (duration === void 0) { duration = 10; }
if (fade === void 0) { fade = [0.15, 0.15]; }
this._timeSeriesWidget = select(timeSeries);
this._layer = layer;
this._carto = carto;
this._columnName = column;
this._duration = duration;
this._fade = fade;
this._variableName = variableName || 'animation';
this._propertyName = propertyName || 'filter';
this._autoplay = autoplay || false;
if (layer.viz) {
this._onLayerLoaded();
readyCb();
}
else {
layer.on('loaded', function () {
_this._onLayerLoaded();
readyCb();
});
}
}
TimeSeries.prototype.removeHistogramLayer = function () {
this._dataLayer.remove();
};
/**
* Set the range of the animation input.
*
* This is called when the time series selection is changed.
*
* @param {[number, number]} range
* @returns
* @memberof TimeSeries
*/
TimeSeries.prototype.setRange = function (range) {
if (!this._animation || !this._animation.input || !this._animation.input.min || !this._animation.input.max) {
return;
}
if (range === null) {
this._animation.input.min.blendTo(this._min, 0);
this._animation.input.max.blendTo(this._max, 0);
this._animation.duration.blendTo(this._duration, 0);
}
else if (range[0] !== range[1]) {
var s = this._carto.expressions;
var min = void 0;
var max = void 0;
var ratio = void 0;
if (this._animation.input.min.expressionName === 'Blend' &&
this._animation.input.min.mix.expressionName !== 'Transition') {
if (typeof range[0] === 'number' && typeof range[1] === 'number') {
min = range[0];
max = range[1];
ratio = Math.min(1, (max - min) / (this._max.value - this._min.value));
}
else if (range[0] instanceof Date && range[1] instanceof Date) {
min = s.time(range[0]);
max = s.time(range[1]);
ratio = Math.min(1, (range[0].getTime() - range[1].getTime()) / (this._max.value - this._min.value));
}
this._animation.input.min.blendTo(min, 0);
this._animation.input.max.blendTo(max, 0);
this._animation.duration.blendTo(this._duration * ratio, 0);
}
}
};
Object.defineProperty(TimeSeries.prototype, "variableName", {
get: function () {
return this._variableName;
},
enumerable: true,
configurable: true
});
Object.defineProperty(TimeSeries.prototype, "propertyName", {
get: function () {
return this._propertyName;
},
set: function (name) {
this._propertyName = name;
},
enumerable: true,
configurable: true
});
TimeSeries.prototype.setDuration = function (duration) {
this._duration = duration;
this._animation.duration.blendTo(duration, 0);
};
Object.defineProperty(TimeSeries.prototype, "animation", {
get: function () {
return this._animation;
},
enumerable: true,
configurable: true
});
TimeSeries.prototype.restart = function () {
this._animation.setProgressPct(0);
};
/**
* This method sets up the events to handle animation updates and bind it to the TimeSeries widget:
* - Update the progress
* - Update the progress when user seeks
* - Play / Pause events
*
* @private
* @memberof TimeSeries
*/
TimeSeries.prototype._onLayerLoaded = function () {
var _this = this;
this._viz = this._layer.viz;
var expr = this._getAnimationExpression();
if (expr.a && expr.b) {
this._animation = expr.a.expressionName === 'animation' ? expr.a : expr.b;
}
else {
this._animation = expr;
}
this._viz.variables[this._variableName] = this._animation;
this._viz[this._propertyName].blendTo(expr, 0);
this._animation.parent = this._viz;
this._animation.notify = this._viz._changed.bind(this._viz);
this._max = this._animation.input.max;
this._min = this._animation.input.min;
this._duration = this._animation.duration.value;
this._layer.on('updated', function () {
_this._timeSeriesWidget.progress = _this._animation.getProgressPct() * 100;
_this._timeSeriesWidget.playing = _this._animation.isPlaying();
});
this._timeSeriesWidget.animated = this._autoplay;
this._timeSeriesWidget.addEventListener('seek', function (evt) {
_this._animation.setProgressPct(evt.detail / 100);
_this._timeSeriesWidget.progress = evt.detail;
});
this._timeSeriesWidget.addEventListener('play', function () {
_this._animation.play();
});
this._timeSeriesWidget.addEventListener('pause', function () {
_this._animation.pause();
});
};
TimeSeries.prototype._getAnimationExpression = function () {
if (this._variableName && this._viz.variables[this._variableName]) {
return this._viz.variables[this._variableName];
}
if (this._propertyName &&
this._viz[this._propertyName] &&
this._viz[this._propertyName].isAnimated()) {
return this._viz[this._propertyName];
}
return this._createDefaultAnimation();
};
TimeSeries.prototype._createDefaultAnimation = function () {
var s = this._carto.expressions;
return s.animation(s.linear(s.prop(this._columnName)), this._duration, s.fade(this._fade[0], this._fade[1]));
};
return TimeSeries;
}());
export { TimeSeries };
export default TimeSeries;