添加项目文件。
This commit is contained in:
@ -0,0 +1,382 @@
|
||||
/* *
|
||||
*
|
||||
* (c) 2009-2018 Øystein Moseng
|
||||
*
|
||||
* Code for sonifying single points.
|
||||
*
|
||||
* License: www.highcharts.com/license
|
||||
*
|
||||
* */
|
||||
|
||||
|
||||
/**
|
||||
* Define the parameter mapping for an instrument.
|
||||
*
|
||||
* @requires module:modules/sonification
|
||||
*
|
||||
* @interface Highcharts.PointInstrumentMappingObject
|
||||
*//**
|
||||
* Define the volume of the instrument. This can be a string with a data
|
||||
* property name, e.g. `'y'`, in which case this data property is used to define
|
||||
* the volume relative to the `y`-values of the other points. A higher `y` value
|
||||
* would then result in a higher volume. This option can also be a fixed number
|
||||
* or a function. If it is a function, this function is called in regular
|
||||
* intervals while the note is playing. It receives three arguments: The point,
|
||||
* the dataExtremes, and the current relative time - where 0 is the beginning of
|
||||
* the note and 1 is the end. The function should return the volume of the note
|
||||
* as a number between 0 and 1.
|
||||
* @name Highcharts.PointInstrumentMappingObject#volume
|
||||
* @type {string|number|Function}
|
||||
*//**
|
||||
* Define the duration of the notes for this instrument. This can be a string
|
||||
* with a data property name, e.g. `'y'`, in which case this data property is
|
||||
* used to define the duration relative to the `y`-values of the other points. A
|
||||
* higher `y` value would then result in a longer duration. This option can also
|
||||
* be a fixed number or a function. If it is a function, this function is called
|
||||
* once before the note starts playing, and should return the duration in
|
||||
* milliseconds. It receives two arguments: The point, and the dataExtremes.
|
||||
* @name Highcharts.PointInstrumentMappingObject#duration
|
||||
* @type {string|number|Function}
|
||||
*//**
|
||||
* Define the panning of the instrument. This can be a string with a data
|
||||
* property name, e.g. `'x'`, in which case this data property is used to define
|
||||
* the panning relative to the `x`-values of the other points. A higher `x`
|
||||
* value would then result in a higher panning value (panned further to the
|
||||
* right). This option can also be a fixed number or a function. If it is a
|
||||
* function, this function is called in regular intervals while the note is
|
||||
* playing. It receives three arguments: The point, the dataExtremes, and the
|
||||
* current relative time - where 0 is the beginning of the note and 1 is the
|
||||
* end. The function should return the panning of the note as a number between
|
||||
* -1 and 1.
|
||||
* @name Highcharts.PointInstrumentMappingObject#pan
|
||||
* @type {string|number|Function|undefined}
|
||||
*//**
|
||||
* Define the frequency of the instrument. This can be a string with a data
|
||||
* property name, e.g. `'y'`, in which case this data property is used to define
|
||||
* the frequency relative to the `y`-values of the other points. A higher `y`
|
||||
* value would then result in a higher frequency. This option can also be a
|
||||
* fixed number or a function. If it is a function, this function is called in
|
||||
* regular intervals while the note is playing. It receives three arguments:
|
||||
* The point, the dataExtremes, and the current relative time - where 0 is the
|
||||
* beginning of the note and 1 is the end. The function should return the
|
||||
* frequency of the note as a number (in Hz).
|
||||
* @name Highcharts.PointInstrumentMappingObject#frequency
|
||||
* @type {string|number|Function}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @requires module:modules/sonification
|
||||
*
|
||||
* @interface Highcharts.PointInstrumentOptionsObject
|
||||
*//**
|
||||
* The minimum duration for a note when using a data property for duration. Can
|
||||
* be overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.duration. Defaults to 20.
|
||||
* @name Highcharts.PointInstrumentOptionsObject#minDuration
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The maximum duration for a note when using a data property for duration. Can
|
||||
* be overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.duration. Defaults to 2000.
|
||||
* @name Highcharts.PointInstrumentOptionsObject#maxDuration
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The minimum pan value for a note when using a data property for panning. Can
|
||||
* be overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.pan. Defaults to -1 (fully left).
|
||||
* @name Highcharts.PointInstrumentOptionsObject#minPan
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The maximum pan value for a note when using a data property for panning. Can
|
||||
* be overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.pan. Defaults to 1 (fully right).
|
||||
* @name Highcharts.PointInstrumentOptionsObject#maxPan
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The minimum volume for a note when using a data property for volume. Can be
|
||||
* overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.volume. Defaults to 0.1.
|
||||
* @name Highcharts.PointInstrumentOptionsObject#minVolume
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The maximum volume for a note when using a data property for volume. Can be
|
||||
* overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.volume. Defaults to 1.
|
||||
* @name Highcharts.PointInstrumentOptionsObject#maxVolume
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The minimum frequency for a note when using a data property for frequency.
|
||||
* Can be overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.frequency. Defaults to 220.
|
||||
* @name Highcharts.PointInstrumentOptionsObject#minFrequency
|
||||
* @type {number|undefined}
|
||||
*//**
|
||||
* The maximum frequency for a note when using a data property for frequency.
|
||||
* Can be overridden by using either a fixed number or a function for
|
||||
* instrumentMapping.frequency. Defaults to 2200.
|
||||
* @name Highcharts.PointInstrumentOptionsObject#maxFrequency
|
||||
* @type {number|undefined}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* An instrument definition for a point, specifying the instrument to play and
|
||||
* how to play it.
|
||||
*
|
||||
* @interface Highcharts.PointInstrumentObject
|
||||
*//**
|
||||
* An Instrument instance or the name of the instrument in the
|
||||
* Highcharts.sonification.instruments map.
|
||||
* @name Highcharts.PointInstrumentObject#instrument
|
||||
* @type {Highcharts.Instrument|string}
|
||||
*//**
|
||||
* Mapping of instrument parameters for this instrument.
|
||||
* @name Highcharts.PointInstrumentObject#instrumentMapping
|
||||
* @type {Highcharts.PointInstrumentMappingObject}
|
||||
*//**
|
||||
* Options for this instrument.
|
||||
* @name Highcharts.PointInstrumentObject#instrumentOptions
|
||||
* @type {Highcharts.PointInstrumentOptionsObject|undefined}
|
||||
*//**
|
||||
* Callback to call when the instrument has stopped playing.
|
||||
* @name Highcharts.PointInstrumentObject#onEnd
|
||||
* @type {Function|undefined}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Options for sonifying a point.
|
||||
* @interface Highcharts.PointSonifyOptionsObject
|
||||
*//**
|
||||
* The instrument definitions for this point.
|
||||
* @name Highcharts.PointSonifyOptionsObject#instruments
|
||||
* @type {Array<Highcharts.PointInstrumentObject>}
|
||||
*//**
|
||||
* Optionally provide the minimum/maximum values for the points. If this is not
|
||||
* supplied, it is calculated from the points in the chart on demand. This
|
||||
* option is supplied in the following format, as a map of point data properties
|
||||
* to objects with min/max values:
|
||||
* ```js
|
||||
* dataExtremes: {
|
||||
* y: {
|
||||
* min: 0,
|
||||
* max: 100
|
||||
* },
|
||||
* z: {
|
||||
* min: -10,
|
||||
* max: 10
|
||||
* }
|
||||
* // Properties used and not provided are calculated on demand
|
||||
* }
|
||||
* ```
|
||||
* @name Highcharts.PointSonifyOptionsObject#dataExtremes
|
||||
* @type {object|undefined}
|
||||
*//**
|
||||
* Callback called when the sonification has finished.
|
||||
* @name Highcharts.PointSonifyOptionsObject#onEnd
|
||||
* @type {Function|undefined}
|
||||
*/
|
||||
|
||||
|
||||
'use strict';
|
||||
|
||||
import H from '../../parts/Globals.js';
|
||||
import utilities from 'utilities.js';
|
||||
|
||||
// Defaults for the instrument options
|
||||
// NOTE: Also change defaults in Highcharts.PointInstrumentOptionsObject if
|
||||
// making changes here.
|
||||
var defaultInstrumentOptions = {
|
||||
minDuration: 20,
|
||||
maxDuration: 2000,
|
||||
minVolume: 0.1,
|
||||
maxVolume: 1,
|
||||
minPan: -1,
|
||||
maxPan: 1,
|
||||
minFrequency: 220,
|
||||
maxFrequency: 2200
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Sonify a single point.
|
||||
*
|
||||
* @sample highcharts/sonification/point-basic/
|
||||
* Click on points to sonify
|
||||
* @sample highcharts/sonification/point-advanced/
|
||||
* Sonify bubbles
|
||||
*
|
||||
* @requires module:modules/sonification
|
||||
*
|
||||
* @function Highcharts.Point#sonify
|
||||
*
|
||||
* @param {Highcharts.PointSonifyOptionsObject} options
|
||||
* Options for the sonification of the point.
|
||||
*/
|
||||
function pointSonify(options) {
|
||||
var point = this,
|
||||
chart = point.series.chart,
|
||||
dataExtremes = options.dataExtremes || {},
|
||||
// Get the value to pass to instrument.play from the mapping value
|
||||
// passed in.
|
||||
getMappingValue = function (
|
||||
value, makeFunction, allowedExtremes, allowedValues
|
||||
) {
|
||||
// Fixed number, just use that
|
||||
if (typeof value === 'number' || value === undefined) {
|
||||
return value;
|
||||
}
|
||||
// Function. Return new function if we try to use callback,
|
||||
// otherwise call it now and return result.
|
||||
if (typeof value === 'function') {
|
||||
return makeFunction ?
|
||||
function (time) {
|
||||
return value(point, dataExtremes, time);
|
||||
} :
|
||||
value(point, dataExtremes);
|
||||
}
|
||||
// String, this is a data prop.
|
||||
if (typeof value === 'string') {
|
||||
// Find data extremes if we don't have them
|
||||
dataExtremes[value] = dataExtremes[value] ||
|
||||
utilities.calculateDataExtremes(
|
||||
point.series.chart, value
|
||||
);
|
||||
// Find the value
|
||||
return utilities.virtualAxisTranslate(
|
||||
H.pick(point[value], point.options[value]),
|
||||
dataExtremes[value],
|
||||
allowedExtremes,
|
||||
allowedValues
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
// Register playing point on chart
|
||||
chart.sonification.currentlyPlayingPoint = point;
|
||||
|
||||
// Keep track of instruments playing
|
||||
point.sonification = point.sonification || {};
|
||||
point.sonification.instrumentsPlaying =
|
||||
point.sonification.instrumentsPlaying || {};
|
||||
|
||||
// Register signal handler for the point
|
||||
var signalHandler = point.sonification.signalHandler =
|
||||
point.sonification.signalHandler ||
|
||||
new utilities.SignalHandler(['onEnd']);
|
||||
signalHandler.clearSignalCallbacks();
|
||||
signalHandler.registerSignalCallbacks({ onEnd: options.onEnd });
|
||||
|
||||
// If we have a null point or invisible point, just return
|
||||
if (point.isNull || !point.visible || !point.series.visible) {
|
||||
signalHandler.emitSignal('onEnd');
|
||||
return;
|
||||
}
|
||||
|
||||
// Go through instruments and play them
|
||||
options.instruments.forEach(function (instrumentDefinition) {
|
||||
var instrument = typeof instrumentDefinition.instrument === 'string' ?
|
||||
H.sonification.instruments[instrumentDefinition.instrument] :
|
||||
instrumentDefinition.instrument,
|
||||
mapping = instrumentDefinition.instrumentMapping || {},
|
||||
extremes = H.merge(
|
||||
defaultInstrumentOptions,
|
||||
instrumentDefinition.instrumentOptions
|
||||
),
|
||||
id = instrument.id,
|
||||
onEnd = function (cancelled) {
|
||||
// Instrument on end
|
||||
if (instrumentDefinition.onEnd) {
|
||||
instrumentDefinition.onEnd.apply(this, arguments);
|
||||
}
|
||||
|
||||
// Remove currently playing point reference on chart
|
||||
if (
|
||||
chart.sonification &&
|
||||
chart.sonification.currentlyPlayingPoint
|
||||
) {
|
||||
delete chart.sonification.currentlyPlayingPoint;
|
||||
}
|
||||
|
||||
// Remove reference from instruments playing
|
||||
if (
|
||||
point.sonification && point.sonification.instrumentsPlaying
|
||||
) {
|
||||
delete point.sonification.instrumentsPlaying[id];
|
||||
|
||||
// This was the last instrument?
|
||||
if (
|
||||
!Object.keys(
|
||||
point.sonification.instrumentsPlaying
|
||||
).length
|
||||
) {
|
||||
signalHandler.emitSignal('onEnd', cancelled);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Play the note on the instrument
|
||||
if (instrument && instrument.play) {
|
||||
point.sonification.instrumentsPlaying[instrument.id] = instrument;
|
||||
instrument.play({
|
||||
frequency: getMappingValue(
|
||||
mapping.frequency,
|
||||
true,
|
||||
{ min: extremes.minFrequency, max: extremes.maxFrequency }
|
||||
),
|
||||
duration: getMappingValue(
|
||||
mapping.duration,
|
||||
false,
|
||||
{ min: extremes.minDuration, max: extremes.maxDuration }
|
||||
),
|
||||
pan: getMappingValue(
|
||||
mapping.pan,
|
||||
true,
|
||||
{ min: extremes.minPan, max: extremes.maxPan }
|
||||
),
|
||||
volume: getMappingValue(
|
||||
mapping.volume,
|
||||
true,
|
||||
{ min: extremes.minVolume, max: extremes.maxVolume }
|
||||
),
|
||||
onEnd: onEnd,
|
||||
minFrequency: extremes.minFrequency,
|
||||
maxFrequency: extremes.maxFrequency
|
||||
});
|
||||
} else {
|
||||
H.error(30);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Cancel sonification of a point. Calls onEnd functions.
|
||||
*
|
||||
* @requires module:modules/sonification
|
||||
*
|
||||
* @function Highcharts.Point#cancelSonify
|
||||
*
|
||||
* @param {boolean} [fadeOut=false]
|
||||
* Whether or not to fade out as we stop. If false, the points are
|
||||
* cancelled synchronously.
|
||||
*/
|
||||
function pointCancelSonify(fadeOut) {
|
||||
var playing = this.sonification && this.sonification.instrumentsPlaying,
|
||||
instrIds = playing && Object.keys(playing);
|
||||
if (instrIds && instrIds.length) {
|
||||
instrIds.forEach(function (instr) {
|
||||
playing[instr].stop(!fadeOut, null, 'cancelled');
|
||||
});
|
||||
this.sonification.instrumentsPlaying = {};
|
||||
this.sonification.signalHandler.emitSignal('onEnd', 'cancelled');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var pointSonifyFunctions = {
|
||||
pointSonify: pointSonify,
|
||||
pointCancelSonify: pointCancelSonify
|
||||
};
|
||||
export default pointSonifyFunctions;
|
Reference in New Issue
Block a user