Browse Source

feat: #2451 Allow pass the color of points in 'dot-color' mode of Graph3D (#2489)

* Allow pass the color of points in 'dot-color' mode of Graph3D explicitly - clear the source code and finalize
* Add an onclick callback in Graph3D, to enable click and display customer user-defined information for single data point
* Extra data type validation for string conversion functions in Setings
* Disable onclick callback immediately after rotate/pan
* Re-format the JavaScript file
* No onclick event set by user - properly treat this case now
* Further reformat - indentation
* Handle the case where there is no closest data point
readme-improvements
Ephraim Berkovitch 7 years ago
committed by Alexander Wunschik
parent
commit
d9cdcb82f1
3 changed files with 80 additions and 37 deletions
  1. +6
    -2
      examples/graph3d/07_dot_cloud_colors.html
  2. +69
    -34
      lib/graph3d/Graph3d.js
  3. +5
    -1
      lib/graph3d/Settings.js

+ 6
- 2
examples/graph3d/07_dot_cloud_colors.html View File

@ -13,6 +13,9 @@
var data = null;
var graph = null;
function onclick(point) {
console.log(point);
}
// Called when the Visualization API is loaded.
function drawVisualization() {
@ -30,9 +33,9 @@
var x = pow(random(), 2);
var y = pow(random(), 2);
var z = pow(random(), 2);
var dist = sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2));
var style = (i%2==0) ? sqrt(pow(x, 2) + pow(y, 2) + pow(z, 2)) : "#00ffff";
data.add({x:x,y:y,z:z,style:dist});
data.add({x:x,y:y,z:z,style:style});
}
// specify options
@ -45,6 +48,7 @@
keepAspectRatio: true,
verticalRatio: 1.0,
legendLabel: 'distance',
onclick: onclick,
cameraPosition: {
horizontal: -0.35,
vertical: 0.22,

+ 69
- 34
lib/graph3d/Graph3d.js View File

@ -693,6 +693,7 @@ Graph3d.prototype.create = function () {
var ontouchstart = function (event) {me._onTouchStart(event);};
var onmousewheel = function (event) {me._onWheel(event);};
var ontooltip = function (event) {me._onTooltip(event);};
var onclick = function(event) {me._onClick(event);};
// TODO: these events are never cleaned up... can give a 'memory leakage'
util.addEventListener(this.frame.canvas, 'keydown', onkeydown);
@ -700,6 +701,7 @@ Graph3d.prototype.create = function () {
util.addEventListener(this.frame.canvas, 'touchstart', ontouchstart);
util.addEventListener(this.frame.canvas, 'mousewheel', onmousewheel);
util.addEventListener(this.frame.canvas, 'mousemove', ontooltip);
util.addEventListener(this.frame.canvas, 'click', onclick);
// add the new graph to the container element
this.containerElement.appendChild(this.frame);
@ -956,52 +958,52 @@ Graph3d.prototype._dotSize = function() {
/**
* Get legend width
* Get legend width
*/
Graph3d.prototype._getLegendWidth = function() {
var width;
var width;
if (this.style === Graph3d.STYLE.DOTSIZE) {
var dotSize = this._dotSize();
width = dotSize / 2 + dotSize * 2;
width = dotSize / 2 + dotSize * 2;
} else if (this.style === Graph3d.STYLE.BARSIZE) {
width = this.xBarWidth ;
} else {
width = 20;
width = 20;
}
return width;
}
/**
* Redraw the legend based on size, dot color, or surface height
* Redraw the legend based on size, dot color, or surface height
*/
Graph3d.prototype._redrawLegend = function() {
//Return without drawing anything, if no legend is specified
//Return without drawing anything, if no legend is specified
if (this.showLegend !== true) {
return;
}
}
// Do not draw legend when graph style does not support
if (this.style === Graph3d.STYLE.LINE
|| this.style === Graph3d.STYLE.BARSIZE //TODO add legend support for BARSIZE
|| this.style === Graph3d.STYLE.BARSIZE //TODO add legend support for BARSIZE
){
return;
}
}
// Legend types - size and color. Determine if size legend.
var isSizeLegend = (this.style === Graph3d.STYLE.BARSIZE
// Legend types - size and color. Determine if size legend.
var isSizeLegend = (this.style === Graph3d.STYLE.BARSIZE
|| this.style === Graph3d.STYLE.DOTSIZE) ;
// Legend is either tracking z values or style values. This flag if false means use z values.
var isValueLegend = (this.style === Graph3d.STYLE.DOTSIZE
|| this.style === Graph3d.STYLE.DOTCOLOR
// Legend is either tracking z values or style values. This flag if false means use z values.
var isValueLegend = (this.style === Graph3d.STYLE.DOTSIZE
|| this.style === Graph3d.STYLE.DOTCOLOR
|| this.style === Graph3d.STYLE.BARCOLOR);
var height = Math.max(this.frame.clientHeight * 0.25, 100);
var top = this.margin;
var width = this._getLegendWidth() ; // px - overwritten by size legend
var width = this._getLegendWidth() ; // px - overwritten by size legend
var right = this.frame.clientWidth - this.margin;
var left = right - width;
var bottom = top + height;
@ -1031,14 +1033,14 @@ Graph3d.prototype._redrawLegend = function() {
ctx.strokeRect(left, top, width, height);
} else {
// draw the size legend box
// draw the size legend box
var widthMin;
if (this.style === Graph3d.STYLE.DOTSIZE) {
if (this.style === Graph3d.STYLE.DOTSIZE) {
var dotSize = this._dotSize();
widthMin = dotSize / 2; // px
} else if (this.style === Graph3d.STYLE.BARSIZE) {
//widthMin = this.xBarWidth * 0.2 this is wrong - barwidth measures in terms of xvalues
} else if (this.style === Graph3d.STYLE.BARSIZE) {
//widthMin = this.xBarWidth * 0.2 this is wrong - barwidth measures in terms of xvalues
}
ctx.strokeStyle = this.axisColor;
ctx.fillStyle = this.dataColor.fill;
@ -1052,10 +1054,10 @@ Graph3d.prototype._redrawLegend = function() {
ctx.stroke();
}
// print value text along the legend edge
// print value text along the legend edge
var gridLineLen = 5; // px
var legendMin = isValueLegend ? this.valueRange.min : this.zRange.min;
var legendMin = isValueLegend ? this.valueRange.min : this.zRange.min;
var legendMax = isValueLegend ? this.valueRange.max : this.zRange.max;
var step = new StepNumber(legendMin, legendMax, (legendMax-legendMin)/5, true);
step.start(true);
@ -1330,7 +1332,7 @@ Graph3d.prototype._redrawAxis = function() {
xText = (armVector.y > 0) ? xRange.min : xRange.max;
point3d = new Point3d(xText, y, zRange.min);
var msg = ' ' + this.yValueLabel(y) + ' ';
var msg = ' ' + this.yValueLabel(y) + ' ';
this.drawAxisLabelY(ctx, point3d, msg, armAngle, textMargin);
step.next();
@ -1550,7 +1552,7 @@ Graph3d.prototype._redrawBar = function(ctx, point, xWidth, yWidth, color, borde
/**
* Draw a polygon using the passed points and fill it with the passed style and stroke.
*
* @param points an array of points.
* @param points an array of points.
* @param fillStyle optional; the fill style to set
* @param strokeStyle optional; the stroke style to set
*/
@ -1614,16 +1616,28 @@ Graph3d.prototype._getColorsRegular = function(point) {
/**
* Get the colors for the 'color' graph styles.
* These styles are currently: 'bar-color' and 'dot-color'
* Color may be set as a string representation of HTML color, like #ff00ff,
* or calculated from a number, for example, distance from this point
* The first option is useful when we have some pre-given legend, to which we have to adjust ourselves
* The second option is useful when we are interested in automatically setting the color, from some value,
* using some color scale
*/
Graph3d.prototype._getColorsColor = function(point) {
// calculate the color based on the value
var hue = (1 - (point.point.value - this.valueRange.min) * this.scale.value) * 240;
var color = this._hsv2rgb(hue, 1, 1);
var borderColor = this._hsv2rgb(hue, 1, 0.8);
var color, borderColor;
if (typeof point.point.value === "string") {
color = point.point.value;
borderColor = point.point.value;
}
else {
var hue = (1 - (point.point.value - this.valueRange.min) * this.scale.value) * 240;
color = this._hsv2rgb(hue, 1, 1);
borderColor = this._hsv2rgb(hue, 1, 0.8);
}
return {
fill : color,
border : borderColor
border : borderColor
};
};
@ -1897,7 +1911,7 @@ Graph3d.prototype._storeMousePosition = function(event) {
// get mouse position (different code for IE and all other browsers)
this.startMouseX = getMouseX(event);
this.startMouseY = getMouseY(event);
this._startCameraOffset = this.camera.getOffset();
};
@ -1946,12 +1960,13 @@ Graph3d.prototype._onMouseDown = function(event) {
* @param {Event} event Well, eehh, the event
*/
Graph3d.prototype._onMouseMove = function (event) {
this.moving = true;
event = event || window.event;
// calculate change in mouse position
var diffX = parseFloat(getMouseX(event)) - this.startMouseX;
var diffY = parseFloat(getMouseY(event)) - this.startMouseY;
// move with ctrl or rotate by other
if (event && event.ctrlKey === true) {
// calculate change in mouse position
@ -1960,7 +1975,7 @@ Graph3d.prototype._onMouseMove = function (event) {
var offXNew = (this._startCameraOffset.x || 0) - ((diffX / scaleX) * this.camera.armLength) * 0.8;
var offYNew = (this._startCameraOffset.y || 0) + ((diffY / scaleY) * this.camera.armLength) * 0.8;
this.camera.setOffset(offXNew, offYNew);
this._storeMousePosition(event);
} else {
@ -2014,6 +2029,26 @@ Graph3d.prototype._onMouseUp = function (event) {
util.preventDefault(event);
};
/**
* @param {event} event The event
*/
Graph3d.prototype._onClick = function (event) {
if (!this.onclick_callback)
return;
if (!this.moving) {
var boundingRect = this.frame.getBoundingClientRect();
var mouseX = getMouseX(event) - boundingRect.left;
var mouseY = getMouseY(event) - boundingRect.top;
var dataPoint = this._dataPointFromXY(mouseX, mouseY);
if (dataPoint)
this.onclick_callback(dataPoint.point.data);
}
else { // disable onclick callback, if it came immediately after rotate/pan
this.moving = false;
}
util.preventDefault(event);
};
/**
* After having moved the mouse, a tooltip should pop up when the mouse is resting on a data point
* @param {Event} event A mouse move event
@ -2403,4 +2438,4 @@ Graph3d.prototype.setSize = function(width, height) {
// -----------------------------------------------------------------------------
module.exports = Graph3d;
module.exports = Graph3d;

+ 5
- 1
lib/graph3d/Settings.js View File

@ -119,7 +119,7 @@ function isEmpty(obj) {
* Source: http://stackoverflow.com/a/1026087
*/
function capitalize(str) {
if (str === undefined || str === "") {
if (str === undefined || str === "" || typeof str != "string") {
return str;
}
@ -221,6 +221,7 @@ function setDefaults(src, dst) {
dst.margin = 10; // px
dst.showGrayBottom = false; // TODO: this does not work correctly
dst.showTooltip = false;
dst.onclick_callback = null;
dst.eye = new Point3d(0, 0, -1); // TODO: set eye.z about 3/4 of the width of the window?
}
@ -267,6 +268,9 @@ function setSpecialSettings(src, dst) {
if (src.tooltip !== undefined) {
dst.showTooltip = src.tooltip;
}
if (src.onclick != undefined) {
dst.onclick_callback = src.onclick;
}
}

Loading…
Cancel
Save