Browse Source

icons for left and right axis

css_transitions
Alex de Mulder 10 years ago
parent
commit
4620f53df6
9 changed files with 410 additions and 221 deletions
  1. +6
    -2
      dist/vis.css
  2. +196
    -106
      dist/vis.js
  3. +7
    -6
      examples/Graph2d/01_basic.html
  4. +92
    -81
      src/timeline/component/DataAxis.js
  5. +39
    -1
      src/timeline/component/GraphGroup.js
  6. +58
    -15
      src/timeline/component/Linegraph.js
  7. +2
    -2
      src/timeline/component/css/dataaxis.css
  8. +4
    -0
      src/timeline/component/css/pathStyles.css
  9. +6
    -8
      src/timeline/component/legend.js

+ 6
- 2
dist/vis.css View File

@ -341,7 +341,7 @@
.vis.timeline .dataaxis .yAxis.major {
font-size:10px;
font-size:12px;
width: 100%;
position: absolute;
color: #4d4d4d;
@ -350,7 +350,7 @@
.vis.timeline .dataaxis .yAxis.minor{
font-size:10px;
font-size:12px;
position: absolute;
width: 100%;
color: #979797;
@ -453,6 +453,10 @@
stroke: #e5e5e5;
}
.vis.timeline .iconFill {
fill-opacity:0.3;
stroke: none;
}

+ 196
- 106
dist/vis.js View File

@ -5,7 +5,7 @@
* A dynamic, browser-based visualization library.
*
* @version 1.1.0
* @date 2014-06-18
* @date 2014-06-19
*
* @license
* Copyright (C) 2011-2014 Almende B.V, http://almende.com
@ -2581,7 +2581,7 @@ GraphGroup.prototype.setClass = function (className) {
GraphGroup.prototype.setOptions = function(options) {
if (options !== undefined) {
var fields = ['yAxisOrientation'];
util.selectiveExtend(fields, options, this.options);
util.selectiveExtend(fields, this.options, options);
this.linegraph._mergeOptions(this.options, options,'catmullRom');
this.linegraph._mergeOptions(this.options, options,'drawPoints');
this.linegraph._mergeOptions(this.options, options,'shaded');
@ -2595,6 +2595,44 @@ GraphGroup.prototype.update = function(group) {
this.setOptions(group.options);
};
GraphGroup.prototype.drawIcon = function(x,y,JSONcontainer, SVGcontainer, lineLength, iconHeight) {
var fillHeight = iconHeight * 0.5;
var path, fillPath, outline;
if (this.options.barGraph.enabled == false) {
outline = this.linegraph._getSVGElement("rect", JSONcontainer, SVGcontainer);
outline.setAttributeNS(null, "x", x);
outline.setAttributeNS(null, "y", y - fillHeight);
outline.setAttributeNS(null, "width", lineLength);
outline.setAttributeNS(null, "height", 2*fillHeight);
outline.setAttributeNS(null, "class", "outline");
path = this.linegraph._getSVGElement("path", JSONcontainer, SVGcontainer);
path.setAttributeNS(null, "class", this.className);
path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + lineLength) + ","+y+"");
if (this.options.shaded.enabled == true) {
fillPath = this.linegraph._getSVGElement("path", JSONcontainer, SVGcontainer);
if (this.options.shaded.orientation == 'top') {
fillPath.setAttributeNS(null, "d", "M"+x+", " + (y - fillHeight) +
"L"+x+","+y+" L"+ (x + lineLength) + ","+y+" L"+ (x + lineLength) + "," + (y - fillHeight));
}
else {
fillPath.setAttributeNS(null, "d", "M"+x+","+y+" " +
"L"+x+"," + (y + fillHeight) + " " +
"L"+ (x + lineLength) + "," + (y + fillHeight) +
"L"+ (x + lineLength) + ","+y);
}
fillPath.setAttributeNS(null, "class", this.className + " iconFill");
}
if (this.options.drawPoints.enabled == true) {
this.linegraph.drawPoint(x + 0.5 * lineLength,y, this, JSONcontainer, SVGcontainer);
}
}
else {
//TODO: bars
}
}
/**
* Created by Alex on 6/17/14.
*/
@ -2610,7 +2648,7 @@ function Legend(body, options, linegraph) {
this.svgElements = {};
this.dom = {};
this.classes;
this.graphs = {};
this.groups = {};
this.setOptions(options);
this.create();
@ -2620,20 +2658,18 @@ Legend.prototype = new Component();
Legend.prototype.addGroup = function(label, graphOptions) {
if (!this.graphs.hasOwnProperty(label)) {
this.graphs[label] = graphOptions;
this.redraw();
if (!this.groups.hasOwnProperty(label)) {
this.groups[label] = graphOptions;
}
};
Legend.prototype.updateGroup = function(label, graphOptions) {
this.graphs[label] = graphOptions;
this.groups[label] = graphOptions;
};
Legend.prototype.deleteGroup = function(label) {
if (this.graphs.hasOwnProperty(label)) {
delete this.graphs[label];
this.redraw();
if (this.groups.hasOwnProperty(label)) {
delete this.groups[label];
}
};
@ -2763,26 +2799,24 @@ function DataAxis (body, options) {
this.body = body;
this.defaultOptions = {
orientation: 'left', // supported: 'left'
orientation: 'left', // supported: 'left', 'right'
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 25,
minorLinesOffset: 25,
width: '50px',
majorLinesOffset: 7,
minorLinesOffset: 4,
labelOffsetX: 9,
labelOffsetY: -6,
width: '60px',
height: '300px'
};
this.props = {};
this.dom = {
majorLines: [],
majorTexts: [],
minorLines: [],
minorTexts: [],
lines: [],
labels: [],
redundant: {
majorLines: [],
majorTexts: [],
minorLines: [],
minorTexts: []
lines: [],
labels: []
}
};
@ -2799,6 +2833,10 @@ function DataAxis (body, options) {
this.stepPixelsForced = 25;
this.lineOffset = 0;
this.master = true;
this.svgElements = {};
this.drawIcons = false;
this.groups = {};
// create the HTML DOM
this._create();
@ -2806,6 +2844,25 @@ function DataAxis (body, options) {
DataAxis.prototype = new Component();
DataAxis.prototype.addGroup = function(label, graphOptions) {
if (!this.groups.hasOwnProperty(label)) {
this.groups[label] = graphOptions;
}
};
DataAxis.prototype.updateGroup = function(label, graphOptions) {
this.groups[label] = graphOptions;
};
DataAxis.prototype.deleteGroup = function(label) {
if (this.groups.hasOwnProperty(label)) {
delete this.groups[label];
}
};
DataAxis.prototype.setOptions = function(options) {
if (options) {
var redraw = false;
@ -2834,8 +2891,38 @@ DataAxis.prototype._create = function() {
this.dom.lineContainer = document.createElement('div');
this.dom.lineContainer.style.width = '100%';
this.dom.lineContainer.style.height = this.options.height;
// create svg element for graph drawing.
this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
this.svg.style.position = "absolute";
this.svg.style.top = '0px';
this.svg.style.height = '100%';
this.svg.style.width = '100%';
this.svg.style.display = "block";
this.dom.frame.appendChild(this.svg);
};
DataAxis.prototype._redrawGroupIcons = function() {
var x;
var iconWidth = 20;
var iconHeight = 15;
var iconOffset = 4;
var y = iconOffset + 0.5 * iconHeight;
if (this.options.orientation == 'left') {
x = iconOffset;
}
else {
x = this.width - iconWidth - iconOffset;
}
for (var groupId in this.groups) {
if (this.groups.hasOwnProperty(groupId)) {
this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight);
y += iconHeight + iconOffset;
}
}
}
/**
* Create the HTML DOM for the DataAxis
@ -2924,6 +3011,9 @@ DataAxis.prototype.redraw = function () {
}
this._redrawLabels();
if (this.drawIcons == true) {
this._redrawGroupIcons();
}
};
/**
@ -2944,14 +3034,10 @@ DataAxis.prototype._redrawLabels = function () {
// can be picked for re-use, and clear the lists with lines and texts.
// At the end of the function _redrawLabels, left over elements will be cleaned up
var dom = this.dom;
dom.redundant.majorLines = dom.majorLines;
dom.redundant.majorTexts = dom.majorTexts;
dom.redundant.minorLines = dom.minorLines;
dom.redundant.minorTexts = dom.minorTexts;
dom.majorLines = [];
dom.majorTexts = [];
dom.minorLines = [];
dom.minorTexts = [];
dom.redundant.lines = dom.lines;
dom.redundant.labels = dom.labels;
dom.lines = [];
dom.labels = [];
step.first();
var stepPixels = this.dom.frame.offsetHeight / ((step.marginRange / step.step) + 1);
@ -2972,7 +3058,11 @@ DataAxis.prototype._redrawLabels = function () {
var xFirstMajorLabel = undefined;
this.valueAtZero = step.marginEnd;
var marginStartPos = 0;
var max = 0;
// do not draw the first label
var max = 1;
step.next();
var y = 0;
while (max < amountOfSteps) {
y = Math.round(max * stepPixels);
@ -2980,7 +3070,7 @@ DataAxis.prototype._redrawLabels = function () {
var isMajor = step.isMajor();
if (this.options['showMinorLabels'] && isMajor == false) {
this._redrawMinorText(y - 2, step.getLabelMinor(), orientation);
this._redrawLabel(y - 2, step.getLabelMinor(), orientation, 'yAxis minor');
}
if (isMajor && this.options['showMajorLabels']) {
@ -2988,7 +3078,7 @@ DataAxis.prototype._redrawLabels = function () {
if (xFirstMajorLabel == undefined) {
xFirstMajorLabel = y;
}
this._redrawMajorText(y - 2, step.getLabelMajor(), orientation);
this._redrawLabel(y - 2, step.getLabelMajor(), orientation, 'yAxis major');
}
this._redrawMajorLine(y, orientation);
}
@ -3002,17 +3092,6 @@ DataAxis.prototype._redrawLabels = function () {
this.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step);
// create a major label on the left when needed
if (this.options['showMajorLabels']) {
var leftPoint = this._start;
var leftText = step.getLabelMajor(leftPoint);
var widthText = leftText.length * (this.props.majorCharWidth || 10) + 10; // upper bound estimation
if (xFirstMajorLabel == undefined || widthText < xFirstMajorLabel) {
this._redrawMajorText(0, leftText, orientation);
}
}
// Cleanup leftover DOM elements from the redundant list
util.forEach(this.dom.redundant, function (arr) {
while (arr.length) {
@ -3037,76 +3116,42 @@ DataAxis.prototype.convertValue = function(value) {
return convertedValue; // the -2 is to compensate for the borders
}
/**
* Create a minor label for the axis at position x
* @param {Number} x
* @param {String} text
* @param {String} orientation "top" or "bottom" (default)
* @private
*/
DataAxis.prototype._redrawMinorText = function (y, text, orientation) {
// reuse redundant label
var label = this.dom.redundant.minorTexts.shift();
if (!label) {
// create new label
var content = document.createTextNode('');
label = document.createElement('div');
label.appendChild(content);
label.className = 'yAxis minor';
this.dom.frame.appendChild(label);
}
this.dom.minorTexts.push(label);
label.childNodes[0].nodeValue = text;
if (orientation == 'left') {
label.style.left = '-2px';
label.style.textAlign = "right";
}
else {
label.style.left = '2px';
label.style.textAlign = "left";
}
label.style.top = y + 'px';
//label.title = title; // TODO: this is a heavy operation
};
/**
* Create a Major label for the axis at position x
* Create a label for the axis at position x
* @param {Number} x
* @param {String} text
* @param {String} orientation "top" or "bottom" (default)
* @private
*/
DataAxis.prototype._redrawMajorText = function (y, text, orientation) {
DataAxis.prototype._redrawLabel = function (y, text, orientation, className) {
// reuse redundant label
var label = this.dom.redundant.majorTexts.shift();
var label = this.dom.redundant.labels.shift();
if (!label) {
// create label
var content = document.createTextNode(text);
label = document.createElement('div');
label.className = 'yAxis major';
label.className = className;
label.appendChild(content);
this.dom.frame.appendChild(label);
}
this.dom.majorTexts.push(label);
this.dom.labels.push(label);
label.childNodes[0].nodeValue = text;
//label.title = title; // TODO: this is a heavy operation
if (orientation == 'left') {
label.style.left = '-2px';
label.style.left = '-' + this.options.labelOffsetX + 'px';
label.style.textAlign = "right";
}
else {
label.style.left = '2px';
label.style.left = this.options.labelOffsetX + 'px';
label.style.textAlign = "left";
}
label.style.top = y + 'px';
label.style.top = y + this.options.labelOffsetY + 'px';
};
/**
@ -3118,7 +3163,7 @@ DataAxis.prototype._redrawMajorText = function (y, text, orientation) {
DataAxis.prototype._redrawMinorLine = function (y, orientation) {
if (this.master == true) {
// reuse redundant line
var line = this.dom.redundant.minorLines.shift();
var line = this.dom.redundant.lines.shift();
if (!line) {
// create vertical line
@ -3126,7 +3171,7 @@ DataAxis.prototype._redrawMinorLine = function (y, orientation) {
line.className = 'grid horizontal minor';
this.dom.lineContainer.appendChild(line);
}
this.dom.minorLines.push(line);
this.dom.lines.push(line);
var props = this.props;
if (orientation == 'left') {
@ -3150,7 +3195,7 @@ DataAxis.prototype._redrawMinorLine = function (y, orientation) {
DataAxis.prototype._redrawMajorLine = function (y, orientation) {
if (this.master == true) {
// reuse redundant line
var line = this.dom.redundant.majorLines.shift();
var line = this.dom.redundant.lines.shift();
if (!line) {
// create vertical line
@ -3158,13 +3203,13 @@ DataAxis.prototype._redrawMajorLine = function (y, orientation) {
line.className = 'grid horizontal major';
this.dom.lineContainer.appendChild(line);
}
this.dom.majorLines.push(line);
this.dom.lines.push(line);
if (orientation == 'left') {
line.style.left = (this.width - this.options.majorLinesOffset) + 'px';
}
else {
line.style.left = -1*(this.width - this.options.mayorLinesOffset) + 'px';
line.style.left = -1*(this.width - this.options.majorLinesOffset) + 'px';
}
line.style.top = y + 'px';
line.style.width = this.props.majorLineWidth + 'px';
@ -3216,6 +3261,8 @@ DataAxis.prototype.snap = function(date) {
return this.step.snap(date);
};
var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items
function Linegraph(body, options) {
@ -3229,7 +3276,7 @@ function Linegraph(body, options) {
orientation: 'top' // top, bottom
},
barGraph: {
enabled: true,
enabled: false,
binSize: 'auto'
},
drawPoints: {
@ -3241,6 +3288,24 @@ function Linegraph(body, options) {
enabled: true,
parametrization: 'centripetal', // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5)
alpha: 0.5
},
dataAxis: {
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 27,
minorLinesOffset: 24,
labelOffsetX: 2,
labelOffsetY: 0,
width: '60px'
},
dataAxisRight: {
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 7,
minorLinesOffset: 4,
labelOffsetX: 9,
labelOffsetY: -6,
width: '60px'
}
};
@ -3335,21 +3400,11 @@ Linegraph.prototype._create = function(){
// panel with time axis
this.yAxisLeft = new DataAxis(this.body, {
orientation: 'left',
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 25,
minorLinesOffset: 25,
width: '50px',
height: this.svg.style.height
});
this.yAxisRight = new DataAxis(this.body, {
orientation: 'right',
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 25,
minorLinesOffset: 25,
width: '50px',
height: this.svg.style.height
});
@ -3547,13 +3602,24 @@ Linegraph.prototype._onUpdateGroups = function (groupIds) {
if (!this.groups.hasOwnProperty(groupIds[i])) {
this.groups[groupIds[i]] = new GraphGroup(group, this.options, this);
this.legend.addGroup(groupIds[i],this.groups[groupIds[i]]);
if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') {
this.yAxisRight.addGroup(groupIds[i], this.groups[groupIds[i]]);
}
else {
this.yAxisLeft.addGroup(groupIds[i], this.groups[groupIds[i]]);
}
}
else {
this.groups[groupIds[i]].update(group);
this.legend.updateGroup(groupIds[i],this.groups[groupIds[i]]);
if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') {
this.yAxisRight.updateGroup(groupIds[i], this.groups[groupIds[i]]);
}
else {
this.yAxisLeft.updateGroup(groupIds[i], this.groups[groupIds[i]]);
}
}
}
this.updateGraph();
this.redraw();
};
@ -3576,9 +3642,23 @@ Linegraph.prototype._updateUngrouped = function() {
var group = {content: "graph"};
if (!this.groups.hasOwnProperty(UNGROUPED)) {
this.groups[UNGROUPED] = new GraphGroup(group, this.options, this);
this.legend.addGroup(UNGROUPED,this.groups[UNGROUPED]);
if (this.groups[UNGROUPED].options.yAxisOrientation == 'right') {
this.yAxisRight.addGroup(UNGROUPED, this.groups[UNGROUPED]);
}
else {
this.yAxisLeft.addGroup(UNGROUPED, this.groups[UNGROUPED]);
}
}
else {
this.groups[UNGROUPED].update(group);
this.legend.updateGroup(UNGROUPED,this.groups[UNGROUPED]);
if (this.groups[UNGROUPED].options.yAxisOrientation == 'right') {
this.yAxisRight.updateGroup(UNGROUPED, this.groups[UNGROUPED]);
}
else {
this.yAxisLeft.updateGroup(UNGROUPED, this.groups[UNGROUPED]);
}
}
if (this.itemsData != null) {
@ -3598,6 +3678,8 @@ Linegraph.prototype._updateUngrouped = function() {
if (pointInUNGROUPED.length == 0) {
this.legend.deleteGroup(UNGROUPED);
delete this.groups[UNGROUPED];
this.yAxisLeft.yAxisRight(UNGROUPED);
this.yAxisLeft.deleteGroup(UNGROUPED);
}
}
};
@ -3713,6 +3795,15 @@ Linegraph.prototype._updateYAxis = function(groupIds) {
this.body.emitter.emit('change');
}
if (yAxisRightUsed == true && yAxisLeftUsed == true) {
this.yAxisLeft.drawIcons = true;
this.yAxisRight.drawIcons = true;
}
else {
this.yAxisLeft.drawIcons = false;
this.yAxisRight.drawIcons = false;
}
this.yAxisRight.master = !yAxisLeftUsed;
if (this.yAxisRight.master == false) {
@ -3767,7 +3858,7 @@ Linegraph.prototype.drawGraph = function (groupId, groupIndex, amountOfGraphs) {
// can be optimized, only has to be done once.
var group = this.groups[groupId];
if (this.options.style == 'bar') {
if (this.options.barGraph.enabled == 'true') {
this.drawBarGraph(datapoints, group, amountOfGraphs);
}
else {
@ -3787,7 +3878,6 @@ Linegraph.prototype.drawBarGraph = function (datapoints, group, amountOfGraphs)
var dataset = this._prepareData(datapoints);
// draw points
for (var i = 0; i < dataset.length; i++) {
this.drawBar(dataset[i].x, dataset[i].y, className);
}
}
@ -3888,7 +3978,7 @@ Linegraph.prototype.drawPoints = function (dataset, group, JSONcontainer, svg) {
*/
Linegraph.prototype.drawPoint = function(x, y, group, JSONcontainer, svgContainer) {
var point;
if (options.drawPoints.style == 'circle') {
if (group.options.drawPoints.style == 'circle') {
point = this._getSVGElement('circle',JSONcontainer,svgContainer);
point.setAttributeNS(null, "cx", x);
point.setAttributeNS(null, "cy", y);

+ 7
- 6
examples/Graph2d/01_basic.html View File

@ -63,6 +63,7 @@
content: names[2],
className: "graphGroup2",
options: {
// yAxisOrientation: 'right',
shaded: {
enabled: false,
orientation: 'top' // top, bottom
@ -71,12 +72,12 @@
var container = document.getElementById('visualization');
var items = [
{x: '2014-06-11', y: 10 },
{x: '2014-06-12', y: 25 },
{x: '2014-06-13', y: 30, group: 0},
{x: '2014-06-14', y: 10, group: 0},
{x: '2014-06-15', y: 150, group: 1},
{x: '2014-06-16', y: 300, group: 1},
{x: '2014-06-11', y: 10000 },
{x: '2014-06-12', y: 25000 },
{x: '2014-06-13', y: 30000, group: 0},
{x: '2014-06-14', y: 10000, group: 0},
{x: '2014-06-15', y: 150000, group: 1},
{x: '2014-06-16', y: 300000, group: 1},
{x: '2014-06-17', y: 100, group: 1},
{x: '2014-06-18', y: 150, group: 1},
{x: '2014-06-19', y: 520, group: 1},

+ 92
- 81
src/timeline/component/DataAxis.js View File

@ -10,26 +10,24 @@ function DataAxis (body, options) {
this.body = body;
this.defaultOptions = {
orientation: 'left', // supported: 'left'
orientation: 'left', // supported: 'left', 'right'
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 25,
minorLinesOffset: 25,
width: '50px',
majorLinesOffset: 7,
minorLinesOffset: 4,
labelOffsetX: 9,
labelOffsetY: -6,
width: '60px',
height: '300px'
};
this.props = {};
this.dom = {
majorLines: [],
majorTexts: [],
minorLines: [],
minorTexts: [],
lines: [],
labels: [],
redundant: {
majorLines: [],
majorTexts: [],
minorLines: [],
minorTexts: []
lines: [],
labels: []
}
};
@ -46,6 +44,10 @@ function DataAxis (body, options) {
this.stepPixelsForced = 25;
this.lineOffset = 0;
this.master = true;
this.svgElements = {};
this.drawIcons = false;
this.groups = {};
// create the HTML DOM
this._create();
@ -53,6 +55,25 @@ function DataAxis (body, options) {
DataAxis.prototype = new Component();
DataAxis.prototype.addGroup = function(label, graphOptions) {
if (!this.groups.hasOwnProperty(label)) {
this.groups[label] = graphOptions;
}
};
DataAxis.prototype.updateGroup = function(label, graphOptions) {
this.groups[label] = graphOptions;
};
DataAxis.prototype.deleteGroup = function(label) {
if (this.groups.hasOwnProperty(label)) {
delete this.groups[label];
}
};
DataAxis.prototype.setOptions = function(options) {
if (options) {
var redraw = false;
@ -81,8 +102,38 @@ DataAxis.prototype._create = function() {
this.dom.lineContainer = document.createElement('div');
this.dom.lineContainer.style.width = '100%';
this.dom.lineContainer.style.height = this.options.height;
// create svg element for graph drawing.
this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
this.svg.style.position = "absolute";
this.svg.style.top = '0px';
this.svg.style.height = '100%';
this.svg.style.width = '100%';
this.svg.style.display = "block";
this.dom.frame.appendChild(this.svg);
};
DataAxis.prototype._redrawGroupIcons = function() {
var x;
var iconWidth = 20;
var iconHeight = 15;
var iconOffset = 4;
var y = iconOffset + 0.5 * iconHeight;
if (this.options.orientation == 'left') {
x = iconOffset;
}
else {
x = this.width - iconWidth - iconOffset;
}
for (var groupId in this.groups) {
if (this.groups.hasOwnProperty(groupId)) {
this.groups[groupId].drawIcon(x, y, this.svgElements, this.svg, iconWidth, iconHeight);
y += iconHeight + iconOffset;
}
}
}
/**
* Create the HTML DOM for the DataAxis
@ -171,6 +222,9 @@ DataAxis.prototype.redraw = function () {
}
this._redrawLabels();
if (this.drawIcons == true) {
this._redrawGroupIcons();
}
};
/**
@ -191,14 +245,10 @@ DataAxis.prototype._redrawLabels = function () {
// can be picked for re-use, and clear the lists with lines and texts.
// At the end of the function _redrawLabels, left over elements will be cleaned up
var dom = this.dom;
dom.redundant.majorLines = dom.majorLines;
dom.redundant.majorTexts = dom.majorTexts;
dom.redundant.minorLines = dom.minorLines;
dom.redundant.minorTexts = dom.minorTexts;
dom.majorLines = [];
dom.majorTexts = [];
dom.minorLines = [];
dom.minorTexts = [];
dom.redundant.lines = dom.lines;
dom.redundant.labels = dom.labels;
dom.lines = [];
dom.labels = [];
step.first();
var stepPixels = this.dom.frame.offsetHeight / ((step.marginRange / step.step) + 1);
@ -219,7 +269,11 @@ DataAxis.prototype._redrawLabels = function () {
var xFirstMajorLabel = undefined;
this.valueAtZero = step.marginEnd;
var marginStartPos = 0;
var max = 0;
// do not draw the first label
var max = 1;
step.next();
var y = 0;
while (max < amountOfSteps) {
y = Math.round(max * stepPixels);
@ -227,7 +281,7 @@ DataAxis.prototype._redrawLabels = function () {
var isMajor = step.isMajor();
if (this.options['showMinorLabels'] && isMajor == false) {
this._redrawMinorText(y - 2, step.getLabelMinor(), orientation);
this._redrawLabel(y - 2, step.getLabelMinor(), orientation, 'yAxis minor');
}
if (isMajor && this.options['showMajorLabels']) {
@ -235,7 +289,7 @@ DataAxis.prototype._redrawLabels = function () {
if (xFirstMajorLabel == undefined) {
xFirstMajorLabel = y;
}
this._redrawMajorText(y - 2, step.getLabelMajor(), orientation);
this._redrawLabel(y - 2, step.getLabelMajor(), orientation, 'yAxis major');
}
this._redrawMajorLine(y, orientation);
}
@ -249,17 +303,6 @@ DataAxis.prototype._redrawLabels = function () {
this.conversionFactor = marginStartPos/((amountOfSteps-1) * step.step);
// create a major label on the left when needed
if (this.options['showMajorLabels']) {
var leftPoint = this._start;
var leftText = step.getLabelMajor(leftPoint);
var widthText = leftText.length * (this.props.majorCharWidth || 10) + 10; // upper bound estimation
if (xFirstMajorLabel == undefined || widthText < xFirstMajorLabel) {
this._redrawMajorText(0, leftText, orientation);
}
}
// Cleanup leftover DOM elements from the redundant list
util.forEach(this.dom.redundant, function (arr) {
while (arr.length) {
@ -284,76 +327,42 @@ DataAxis.prototype.convertValue = function(value) {
return convertedValue; // the -2 is to compensate for the borders
}
/**
* Create a minor label for the axis at position x
* @param {Number} x
* @param {String} text
* @param {String} orientation "top" or "bottom" (default)
* @private
*/
DataAxis.prototype._redrawMinorText = function (y, text, orientation) {
// reuse redundant label
var label = this.dom.redundant.minorTexts.shift();
if (!label) {
// create new label
var content = document.createTextNode('');
label = document.createElement('div');
label.appendChild(content);
label.className = 'yAxis minor';
this.dom.frame.appendChild(label);
}
this.dom.minorTexts.push(label);
label.childNodes[0].nodeValue = text;
if (orientation == 'left') {
label.style.left = '-2px';
label.style.textAlign = "right";
}
else {
label.style.left = '2px';
label.style.textAlign = "left";
}
label.style.top = y + 'px';
//label.title = title; // TODO: this is a heavy operation
};
/**
* Create a Major label for the axis at position x
* Create a label for the axis at position x
* @param {Number} x
* @param {String} text
* @param {String} orientation "top" or "bottom" (default)
* @private
*/
DataAxis.prototype._redrawMajorText = function (y, text, orientation) {
DataAxis.prototype._redrawLabel = function (y, text, orientation, className) {
// reuse redundant label
var label = this.dom.redundant.majorTexts.shift();
var label = this.dom.redundant.labels.shift();
if (!label) {
// create label
var content = document.createTextNode(text);
label = document.createElement('div');
label.className = 'yAxis major';
label.className = className;
label.appendChild(content);
this.dom.frame.appendChild(label);
}
this.dom.majorTexts.push(label);
this.dom.labels.push(label);
label.childNodes[0].nodeValue = text;
//label.title = title; // TODO: this is a heavy operation
if (orientation == 'left') {
label.style.left = '-2px';
label.style.left = '-' + this.options.labelOffsetX + 'px';
label.style.textAlign = "right";
}
else {
label.style.left = '2px';
label.style.left = this.options.labelOffsetX + 'px';
label.style.textAlign = "left";
}
label.style.top = y + 'px';
label.style.top = y + this.options.labelOffsetY + 'px';
};
/**
@ -365,7 +374,7 @@ DataAxis.prototype._redrawMajorText = function (y, text, orientation) {
DataAxis.prototype._redrawMinorLine = function (y, orientation) {
if (this.master == true) {
// reuse redundant line
var line = this.dom.redundant.minorLines.shift();
var line = this.dom.redundant.lines.shift();
if (!line) {
// create vertical line
@ -373,7 +382,7 @@ DataAxis.prototype._redrawMinorLine = function (y, orientation) {
line.className = 'grid horizontal minor';
this.dom.lineContainer.appendChild(line);
}
this.dom.minorLines.push(line);
this.dom.lines.push(line);
var props = this.props;
if (orientation == 'left') {
@ -397,7 +406,7 @@ DataAxis.prototype._redrawMinorLine = function (y, orientation) {
DataAxis.prototype._redrawMajorLine = function (y, orientation) {
if (this.master == true) {
// reuse redundant line
var line = this.dom.redundant.majorLines.shift();
var line = this.dom.redundant.lines.shift();
if (!line) {
// create vertical line
@ -405,13 +414,13 @@ DataAxis.prototype._redrawMajorLine = function (y, orientation) {
line.className = 'grid horizontal major';
this.dom.lineContainer.appendChild(line);
}
this.dom.majorLines.push(line);
this.dom.lines.push(line);
if (orientation == 'left') {
line.style.left = (this.width - this.options.majorLinesOffset) + 'px';
}
else {
line.style.left = -1*(this.width - this.options.mayorLinesOffset) + 'px';
line.style.left = -1*(this.width - this.options.majorLinesOffset) + 'px';
}
line.style.top = y + 'px';
line.style.width = this.props.majorLineWidth + 'px';
@ -462,3 +471,5 @@ DataAxis.prototype._calculateCharSize = function () {
DataAxis.prototype.snap = function(date) {
return this.step.snap(date);
};

+ 39
- 1
src/timeline/component/GraphGroup.js View File

@ -21,7 +21,7 @@ GraphGroup.prototype.setClass = function (className) {
GraphGroup.prototype.setOptions = function(options) {
if (options !== undefined) {
var fields = ['yAxisOrientation'];
util.selectiveExtend(fields, options, this.options);
util.selectiveExtend(fields, this.options, options);
this.linegraph._mergeOptions(this.options, options,'catmullRom');
this.linegraph._mergeOptions(this.options, options,'drawPoints');
this.linegraph._mergeOptions(this.options, options,'shaded');
@ -34,3 +34,41 @@ GraphGroup.prototype.update = function(group) {
this.className = group.className || this.className || "graphGroup" + this.linegraph.groupsUsingDefaultStyles;
this.setOptions(group.options);
};
GraphGroup.prototype.drawIcon = function(x,y,JSONcontainer, SVGcontainer, lineLength, iconHeight) {
var fillHeight = iconHeight * 0.5;
var path, fillPath, outline;
if (this.options.barGraph.enabled == false) {
outline = this.linegraph._getSVGElement("rect", JSONcontainer, SVGcontainer);
outline.setAttributeNS(null, "x", x);
outline.setAttributeNS(null, "y", y - fillHeight);
outline.setAttributeNS(null, "width", lineLength);
outline.setAttributeNS(null, "height", 2*fillHeight);
outline.setAttributeNS(null, "class", "outline");
path = this.linegraph._getSVGElement("path", JSONcontainer, SVGcontainer);
path.setAttributeNS(null, "class", this.className);
path.setAttributeNS(null, "d", "M" + x + ","+y+" L" + (x + lineLength) + ","+y+"");
if (this.options.shaded.enabled == true) {
fillPath = this.linegraph._getSVGElement("path", JSONcontainer, SVGcontainer);
if (this.options.shaded.orientation == 'top') {
fillPath.setAttributeNS(null, "d", "M"+x+", " + (y - fillHeight) +
"L"+x+","+y+" L"+ (x + lineLength) + ","+y+" L"+ (x + lineLength) + "," + (y - fillHeight));
}
else {
fillPath.setAttributeNS(null, "d", "M"+x+","+y+" " +
"L"+x+"," + (y + fillHeight) + " " +
"L"+ (x + lineLength) + "," + (y + fillHeight) +
"L"+ (x + lineLength) + ","+y);
}
fillPath.setAttributeNS(null, "class", this.className + " iconFill");
}
if (this.options.drawPoints.enabled == true) {
this.linegraph.drawPoint(x + 0.5 * lineLength,y, this, JSONcontainer, SVGcontainer);
}
}
else {
//TODO: bars
}
}

+ 58
- 15
src/timeline/component/Linegraph.js View File

@ -11,7 +11,7 @@ function Linegraph(body, options) {
orientation: 'top' // top, bottom
},
barGraph: {
enabled: true,
enabled: false,
binSize: 'auto'
},
drawPoints: {
@ -23,6 +23,24 @@ function Linegraph(body, options) {
enabled: true,
parametrization: 'centripetal', // uniform (alpha = 0.0), chordal (alpha = 1.0), centripetal (alpha = 0.5)
alpha: 0.5
},
dataAxis: {
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 27,
minorLinesOffset: 24,
labelOffsetX: 2,
labelOffsetY: 0,
width: '60px'
},
dataAxisRight: {
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 7,
minorLinesOffset: 4,
labelOffsetX: 9,
labelOffsetY: -6,
width: '60px'
}
};
@ -117,21 +135,11 @@ Linegraph.prototype._create = function(){
// panel with time axis
this.yAxisLeft = new DataAxis(this.body, {
orientation: 'left',
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 25,
minorLinesOffset: 25,
width: '50px',
height: this.svg.style.height
});
this.yAxisRight = new DataAxis(this.body, {
orientation: 'right',
showMinorLabels: true,
showMajorLabels: true,
majorLinesOffset: 25,
minorLinesOffset: 25,
width: '50px',
height: this.svg.style.height
});
@ -329,13 +337,24 @@ Linegraph.prototype._onUpdateGroups = function (groupIds) {
if (!this.groups.hasOwnProperty(groupIds[i])) {
this.groups[groupIds[i]] = new GraphGroup(group, this.options, this);
this.legend.addGroup(groupIds[i],this.groups[groupIds[i]]);
if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') {
this.yAxisRight.addGroup(groupIds[i], this.groups[groupIds[i]]);
}
else {
this.yAxisLeft.addGroup(groupIds[i], this.groups[groupIds[i]]);
}
}
else {
this.groups[groupIds[i]].update(group);
this.legend.updateGroup(groupIds[i],this.groups[groupIds[i]]);
if (this.groups[groupIds[i]].options.yAxisOrientation == 'right') {
this.yAxisRight.updateGroup(groupIds[i], this.groups[groupIds[i]]);
}
else {
this.yAxisLeft.updateGroup(groupIds[i], this.groups[groupIds[i]]);
}
}
}
this.updateGraph();
this.redraw();
};
@ -358,9 +377,23 @@ Linegraph.prototype._updateUngrouped = function() {
var group = {content: "graph"};
if (!this.groups.hasOwnProperty(UNGROUPED)) {
this.groups[UNGROUPED] = new GraphGroup(group, this.options, this);
this.legend.addGroup(UNGROUPED,this.groups[UNGROUPED]);
if (this.groups[UNGROUPED].options.yAxisOrientation == 'right') {
this.yAxisRight.addGroup(UNGROUPED, this.groups[UNGROUPED]);
}
else {
this.yAxisLeft.addGroup(UNGROUPED, this.groups[UNGROUPED]);
}
}
else {
this.groups[UNGROUPED].update(group);
this.legend.updateGroup(UNGROUPED,this.groups[UNGROUPED]);
if (this.groups[UNGROUPED].options.yAxisOrientation == 'right') {
this.yAxisRight.updateGroup(UNGROUPED, this.groups[UNGROUPED]);
}
else {
this.yAxisLeft.updateGroup(UNGROUPED, this.groups[UNGROUPED]);
}
}
if (this.itemsData != null) {
@ -380,6 +413,8 @@ Linegraph.prototype._updateUngrouped = function() {
if (pointInUNGROUPED.length == 0) {
this.legend.deleteGroup(UNGROUPED);
delete this.groups[UNGROUPED];
this.yAxisLeft.yAxisRight(UNGROUPED);
this.yAxisLeft.deleteGroup(UNGROUPED);
}
}
};
@ -495,6 +530,15 @@ Linegraph.prototype._updateYAxis = function(groupIds) {
this.body.emitter.emit('change');
}
if (yAxisRightUsed == true && yAxisLeftUsed == true) {
this.yAxisLeft.drawIcons = true;
this.yAxisRight.drawIcons = true;
}
else {
this.yAxisLeft.drawIcons = false;
this.yAxisRight.drawIcons = false;
}
this.yAxisRight.master = !yAxisLeftUsed;
if (this.yAxisRight.master == false) {
@ -549,7 +593,7 @@ Linegraph.prototype.drawGraph = function (groupId, groupIndex, amountOfGraphs) {
// can be optimized, only has to be done once.
var group = this.groups[groupId];
if (this.options.style == 'bar') {
if (this.options.barGraph.enabled == 'true') {
this.drawBarGraph(datapoints, group, amountOfGraphs);
}
else {
@ -569,7 +613,6 @@ Linegraph.prototype.drawBarGraph = function (datapoints, group, amountOfGraphs)
var dataset = this._prepareData(datapoints);
// draw points
for (var i = 0; i < dataset.length; i++) {
this.drawBar(dataset[i].x, dataset[i].y, className);
}
}
@ -670,7 +713,7 @@ Linegraph.prototype.drawPoints = function (dataset, group, JSONcontainer, svg) {
*/
Linegraph.prototype.drawPoint = function(x, y, group, JSONcontainer, svgContainer) {
var point;
if (options.drawPoints.style == 'circle') {
if (group.options.drawPoints.style == 'circle') {
point = this._getSVGElement('circle',JSONcontainer,svgContainer);
point.setAttributeNS(null, "cx", x);
point.setAttributeNS(null, "cy", y);

+ 2
- 2
src/timeline/component/css/dataaxis.css View File

@ -17,7 +17,7 @@
.vis.timeline .dataaxis .yAxis.major {
font-size:10px;
font-size:12px;
width: 100%;
position: absolute;
color: #4d4d4d;
@ -26,7 +26,7 @@
.vis.timeline .dataaxis .yAxis.minor{
font-size:10px;
font-size:12px;
position: absolute;
width: 100%;
color: #979797;

+ 4
- 0
src/timeline/component/css/pathStyles.css View File

@ -94,5 +94,9 @@
stroke: #e5e5e5;
}
.vis.timeline .iconFill {
fill-opacity:0.3;
stroke: none;
}

+ 6
- 8
src/timeline/component/legend.js View File

@ -13,7 +13,7 @@ function Legend(body, options, linegraph) {
this.svgElements = {};
this.dom = {};
this.classes;
this.graphs = {};
this.groups = {};
this.setOptions(options);
this.create();
@ -23,20 +23,18 @@ Legend.prototype = new Component();
Legend.prototype.addGroup = function(label, graphOptions) {
if (!this.graphs.hasOwnProperty(label)) {
this.graphs[label] = graphOptions;
this.redraw();
if (!this.groups.hasOwnProperty(label)) {
this.groups[label] = graphOptions;
}
};
Legend.prototype.updateGroup = function(label, graphOptions) {
this.graphs[label] = graphOptions;
this.groups[label] = graphOptions;
};
Legend.prototype.deleteGroup = function(label) {
if (this.graphs.hasOwnProperty(label)) {
delete this.graphs[label];
this.redraw();
if (this.groups.hasOwnProperty(label)) {
delete this.groups[label];
}
};

Loading…
Cancel
Save