osh-js
Version:
OSH javascript Toolkit
236 lines (231 loc) • 10.5 kB
JavaScript
/***************************** BEGIN LICENSE BLOCK ***************************
The contents of this file are subject to the Mozilla Public License, v. 2.0.
If a copy of the MPL was not distributed with this file, You can obtain one
at http://mozilla.org/MPL/2.0/.
Software distributed under the License is distributed on an "AS IS" basis,
WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
for the specific language governing rights and limitations under the License.
Copyright (C) 2020 Ian Patterson. All Rights Reserved.
Author: Ian Patterson <cr31.dev@gmail.com>
******************************* END LICENSE BLOCK ***************************/
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
if (ar || !(i in from)) {
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
ar[i] = from[i];
}
}
return to.concat(ar || Array.prototype.slice.call(from));
};
import View from '../../../../core/ui/view/View.js';
import * as d3 from 'd3/dist/d3.js';
/**
* @extends View
*/
var SpectrogramView = /** @class */ (function (_super) {
__extends(SpectrogramView, _super);
/**
*
* @param {Object} [properties={}] - the properties of the view
* * @param {String} properties.isSim - Enable simulation mode
*/
function SpectrogramView(properties) {
var _this = _super.call(this, __assign(__assign({ supportedLayers: ['data'], dataSourceId: properties.dataSource.id }, properties), { visible: true })) || this;
// Data Vars
_this.spectrogramData = [];
_this.powerRange = [-80, 250];
_this.minDate = Date.now();
_this.maxDate = Date.now() + 60000;
_this.freqUnit = 'Hz';
_this.minFreq = 0;
_this.maxFreq = 4000;
_this.numBands = 10;
_this.maxDataPoints = 1000;
_this.isSim = false;
_this.tickArray = [];
for (var i = 0; i <= _this.numBands; i++) {
var interval = (_this.maxFreq - _this.minFreq) / _this.numBands;
var tickVal = i * interval;
_this.tickArray.push(tickVal);
}
// Layout Vars
var thisDiv = document.getElementById(_this.divId);
thisDiv.style.height = thisDiv.parentElement.getBoundingClientRect().height + 'px';
// this.width = thisDiv.getBoundingClientRect().width;
// this.height = thisDiv.getBoundingClientRect().height;
_this.width = 500;
_this.height = 350;
_this.xOffset = (0.10 * _this.width);
_this.yOffset = (0.90 * _this.height);
_this.yOffsetBottom = 10;
// Draw Spectrogram
// The div that will be the root of the D3JS Chart
_this.container = d3.select('#' + _this.divId);
_this.width = parseInt(_this.container.style('width'), 10);
_this.height = parseInt(_this.container.style('height'), 10);
_this.aspect = _this.width / _this.height;
_this.svg = _this.container.append('svg')
.classed('spec-svg', true)
.attr("viewBox", "0 0 ".concat(_this.width, " ").concat(_this.height))
.attr('preserveAspectRatio', 'xMinYMid')
.call(_this.makeResponsive);
// Setup Scales
_this.initXScale = d3.scaleTime()
.domain([_this.minDate, _this.maxDate])
.range([_this.xOffset, _this.width - 100]);
_this.initXAxis = d3.axisBottom(_this.initXScale);
_this.initYScale = d3.scaleLinear()
.domain([_this.minFreq, _this.maxFreq])
.range([_this.yOffset, _this.yOffsetBottom]); // TODO: name {bottomOffset} something better
// this.initYAxis = d3.axisLeft(this.initYScale).ticks(this.numBands).tickFormat((d, i) => d + this.freqUnit);
_this.initYAxis = d3.axisLeft(_this.initYScale).tickValues(_this.tickArray).tickFormat(function (d, i) { return d + _this.freqUnit; });
_this.initZScale = d3.scaleSequential(d3.interpolateOrRd).domain(_this.powerRange);
// Add Axes to Chart
_this.xBar = _this.svg.append('g')
.attr('class', ' x axis')
.attr('transform', 'translate(' + (0) + ',' + (_this.yOffset) + ')')
.call(_this.initXAxis);
_this.yBar = _this.svg.append('g')
.attr('class', 'y axis')
.attr('transform', 'translate(' + (_this.xOffset) + ',' + (0) + ')')
.call(_this.initYAxis);
if (properties.hasOwnProperty('isSim')) {
_this.isSim = properties.isSim;
}
if (_this.isSim) {
console.info("Simulating Spectrogram");
setInterval(function () {
// this.spectrogramData = this.spectrogramData.concat(this.createDataEntries());
_this.spectrogramData = __spreadArray(__spreadArray([], _this.spectrogramData, true), _this.createDataEntries(), true);
_this.draw();
}, 1000);
}
return _this;
}
SpectrogramView.prototype.setData = function (dataSourceId, data) {
var values = data.values;
for (var i = 0; i < values.length; i++) {
var d = values[i];
if (data.type === 'spectrogram') {
this.updateSpectrogram(d);
}
}
};
/**
* Updates the spectrogram data and redraw.
* @param {Spectogram.props} props - The layer properties allowing the update of the spectrogram
*/
SpectrogramView.prototype.updateSpectrogram = function (data) {
// push layer data into Spectrogram Data Object
if (layer !== null)
this.spectrogramData.push(layer.latestData);
// redraw
this.draw();
};
/**
* Draws the spectrogram
*/
SpectrogramView.prototype.draw = function () {
var _this = this;
// check for dataset size
if (this.spectrogramData.length > this.maxDataPoints) {
var pointsToCull = this.spectrogramData.length - this.maxDataPoints;
this.spectrogramData = this.spectrogramData.slice(pointsToCull, this.spectrogramData.length);
}
this.minDate = this.spectrogramData[0].time;
this.maxDate = Date.now();
var tempXScale = d3
.scaleTime()
.domain([this.minDate, this.maxDate])
.range([this.xOffset, this.width]);
var newXAxis = d3.axisBottom(tempXScale).ticks(10);
this.xBar = this.svg.select('g.x.axis')
.call(newXAxis);
var bandwidth = 10 * this.width / this.spectrogramData.length;
this.svg.selectAll('rect')
.data(this.spectrogramData)
.join('rect')
.attr('width', bandwidth)
.attr('height', function (d) { return _this.initYScale(d.freqBand[0]) - _this.initYScale(d.freqBand[1]); })
.attr('x', function (d) { return tempXScale(d.time); })
.attr('y', function (d) { return _this.initYScale(d.freqBand[1]); })
.style('fill', function (d) { return _this.initZScale(d.power); });
};
/**
*
*/
SpectrogramView.prototype.createDataEntries = function () {
var tempDataArr = [];
var freqCounter = 0;
for (var i = 0; i < this.numBands; i++) {
var randomPower = Math.random() * (this.powerRange[1] - this.powerRange[0]) + this.powerRange[0];
tempDataArr.push({
time: Date.now(),
freqBand: [freqCounter, freqCounter + 400],
power: randomPower
});
freqCounter += 400;
}
console.log(tempDataArr);
return tempDataArr;
};
SpectrogramView.prototype.makeResponsive = function (svg) {
// container will be the DOM element
// that the svg is appended to
// we then measure the container
// and find its aspect ratio
var container = d3.select(svg.node().parentNode), width = parseInt(svg.style('width'), 10), height = parseInt(svg.style('height'), 10), aspect = width / height;
// set viewBox attribute to the initial size
// control scaling with preserveAspectRatio
// resize svg on inital page load
svg.attr('viewBox', "0 0 ".concat(width, " ").concat(height))
.attr('preserveAspectRatio', 'xMinYMid')
.call(resize);
// add a listener so the chart will be resized
// when the window resizes
// multiple listeners for the same event type
// requires a namespace, i.e., 'click.foo'
// api docs: https://goo.gl/F3ZCFr
d3.select(window).on('resize.' + container.attr('id'), resize);
// this is the code that resizes the chart
// it will be called on load
// and in response to window resizes
// gets the width of the container
// and resizes the svg to fill it
// while maintaining a consistent aspect ratio
function resize() {
var w = parseInt(container.style('width'));
svg.attr('width', w - 5);
svg.attr('height', Math.round(w / aspect));
}
};
return SpectrogramView;
}(View));
export default SpectrogramView;
//# sourceMappingURL=SpectrogramView.js.map