Browse Source

Final cleanup for settings handling

codeClimate
Wim Rijnders 8 years ago
parent
commit
6fc876a0ed
1 changed files with 452 additions and 451 deletions
  1. +452
    -451
      lib/graph3d/Graph3d.js

+ 452
- 451
lib/graph3d/Graph3d.js View File

@ -8,9 +8,6 @@ var Filter = require('./Filter');
var Slider = require('./Slider'); var Slider = require('./Slider');
var StepNumber = require('./StepNumber'); var StepNumber = require('./StepNumber');
// -----------------------------------------------------------------------------
// Definitions private to module
// -----------------------------------------------------------------------------
/// enumerate the available styles /// enumerate the available styles
Graph3d.STYLE = { Graph3d.STYLE = {
@ -28,59 +25,14 @@ Graph3d.STYLE = {
/** /**
* Field names in the options hash which are of relevance to the user.
*
* Specifically, these are the fields which require no special handling,
* and can be directly copied over.
*/
var OPTIONKEYS = [
'width',
'height',
'filterLabel',
'legendLabel',
'xLabel',
'yLabel',
'zLabel',
'xValueLabel',
'yValueLabel',
'zValueLabel',
'showGrid',
'showPerspective',
'showShadow',
'keepAspectRatio',
'verticalRatio',
'showAnimationControls',
'animationInterval',
'animationPreload',
'animationAutoStart',
'axisColor',
'gridColor',
'xCenter',
'yCenter'
];
/**
* Field names in the options hash which are of relevance to the user.
*
* Same as OPTIONKEYS, but internally these fields are stored with
* prefix 'default' in the name.
* Following label is used in the settings to describe values which
* should be determined by the code while running, from the current
* data and graph style.
*
* Using 'undefined' directly achieves the same thing, but this is
* more descriptive by describing the intent.
*/ */
var PREFIXEDOPTIONKEYS = [
'xBarWidth',
'yBarWidth',
'valueMin',
'valueMax',
'xMin',
'xMax',
'xStep',
'yMin',
'yMax',
'yStep',
'zMin',
'zMax',
'zStep'
];
var autoByDefault = undefined;
/** /**
@ -89,15 +41,8 @@ var PREFIXEDOPTIONKEYS = [
* These are the values used when a Graph3d instance is initialized * These are the values used when a Graph3d instance is initialized
* without custom settings. * without custom settings.
* *
* If a field is not in this list, a default value of 'undefined' can
* be assumed. Of course, it does no harm to set a field explicitly to
* 'undefined' here.
*
* A value of 'undefined' here normally means:
*
* 'derive from current data and graph style'
*
* In the code, this is indicated by the comment 'auto by default'.
* If a field is not in this list, a default value of 'autoByDefault'
* is assumed, which is just an alias for 'undefined'.
*/ */
var DEFAULTS = { var DEFAULTS = {
width : '400px', width : '400px',
@ -114,29 +59,27 @@ var DEFAULTS = {
showPerspective : true, showPerspective : true,
showShadow : false, showShadow : false,
keepAspectRatio : true, keepAspectRatio : true,
verticalRatio : 0.5, // 0.1 to 1.0, where 1.0 results in a 'cube'
verticalRatio : 0.5, // 0.1 to 1.0, where 1.0 results in a 'cube'
showAnimationControls: undefined, // auto by default
animationInterval : 1000, // milliseconds
showAnimationControls: autoByDefault,
animationInterval : 1000, // milliseconds
animationPreload : false, animationPreload : false,
animationAutoStart : undefined, // auto by default
animationAutoStart : autoByDefault,
axisColor : '#4D4D4D', axisColor : '#4D4D4D',
gridColor : '#D3D3D3', gridColor : '#D3D3D3',
xCenter : '55%', xCenter : '55%',
yCenter : '50%', yCenter : '50%',
// Following require special handling, therefore not mentioned in the OPTIONKEYS tables.
style : Graph3d.STYLE.DOT, style : Graph3d.STYLE.DOT,
tooltip : false, tooltip : false,
showLegend : undefined, // auto by default (based on graph style)
backgroundColor : undefined,
showLegend : autoByDefault, // determined by graph style
backgroundColor : autoByDefault,
dataColor : { dataColor : {
fill : '#7DC1FF', fill : '#7DC1FF',
stroke : '#3267D2', stroke : '#3267D2',
strokeWidth: 1 // px
strokeWidth: 1 // px
}, },
cameraPosition : { cameraPosition : {
@ -145,102 +88,22 @@ var DEFAULTS = {
distance : 1.7 distance : 1.7
}, },
// Following stored internally with field prefix 'default'
// All these are 'auto by default'
xBarWidth : undefined,
yBarWidth : undefined,
valueMin : undefined,
valueMax : undefined,
xMin : undefined,
xMax : undefined,
xStep : undefined,
yMin : undefined,
yMax : undefined,
yStep : undefined,
zMin : undefined,
zMax : undefined,
zStep : undefined
xBarWidth : autoByDefault,
yBarWidth : autoByDefault,
valueMin : autoByDefault,
valueMax : autoByDefault,
xMin : autoByDefault,
xMax : autoByDefault,
xStep : autoByDefault,
yMin : autoByDefault,
yMax : autoByDefault,
yStep : autoByDefault,
zMin : autoByDefault,
zMax : autoByDefault,
zStep : autoByDefault
}; };
/**
* Make first letter of parameter upper case.
*
* Source: http://stackoverflow.com/a/1026087
*/
function capitalize(str) {
if (str === undefined || str === "") {
return str;
}
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* Add a prefix to a field name, taking style guide into account
*/
function prefixFieldName(prefix, fieldName) {
if (prefix === undefined || prefix === "") {
return fieldName;
}
return prefix + capitalize(fieldName);
}
/**
* Forcibly copy fields from src to dst in a controlled manner.
*
* A given field in dst will always be overwitten. If this field
* is undefined or not present in src, the field in dst will
* be explicitly set to undefined.
*
* The intention here is to be able to reset all option fields.
*
* Only the fields mentioned in array 'fields' will be handled.
*
* @param fields array with names of fields to copy
* @param prefix optional; prefix to use for the target fields.
*/
function forceCopy(src, dst, fields, prefix) {
var srcKey;
var dstKey;
for (var i in fields) {
srcKey = fields[i];
dstKey = prefixFieldName(prefix, srcKey);
dst[dstKey] = src[srcKey];
}
}
/**
* Copy fields from src to dst in a safe and controlled manner.
*
* Only the fields mentioned in array 'fields' will be copied over,
* and only if these are actually defined.
*
* @param fields array with names of fields to copy
* @param prefix optional; prefix to use for the target fields.
*/
function safeCopy(src, dst, fields, prefix) {
var srcKey;
var dstKey;
for (var i in fields) {
srcKey = fields[i];
if (src[srcKey] === undefined) continue;
dstKey = prefixFieldName(prefix, srcKey);
dst[dstKey] = src[srcKey];
}
}
// ----------------------------------------------------------------------------- // -----------------------------------------------------------------------------
// Class Graph3d // Class Graph3d
@ -272,27 +135,7 @@ function Graph3d(container, data, options) {
// create a frame and canvas // create a frame and canvas
this.create(); this.create();
//
// Set Defaults
//
// Handle the defaults which can be simply copied over
forceCopy(DEFAULTS, this, OPTIONKEYS);
forceCopy(DEFAULTS, this, PREFIXEDOPTIONKEYS, 'default');
// Following are internal fields, not part of the user settings
this.margin = 10; // px
this.showGrayBottom = false; // TODO: this does not work correctly
this.showTooltip = false;
this.dotSizeRatio = 0.02; // size of the dots as a fraction of the graph width
this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window?
// Handle the more complex ('special') fields
this._setSpecialSettings(DEFAULTS, this);
//
// End Set Defaults
//
this._setDefaults();
// the column indexes // the column indexes
this.colX = undefined; this.colX = undefined;
@ -459,278 +302,87 @@ Graph3d.prototype._calcTranslations = function(points, sort) {
}; };
// -----------------------------------------------------------------------------
// Methods for handling settings
// -----------------------------------------------------------------------------
/** /**
* Special handling for certain parameters
*
* 'Special' here means: setting requires more than a simple copy
* Retrieve the style index from given styleName
* @param {string} styleName Style name such as 'dot', 'grid', 'dot-line'
* @return {Number} styleNumber Enumeration value representing the style, or -1
* when not found
*/ */
Graph3d.prototype._setSpecialSettings = function(src, dst) {
if (src.backgroundColor !== undefined) {
this._setBackgroundColor(src.backgroundColor, dst);
Graph3d.prototype._getStyleNumber = function(styleName) {
switch (styleName) {
case 'dot': return Graph3d.STYLE.DOT;
case 'dot-line': return Graph3d.STYLE.DOTLINE;
case 'dot-color': return Graph3d.STYLE.DOTCOLOR;
case 'dot-size': return Graph3d.STYLE.DOTSIZE;
case 'line': return Graph3d.STYLE.LINE;
case 'grid': return Graph3d.STYLE.GRID;
case 'surface': return Graph3d.STYLE.SURFACE;
case 'bar': return Graph3d.STYLE.BAR;
case 'bar-color': return Graph3d.STYLE.BARCOLOR;
case 'bar-size': return Graph3d.STYLE.BARSIZE;
} }
this._setDataColor(src.dataColor, dst);
this._setStyle(src.style, dst);
this._setShowLegend(src.showLegend, dst);
this._setCameraPosition(src.cameraPosition, dst);
// As special fields go, this is an easy one; just a translation of the name.
// Can't use this.tooltip directly, because that field exists internally
if (src.tooltip !== undefined) {
dst.showTooltip = src.tooltip;
}
return -1;
}; };
/** /**
* Set the value of setting 'showLegend'
*
* This depends on the value of the style fields, so it must be called
* after the style field has been initialized.
* Determine the indexes of the data columns, based on the given style and data
* @param {DataSet} data
* @param {Number} style
*/ */
Graph3d.prototype._setShowLegend = function(showLegend, dst) {
if (showLegend === undefined) {
// If the default was auto, make a choice for this field
var isAutoByDefault = (DEFAULTS.showLegend === undefined);
Graph3d.prototype._determineColumnIndexes = function(data, style) {
if (this.style === Graph3d.STYLE.DOT ||
this.style === Graph3d.STYLE.DOTLINE ||
this.style === Graph3d.STYLE.LINE ||
this.style === Graph3d.STYLE.GRID ||
this.style === Graph3d.STYLE.SURFACE ||
this.style === Graph3d.STYLE.BAR) {
// 3 columns expected, and optionally a 4th with filter values
this.colX = 0;
this.colY = 1;
this.colZ = 2;
this.colValue = undefined;
if (isAutoByDefault) {
// these styles default to having legends
var isLegendGraphStyle = this.style === Graph3d.STYLE.DOTCOLOR
|| this.style === Graph3d.STYLE.DOTSIZE;
if (data.getNumberOfColumns() > 3) {
this.colFilter = 3;
}
}
else if (this.style === Graph3d.STYLE.DOTCOLOR ||
this.style === Graph3d.STYLE.DOTSIZE ||
this.style === Graph3d.STYLE.BARCOLOR ||
this.style === Graph3d.STYLE.BARSIZE) {
// 4 columns expected, and optionally a 5th with filter values
this.colX = 0;
this.colY = 1;
this.colZ = 2;
this.colValue = 3;
this.showLegend = isLegendGraphStyle;
} else {
// Leave current value as is
if (data.getNumberOfColumns() > 4) {
this.colFilter = 4;
} }
} else {
dst.showLegend = showLegend;
}
else {
throw new Error('Unknown style "' + this.style + '"');
} }
}; };
Graph3d.prototype.getNumberOfRows = function(data) {
return data.length;
}
Graph3d.prototype._setStyle = function(style, dst) {
if (style === undefined) {
return; // Nothing to do
Graph3d.prototype.getNumberOfColumns = function(data) {
var counter = 0;
for (var column in data[0]) {
if (data[0].hasOwnProperty(column)) {
counter++;
}
} }
var styleNumber;
if (typeof style === 'string') {
styleNumber = this._getStyleNumber(style);
if (styleNumber === -1 ) {
throw new Error('Style \'' + style + '\' is invalid');
}
} else {
// Do a pedantic check on style number value
var valid = false;
for (var n in Graph3d.STYLE) {
if (Graph3d.STYLE[n] === style) {
valid = true;
break;
}
}
if (!valid) {
throw new Error('Style \'' + style + '\' is invalid');
}
styleNumber = style;
}
dst.style = styleNumber;
};
/**
* Set the background styling for the graph
* @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor
*/
Graph3d.prototype._setBackgroundColor = function(backgroundColor, dst) {
var fill = 'white';
var stroke = 'gray';
var strokeWidth = 1;
if (typeof(backgroundColor) === 'string') {
fill = backgroundColor;
stroke = 'none';
strokeWidth = 0;
}
else if (typeof(backgroundColor) === 'object') {
if (backgroundColor.fill !== undefined) fill = backgroundColor.fill;
if (backgroundColor.stroke !== undefined) stroke = backgroundColor.stroke;
if (backgroundColor.strokeWidth !== undefined) strokeWidth = backgroundColor.strokeWidth;
}
else {
throw new Error('Unsupported type of backgroundColor');
}
dst.frame.style.backgroundColor = fill;
dst.frame.style.borderColor = stroke;
dst.frame.style.borderWidth = strokeWidth + 'px';
dst.frame.style.borderStyle = 'solid';
};
Graph3d.prototype._setDataColor = function(dataColor, dst) {
if (dataColor === undefined) {
return; // Nothing to do
}
if (dst.dataColor === undefined) {
dst.dataColor = {};
}
if (typeof dataColor === 'string') {
dst.dataColor.fill = dataColor;
dst.dataColor.stroke = dataColor;
}
else {
if (dataColor.fill) {
dst.dataColor.fill = dataColor.fill;
}
if (dataColor.stroke) {
dst.dataColor.stroke = dataColor.stroke;
}
if (dataColor.strokeWidth !== undefined) {
dst.dataColor.strokeWidth = dataColor.strokeWidth;
}
}
};
Graph3d.prototype._setCameraPosition = function(cameraPosition, dst) {
var camPos = cameraPosition;
if (camPos === undefined) {
return;
}
if (dst.camera === undefined) {
dst.camera = new Camera();
}
dst.camera.setArmRotation(camPos.horizontal, camPos.vertical);
dst.camera.setArmLength(camPos.distance);
};
//
// Public methods for specific settings
//
/**
* Set the rotation and distance of the camera
* @param {Object} pos An object with the camera position. The object
* contains three parameters:
* - horizontal {Number}
* The horizontal rotation, between 0 and 2*PI.
* Optional, can be left undefined.
* - vertical {Number}
* The vertical rotation, between 0 and 0.5*PI
* if vertical=0.5*PI, the graph is shown from the
* top. Optional, can be left undefined.
* - distance {Number}
* The (normalized) distance of the camera to the
* center of the graph, a value between 0.71 and 5.0.
* Optional, can be left undefined.
*/
Graph3d.prototype.setCameraPosition = function(pos) {
this._setCameraPosition(pos, this);
this.redraw();
};
// -----------------------------------------------------------------------------
// End methods for handling settings
// -----------------------------------------------------------------------------
/**
* Retrieve the style index from given styleName
* @param {string} styleName Style name such as 'dot', 'grid', 'dot-line'
* @return {Number} styleNumber Enumeration value representing the style, or -1
* when not found
*/
Graph3d.prototype._getStyleNumber = function(styleName) {
switch (styleName) {
case 'dot': return Graph3d.STYLE.DOT;
case 'dot-line': return Graph3d.STYLE.DOTLINE;
case 'dot-color': return Graph3d.STYLE.DOTCOLOR;
case 'dot-size': return Graph3d.STYLE.DOTSIZE;
case 'line': return Graph3d.STYLE.LINE;
case 'grid': return Graph3d.STYLE.GRID;
case 'surface': return Graph3d.STYLE.SURFACE;
case 'bar': return Graph3d.STYLE.BAR;
case 'bar-color': return Graph3d.STYLE.BARCOLOR;
case 'bar-size': return Graph3d.STYLE.BARSIZE;
}
return -1;
};
/**
* Determine the indexes of the data columns, based on the given style and data
* @param {DataSet} data
* @param {Number} style
*/
Graph3d.prototype._determineColumnIndexes = function(data, style) {
if (this.style === Graph3d.STYLE.DOT ||
this.style === Graph3d.STYLE.DOTLINE ||
this.style === Graph3d.STYLE.LINE ||
this.style === Graph3d.STYLE.GRID ||
this.style === Graph3d.STYLE.SURFACE ||
this.style === Graph3d.STYLE.BAR) {
// 3 columns expected, and optionally a 4th with filter values
this.colX = 0;
this.colY = 1;
this.colZ = 2;
this.colValue = undefined;
if (data.getNumberOfColumns() > 3) {
this.colFilter = 3;
}
}
else if (this.style === Graph3d.STYLE.DOTCOLOR ||
this.style === Graph3d.STYLE.DOTSIZE ||
this.style === Graph3d.STYLE.BARCOLOR ||
this.style === Graph3d.STYLE.BARSIZE) {
// 4 columns expected, and optionally a 5th with filter values
this.colX = 0;
this.colY = 1;
this.colZ = 2;
this.colValue = 3;
if (data.getNumberOfColumns() > 4) {
this.colFilter = 4;
}
}
else {
throw new Error('Unknown style "' + this.style + '"');
}
};
Graph3d.prototype.getNumberOfRows = function(data) {
return data.length;
}
Graph3d.prototype.getNumberOfColumns = function(data) {
var counter = 0;
for (var column in data[0]) {
if (data[0].hasOwnProperty(column)) {
counter++;
}
}
return counter;
}
return counter;
}
Graph3d.prototype.getDistinctValues = function(data, column) { Graph3d.prototype.getDistinctValues = function(data, column) {
@ -1203,16 +855,7 @@ Graph3d.prototype.setOptions = function (options) {
this.animationStop(); this.animationStop();
if (options !== undefined) {
// retrieve parameter values
// Handle the parameters which can be simply copied over
safeCopy(options, this, OPTIONKEYS);
safeCopy(options, this, PREFIXEDOPTIONKEYS, 'default');
// Handle the more complex ('special') fields
this._setSpecialSettings(options, this);
}
this._setOptions(options);
this.setSize(this.width, this.height); this.setSize(this.width, this.height);
@ -2571,4 +2214,362 @@ function getMouseY (event) {
return event.targetTouches[0] && event.targetTouches[0].clientY || 0; return event.targetTouches[0] && event.targetTouches[0].clientY || 0;
} }
// -----------------------------------------------------------------------------
// Methods for handling settings
// -----------------------------------------------------------------------------
/**
* Field names in the options hash which are of relevance to the user.
*
* Specifically, these are the fields which require no special handling,
* and can be directly copied over.
*/
var OPTIONKEYS = [
'width',
'height',
'filterLabel',
'legendLabel',
'xLabel',
'yLabel',
'zLabel',
'xValueLabel',
'yValueLabel',
'zValueLabel',
'showGrid',
'showPerspective',
'showShadow',
'keepAspectRatio',
'verticalRatio',
'showAnimationControls',
'animationInterval',
'animationPreload',
'animationAutoStart',
'axisColor',
'gridColor',
'xCenter',
'yCenter'
];
/**
* Field names in the options hash which are of relevance to the user.
*
* Same as OPTIONKEYS, but internally these fields are stored with
* prefix 'default' in the name.
*/
var PREFIXEDOPTIONKEYS = [
'xBarWidth',
'yBarWidth',
'valueMin',
'valueMax',
'xMin',
'xMax',
'xStep',
'yMin',
'yMax',
'yStep',
'zMin',
'zMax',
'zStep'
];
/**
* Make first letter of parameter upper case.
*
* Source: http://stackoverflow.com/a/1026087
*/
function capitalize(str) {
if (str === undefined || str === "") {
return str;
}
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* Add a prefix to a field name, taking style guide into account
*/
function prefixFieldName(prefix, fieldName) {
if (prefix === undefined || prefix === "") {
return fieldName;
}
return prefix + capitalize(fieldName);
}
/**
* Forcibly copy fields from src to dst in a controlled manner.
*
* A given field in dst will always be overwitten. If this field
* is undefined or not present in src, the field in dst will
* be explicitly set to undefined.
*
* The intention here is to be able to reset all option fields.
*
* Only the fields mentioned in array 'fields' will be handled.
*
* @param fields array with names of fields to copy
* @param prefix optional; prefix to use for the target fields.
*/
function forceCopy(src, dst, fields, prefix) {
var srcKey;
var dstKey;
for (var i in fields) {
srcKey = fields[i];
dstKey = prefixFieldName(prefix, srcKey);
dst[dstKey] = src[srcKey];
}
}
/**
* Copy fields from src to dst in a safe and controlled manner.
*
* Only the fields mentioned in array 'fields' will be copied over,
* and only if these are actually defined.
*
* @param fields array with names of fields to copy
* @param prefix optional; prefix to use for the target fields.
*/
function safeCopy(src, dst, fields, prefix) {
var srcKey;
var dstKey;
for (var i in fields) {
srcKey = fields[i];
if (src[srcKey] === undefined) continue;
dstKey = prefixFieldName(prefix, srcKey);
dst[dstKey] = src[srcKey];
}
}
Graph3d.prototype._setDefaults = function() {
// Handle the defaults which can be simply copied over
forceCopy(DEFAULTS, this, OPTIONKEYS);
forceCopy(DEFAULTS, this, PREFIXEDOPTIONKEYS, 'default');
// Handle the more complex ('special') fields
this._setSpecialSettings(DEFAULTS, this);
// Following are internal fields, not part of the user settings
this.margin = 10; // px
this.showGrayBottom = false; // TODO: this does not work correctly
this.showTooltip = false;
this.dotSizeRatio = 0.02; // size of the dots as a fraction of the graph width
this.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window?
};
Graph3d.prototype._setOptions = function(options) {
if (options === undefined) {
return;
}
// Handle the parameters which can be simply copied over
safeCopy(options, this, OPTIONKEYS);
safeCopy(options, this, PREFIXEDOPTIONKEYS, 'default');
// Handle the more complex ('special') fields
this._setSpecialSettings(options, this);
};
/**
* Special handling for certain parameters
*
* 'Special' here means: setting requires more than a simple copy
*/
Graph3d.prototype._setSpecialSettings = function(src, dst) {
if (src.backgroundColor !== undefined) {
this._setBackgroundColor(src.backgroundColor, dst);
}
this._setDataColor(src.dataColor, dst);
this._setStyle(src.style, dst);
this._setShowLegend(src.showLegend, dst);
this._setCameraPosition(src.cameraPosition, dst);
// As special fields go, this is an easy one; just a translation of the name.
// Can't use this.tooltip directly, because that field exists internally
if (src.tooltip !== undefined) {
dst.showTooltip = src.tooltip;
}
};
/**
* Set the value of setting 'showLegend'
*
* This depends on the value of the style fields, so it must be called
* after the style field has been initialized.
*/
Graph3d.prototype._setShowLegend = function(showLegend, dst) {
if (showLegend === undefined) {
// If the default was auto, make a choice for this field
var isAutoByDefault = (DEFAULTS.showLegend === undefined);
if (isAutoByDefault) {
// these styles default to having legends
var isLegendGraphStyle = this.style === Graph3d.STYLE.DOTCOLOR
|| this.style === Graph3d.STYLE.DOTSIZE;
this.showLegend = isLegendGraphStyle;
} else {
// Leave current value as is
}
} else {
dst.showLegend = showLegend;
}
};
Graph3d.prototype._setStyle = function(style, dst) {
if (style === undefined) {
return; // Nothing to do
}
var styleNumber;
if (typeof style === 'string') {
styleNumber = this._getStyleNumber(style);
if (styleNumber === -1 ) {
throw new Error('Style \'' + style + '\' is invalid');
}
} else {
// Do a pedantic check on style number value
var valid = false;
for (var n in Graph3d.STYLE) {
if (Graph3d.STYLE[n] === style) {
valid = true;
break;
}
}
if (!valid) {
throw new Error('Style \'' + style + '\' is invalid');
}
styleNumber = style;
}
dst.style = styleNumber;
};
/**
* Set the background styling for the graph
* @param {string | {fill: string, stroke: string, strokeWidth: string}} backgroundColor
*/
Graph3d.prototype._setBackgroundColor = function(backgroundColor, dst) {
var fill = 'white';
var stroke = 'gray';
var strokeWidth = 1;
if (typeof(backgroundColor) === 'string') {
fill = backgroundColor;
stroke = 'none';
strokeWidth = 0;
}
else if (typeof(backgroundColor) === 'object') {
if (backgroundColor.fill !== undefined) fill = backgroundColor.fill;
if (backgroundColor.stroke !== undefined) stroke = backgroundColor.stroke;
if (backgroundColor.strokeWidth !== undefined) strokeWidth = backgroundColor.strokeWidth;
}
else {
throw new Error('Unsupported type of backgroundColor');
}
dst.frame.style.backgroundColor = fill;
dst.frame.style.borderColor = stroke;
dst.frame.style.borderWidth = strokeWidth + 'px';
dst.frame.style.borderStyle = 'solid';
};
Graph3d.prototype._setDataColor = function(dataColor, dst) {
if (dataColor === undefined) {
return; // Nothing to do
}
if (dst.dataColor === undefined) {
dst.dataColor = {};
}
if (typeof dataColor === 'string') {
dst.dataColor.fill = dataColor;
dst.dataColor.stroke = dataColor;
}
else {
if (dataColor.fill) {
dst.dataColor.fill = dataColor.fill;
}
if (dataColor.stroke) {
dst.dataColor.stroke = dataColor.stroke;
}
if (dataColor.strokeWidth !== undefined) {
dst.dataColor.strokeWidth = dataColor.strokeWidth;
}
}
};
Graph3d.prototype._setCameraPosition = function(cameraPosition, dst) {
var camPos = cameraPosition;
if (camPos === undefined) {
return;
}
if (dst.camera === undefined) {
dst.camera = new Camera();
}
dst.camera.setArmRotation(camPos.horizontal, camPos.vertical);
dst.camera.setArmLength(camPos.distance);
};
//
// Public methods for specific settings
//
/**
* Set the rotation and distance of the camera
* @param {Object} pos An object with the camera position. The object
* contains three parameters:
* - horizontal {Number}
* The horizontal rotation, between 0 and 2*PI.
* Optional, can be left undefined.
* - vertical {Number}
* The vertical rotation, between 0 and 0.5*PI
* if vertical=0.5*PI, the graph is shown from the
* top. Optional, can be left undefined.
* - distance {Number}
* The (normalized) distance of the camera to the
* center of the graph, a value between 0.71 and 5.0.
* Optional, can be left undefined.
*/
Graph3d.prototype.setCameraPosition = function(pos) {
this._setCameraPosition(pos, this);
this.redraw();
};
// -----------------------------------------------------------------------------
// End methods for handling settings
// -----------------------------------------------------------------------------
module.exports = Graph3d; module.exports = Graph3d;

Loading…
Cancel
Save