From 722d4d1ace5007d405864abf32c0fd753644a18a Mon Sep 17 00:00:00 2001 From: Alex de Mulder Date: Mon, 16 Jun 2014 12:39:40 +0200 Subject: [PATCH] adding dataset support, wip --- dist/vis.css | 24 ++- dist/vis.js | 259 ++++++++++++------------ examples/Graph2d/01_basic.html | 16 +- src/timeline/component/DataAxis.js | 32 +-- src/timeline/component/Linegraph.js | 227 +++++++++++---------- src/timeline/component/css/dataaxis.css | 24 ++- 6 files changed, 309 insertions(+), 273 deletions(-) diff --git a/dist/vis.css b/dist/vis.css index 4c476d13..cda934c9 100644 --- a/dist/vis.css +++ b/dist/vis.css @@ -341,7 +341,7 @@ .vis.timeline .dataaxis .yAxis.major { - font-size:12px; + font-size:10px; width: 100%; position: absolute; color: #4d4d4d; @@ -350,12 +350,30 @@ .vis.timeline .dataaxis .yAxis.minor{ - font-size:9px; + font-size:10px; position: absolute; width: 100%; - color: #4d4d4d; + color: #979797; white-space: nowrap; } + +.vis.timeline .default { + fill:none; + stroke-width:1px; + stroke: #5388ff; +} + +.vis.timeline .redd { + fill:none; + stroke-width:1px; + stroke: #ff0000; +} + +.vis.timeline .greenn { + fill:none; + stroke-width:1px; + stroke: #00ff00; +} div.graph-manipulationDiv { border-width:0px; border-bottom: 1px; diff --git a/dist/vis.js b/dist/vis.js index bae9fc7b..c9ae7863 100644 --- a/dist/vis.js +++ b/dist/vis.js @@ -2552,7 +2552,7 @@ function DataAxis (body, options) { orientation: 'left', // supported: 'left' showMinorLabels: true, showMajorLabels: true, - width: '90px', + width: '50px', height: '300px' }; @@ -2582,6 +2582,7 @@ function DataAxis (body, options) { this.options = util.extend({}, this.defaultOptions); this.conversionFactor = 1; + this.width = Number(this.options.width.replace("px","")); // create the HTML DOM this._create(); } @@ -2636,6 +2637,7 @@ DataAxis.prototype.hide = function() { this.body.dom.backgroundHorizontal.removeChild(this.dom.lineContainer); } }; + /** * Set a range (start and end) * @param {Range | Object} range A Range or an object containing start and end. @@ -2670,9 +2672,9 @@ DataAxis.prototype.redraw = function () { props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - props.minorLineWidth = 3000; + props.minorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth; props.minorLineHeight = 1; - props.majorLineWidth = 3000; + props.majorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth; props.majorLineHeight = 1; // take frame offline while updating (is almost twice as fast) @@ -2729,12 +2731,12 @@ DataAxis.prototype._redrawLabels = function () { var marginStartPos = 0; var max = 0; while (step.hasNext() && max < 1000) { - var y = max * stepPixels; - y = y.toPrecision(5) + var y = Math.round(max * stepPixels); + marginStartPos = max * stepPixels; var isMajor = step.isMajor(); if (this.options['showMinorLabels'] && isMajor == false) { - this._redrawMinorText(y, step.getLabelMinor(), orientation); + this._redrawMinorText(y - 2, step.getLabelMinor(), orientation); } if (isMajor && this.options['showMajorLabels']) { @@ -2742,7 +2744,7 @@ DataAxis.prototype._redrawLabels = function () { if (xFirstMajorLabel == undefined) { xFirstMajorLabel = y; } - this._redrawMajorText(y, step.getLabelMajor(), orientation); + this._redrawMajorText(y - 2, step.getLabelMajor(), orientation); } this._redrawMajorLine(y, orientation); } @@ -2751,7 +2753,6 @@ DataAxis.prototype._redrawLabels = function () { } step.next(); - marginStartPos = y; max++; } @@ -2781,12 +2782,12 @@ DataAxis.prototype._redrawLabels = function () { DataAxis.prototype.convertValues = function(data) { for (var i = 0; i < data.length; i++) { - data[i].y = this._getPos(data[i].y); + data[i].y = this.convertValue(data[i].y); } return data; } -DataAxis.prototype._getPos = function(value) { +DataAxis.prototype.convertValue = function(value) { var invertedValue = this.valueAtZero - value; var convertedValue = invertedValue * this.conversionFactor; return convertedValue - 2; // the -2 is to compensate for the borders @@ -2799,7 +2800,7 @@ DataAxis.prototype._getPos = function(value) { * @param {String} orientation "top" or "bottom" (default) * @private */ -DataAxis.prototype._redrawMinorText = function (x, text, orientation) { +DataAxis.prototype._redrawMinorText = function (y, text, orientation) { // reuse redundant label var label = this.dom.redundant.minorTexts.shift(); @@ -2824,7 +2825,7 @@ DataAxis.prototype._redrawMinorText = function (x, text, orientation) { label.style.textAlign = "left"; } - label.style.top = x + 'px'; + label.style.top = y + 'px'; //label.title = title; // TODO: this is a heavy operation }; @@ -2835,7 +2836,7 @@ DataAxis.prototype._redrawMinorText = function (x, text, orientation) { * @param {String} orientation "top" or "bottom" (default) * @private */ -DataAxis.prototype._redrawMajorText = function (x, text, orientation) { +DataAxis.prototype._redrawMajorText = function (y, text, orientation) { // reuse redundant label var label = this.dom.redundant.majorTexts.shift(); @@ -2861,7 +2862,7 @@ DataAxis.prototype._redrawMajorText = function (x, text, orientation) { label.style.textAlign = "left"; } - label.style.top = x + 'px'; + label.style.top = y + 'px'; }; /** @@ -2912,7 +2913,6 @@ DataAxis.prototype._redrawMajorLine = function (y, orientation) { } this.dom.majorLines.push(line); - var props = this.props; if (orientation == 'left') { line.style.left = (this.width - 25) + 'px'; } @@ -2920,7 +2920,7 @@ DataAxis.prototype._redrawMajorLine = function (y, orientation) { line.style.left = -1*(this.width - 25) + 'px'; } line.style.top = y + 'px'; - line.style.width = props.majorLineWidth + 'px'; + line.style.width = this.props.majorLineWidth + 'px'; }; @@ -2975,47 +2975,15 @@ function Linegraph(body, options) { this.body = body; this.defaultOptions = { - type: 'box', - orientation: 'bottom', // 'top' or 'bottom' - align: 'center', // alignment of box items - stack: true, - groupOrder: null, - - selectable: true, - editable: { - updateTime: false, - updateGroup: false, - add: false, - remove: false - }, - - onAdd: function (item, callback) { - callback(item); - }, - onUpdate: function (item, callback) { - callback(item); - }, - onMove: function (item, callback) { - callback(item); - }, - onRemove: function (item, callback) { - callback(item); - }, - - margin: { - item: 10, - axis: 20 - }, - padding: 5 + catmullRom: { + enabled: true, + parametrization: 'centripetal', // uniform (0,0), chordal (1.0), centripetal (0.5) + alpha: 0.5 + } }; // options is shared by this ItemSet and all its items this.options = util.extend({}, this.defaultOptions); - - this.conversion = { - toScreen: body.util.toScreen, - toTime: body.util.toTime - }; this.dom = {}; this.props = {}; this.hammer = null; @@ -3041,6 +3009,8 @@ function Linegraph(body, options) { this.selection = []; // list with the ids of all selected nodes this.lastStart = this.body.range.start; this.touchParams = {}; // stores properties while dragging + this.lines = []; + this.redundantLines = []; // create the HTML DOM this._create(); @@ -3069,14 +3039,6 @@ function Linegraph(body, options) { Linegraph.prototype = new Component(); -// available item types will be registered here -Linegraph.types = { - box: ItemBox, - range: ItemRange, - rangeoverflow: ItemRangeOverflow, - point: ItemPoint -}; - /** * Create the HTML DOM for the ItemSet */ @@ -3098,33 +3060,13 @@ Linegraph.prototype._create = function(){ frame.appendChild(foreground); this.dom.foreground = foreground; + // create svg element for graph drawing. this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); this.svg.style.position = "relative" this.svg.style.height = "300px"; -// this.svg.style.width = this.svg.style.display = "block"; - this.path = document.createElementNS('http://www.w3.org/2000/svg',"path"); - this.path.setAttributeNS(null, "fill","none"); - this.path.setAttributeNS(null, "stroke","blue"); - this.path.setAttributeNS(null, "stroke-width","1"); - - this.path2 = document.createElementNS('http://www.w3.org/2000/svg',"path"); - this.path2.setAttributeNS(null, "fill","none"); - this.path2.setAttributeNS(null, "stroke","red"); - this.path2.setAttributeNS(null, "stroke-width","1"); - - this.path3 = document.createElementNS('http://www.w3.org/2000/svg',"path"); - this.path3.setAttributeNS(null, "fill","none"); - this.path3.setAttributeNS(null, "stroke","green"); - this.path3.setAttributeNS(null, "stroke-width","1"); - frame.appendChild(this.svg); - - this.svg.appendChild(this.path3); - this.svg.appendChild(this.path2); - this.svg.appendChild(this.path); - // panel with time axis this.yAxis = new DataAxis(this.body, { orientation: 'left', @@ -3140,7 +3082,38 @@ Linegraph.prototype._create = function(){ Linegraph.prototype.setOptions = function(options) { if (options) { - + var fields = ['catmullRom']; + util.selectiveExtend(fields, this.options, options); + console.log(this.options); + if (options.catmullRom) { + if (typeof options.catmullRom == 'boolean') { + this.options.catmullRom.enabled = options.catmullRom; + } + else { + if (options.catmullRom.enabled) { + this.options.catmullRom.enabled = options.catmullRom.enabled; + } + else { + this.options.catmullRom.enabled = true; + } + if (options.catmullRom.parametrization) { + this.options.catmullRom.parametrization = options.catmullRom.parametrization; + if (options.catmullRom.parametrization == 'uniform') { + this.options.catmullRom.alpha = 0; + } + else if (options.catmullRom.parametrization == 'chordal') { + this.options.catmullRom.alpha = 1.0; + } + else { + this.options.catmullRom.parametrization = 'centripetal' + this.options.catmullRom.alpha = 0.5; + } + } + if (options.catmullRom.alpha) { + this.options.catmullRom.alpha = options.catmullRom.alpha; + } + } + } } }; @@ -3200,36 +3173,35 @@ Linegraph.prototype.setItems = function(items) { } if (this.itemsData) { -// // subscribe to new dataset -// var id = this.id; -// util.forEach(this.itemListeners, function (callback, event) { -// me.itemsData.on(event, callback, id); -// }); -// -// // add all new items -// ids = this.itemsData.getIds(); -// this._onAdd(ids); + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); + + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); } this.redraw(); }; - /** * Handle added items * @param {Number[]} ids * @protected */ -Linegraph.prototype._onAdd = Linegraph.prototype._onUpdate; + /** * Handle updated items * @param {Number[]} ids * @protected */ -Linegraph.prototype._onUpdate = function(ids) { -}; - +Linegraph.prototype._onUpdate = function(ids) {}; +Linegraph.prototype._onAdd = Linegraph.prototype._onUpdate; +Linegraph.prototype._onRemove = function(ids) {}; @@ -3264,55 +3236,82 @@ Linegraph.prototype.redraw = function() { }; -Linegraph.prototype._extractData = function(dataset) { - var extractedData = []; +Linegraph.prototype.updateGraph = function() { + // reset the lines + this.redundantLines = this.lines; + this.lines = []; - var low = dataset[0].y; - var high = dataset[0].y; + if (this.width != 0 && this.itemsData != null) { + // get the range for the y Axis and draw it + var yRange = {start:this.itemsData.min('y').y,end:this.itemsData.max('y').y}; + this.yAxis.setRange(yRange); + this.yAxis.redraw(); - for (var i = 0; i < dataset.length; i++) { - var val = this.body.util.toScreen(new Date(dataset[i].x)) + this.width; - extractedData.push({x:val, y:dataset[i].y}); - if (low > dataset[i].y) { - low = dataset[i].y; + console.log(this.itemsData); + // look at different lines + var classes = this.itemsData.distinct('className'); + var datapoints; + + if (classes.length == 0) { + datapoints = this.itemsData.get(); + this.drawGraph(datapoints, 'default'); } - if (high < dataset[i].y) { - high = dataset[i].y; + else { + for (var i = 0; i < classes.length; i++) { + datapoints = this.itemsData.get({filter: function(item) {return item.className == classes[i];}}); + this.drawGraph(datapoints, classes[i]); + } } } -// extractedData.sort(function (a,b) {return a.x - b.x;}); - return {range:{low:low,high:high},data:extractedData}; + // cleanup the redundant lines; + for (var i = 0; i < this.redundantLines.length; i++) { + this.redundantLines[i].parentNode.removeChild(this.redundantLines[i]); + } + this.redundantLines = []; } -Linegraph.prototype.updateGraph = function() { - if (this.width != 0 && this.itemsData != null) { - - var datapoints = this.itemsData.get(); - if (datapoints != null) { - if (datapoints.length > 0) { - var dataset = this._extractData(datapoints); - var data = dataset.data; - - this.yAxis.setRange({start:dataset.range.low,end:dataset.range.high}); - this.yAxis.redraw(); - data = this.yAxis.convertValues(data); - - var d, d2, d3; - d = this._catmullRom(data,0.5); - d2 = this._catmullRom(data,0); - d3 = this._linear(data); +Linegraph.prototype.drawGraph = function(datapoints, className) { + if (datapoints != null) { + if (datapoints.length > 0) { + var dataset = this._prepareData(datapoints); + var path, d; + if (this.redundantLines.length != 0) { + path = this.redundantLines[this.redundantLines.length-1]; + this.redundantLines.pop() + } + else { + path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + this.svg.appendChild(path); + } + path.setAttributeNS(null, "class",className); + this.lines.push(path); -// this.path.setAttributeNS(null, "d",d); -// this.path2.setAttributeNS(null, "d",d2); - this.path3.setAttributeNS(null, "d",d3); + if (this.options.catmullRom.enabled == true) { + d = this._catmullRom(dataset,this.options.catmullRom.alpha); } + else { + d = this._linear(dataset); + } + + path.setAttributeNS(null, "d",d); } } } +Linegraph.prototype._prepareData = function(dataset) { + var extractedData = []; + for (var i = 0; i < dataset.length; i++) { + var xValue = this.body.util.toScreen(new Date(dataset[i].x)) + this.width; + var yValue = this.yAxis.convertValue(dataset[i].y); + extractedData.push({x:xValue, y:yValue}); + } +// extractedData.sort(function (a,b) {return a.x - b.x;}); + return extractedData; +} + Linegraph.prototype._catmullRomUniform = function(data) { // catmull rom var p0, p1, p2, p3, bp1, bp2 diff --git a/examples/Graph2d/01_basic.html b/examples/Graph2d/01_basic.html index 5e67b94b..c2f560c2 100644 --- a/examples/Graph2d/01_basic.html +++ b/examples/Graph2d/01_basic.html @@ -18,15 +18,17 @@ \ No newline at end of file diff --git a/src/timeline/component/DataAxis.js b/src/timeline/component/DataAxis.js index 9b32ac65..b63258d0 100644 --- a/src/timeline/component/DataAxis.js +++ b/src/timeline/component/DataAxis.js @@ -13,7 +13,7 @@ function DataAxis (body, options) { orientation: 'left', // supported: 'left' showMinorLabels: true, showMajorLabels: true, - width: '90px', + width: '50px', height: '300px' }; @@ -43,6 +43,7 @@ function DataAxis (body, options) { this.options = util.extend({}, this.defaultOptions); this.conversionFactor = 1; + this.width = Number(this.options.width.replace("px","")); // create the HTML DOM this._create(); } @@ -97,6 +98,7 @@ DataAxis.prototype.hide = function() { this.body.dom.backgroundHorizontal.removeChild(this.dom.lineContainer); } }; + /** * Set a range (start and end) * @param {Range | Object} range A Range or an object containing start and end. @@ -131,9 +133,9 @@ DataAxis.prototype.redraw = function () { props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0; props.majorLabelHeight = showMajorLabels ? props.majorCharHeight : 0; - props.minorLineWidth = 3000; + props.minorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth; props.minorLineHeight = 1; - props.majorLineWidth = 3000; + props.majorLineWidth = this.body.dom.backgroundHorizontal.offsetWidth; props.majorLineHeight = 1; // take frame offline while updating (is almost twice as fast) @@ -190,12 +192,12 @@ DataAxis.prototype._redrawLabels = function () { var marginStartPos = 0; var max = 0; while (step.hasNext() && max < 1000) { - var y = max * stepPixels; - y = y.toPrecision(5) + var y = Math.round(max * stepPixels); + marginStartPos = max * stepPixels; var isMajor = step.isMajor(); if (this.options['showMinorLabels'] && isMajor == false) { - this._redrawMinorText(y, step.getLabelMinor(), orientation); + this._redrawMinorText(y - 2, step.getLabelMinor(), orientation); } if (isMajor && this.options['showMajorLabels']) { @@ -203,7 +205,7 @@ DataAxis.prototype._redrawLabels = function () { if (xFirstMajorLabel == undefined) { xFirstMajorLabel = y; } - this._redrawMajorText(y, step.getLabelMajor(), orientation); + this._redrawMajorText(y - 2, step.getLabelMajor(), orientation); } this._redrawMajorLine(y, orientation); } @@ -212,7 +214,6 @@ DataAxis.prototype._redrawLabels = function () { } step.next(); - marginStartPos = y; max++; } @@ -242,12 +243,12 @@ DataAxis.prototype._redrawLabels = function () { DataAxis.prototype.convertValues = function(data) { for (var i = 0; i < data.length; i++) { - data[i].y = this._getPos(data[i].y); + data[i].y = this.convertValue(data[i].y); } return data; } -DataAxis.prototype._getPos = function(value) { +DataAxis.prototype.convertValue = function(value) { var invertedValue = this.valueAtZero - value; var convertedValue = invertedValue * this.conversionFactor; return convertedValue - 2; // the -2 is to compensate for the borders @@ -260,7 +261,7 @@ DataAxis.prototype._getPos = function(value) { * @param {String} orientation "top" or "bottom" (default) * @private */ -DataAxis.prototype._redrawMinorText = function (x, text, orientation) { +DataAxis.prototype._redrawMinorText = function (y, text, orientation) { // reuse redundant label var label = this.dom.redundant.minorTexts.shift(); @@ -285,7 +286,7 @@ DataAxis.prototype._redrawMinorText = function (x, text, orientation) { label.style.textAlign = "left"; } - label.style.top = x + 'px'; + label.style.top = y + 'px'; //label.title = title; // TODO: this is a heavy operation }; @@ -296,7 +297,7 @@ DataAxis.prototype._redrawMinorText = function (x, text, orientation) { * @param {String} orientation "top" or "bottom" (default) * @private */ -DataAxis.prototype._redrawMajorText = function (x, text, orientation) { +DataAxis.prototype._redrawMajorText = function (y, text, orientation) { // reuse redundant label var label = this.dom.redundant.majorTexts.shift(); @@ -322,7 +323,7 @@ DataAxis.prototype._redrawMajorText = function (x, text, orientation) { label.style.textAlign = "left"; } - label.style.top = x + 'px'; + label.style.top = y + 'px'; }; /** @@ -373,7 +374,6 @@ DataAxis.prototype._redrawMajorLine = function (y, orientation) { } this.dom.majorLines.push(line); - var props = this.props; if (orientation == 'left') { line.style.left = (this.width - 25) + 'px'; } @@ -381,7 +381,7 @@ DataAxis.prototype._redrawMajorLine = function (y, orientation) { line.style.left = -1*(this.width - 25) + 'px'; } line.style.top = y + 'px'; - line.style.width = props.majorLineWidth + 'px'; + line.style.width = this.props.majorLineWidth + 'px'; }; diff --git a/src/timeline/component/Linegraph.js b/src/timeline/component/Linegraph.js index d65e1e29..bfb63ff3 100644 --- a/src/timeline/component/Linegraph.js +++ b/src/timeline/component/Linegraph.js @@ -5,47 +5,15 @@ function Linegraph(body, options) { this.body = body; this.defaultOptions = { - type: 'box', - orientation: 'bottom', // 'top' or 'bottom' - align: 'center', // alignment of box items - stack: true, - groupOrder: null, - - selectable: true, - editable: { - updateTime: false, - updateGroup: false, - add: false, - remove: false - }, - - onAdd: function (item, callback) { - callback(item); - }, - onUpdate: function (item, callback) { - callback(item); - }, - onMove: function (item, callback) { - callback(item); - }, - onRemove: function (item, callback) { - callback(item); - }, - - margin: { - item: 10, - axis: 20 - }, - padding: 5 + catmullRom: { + enabled: true, + parametrization: 'centripetal', // uniform (0,0), chordal (1.0), centripetal (0.5) + alpha: 0.5 + } }; // options is shared by this ItemSet and all its items this.options = util.extend({}, this.defaultOptions); - - this.conversion = { - toScreen: body.util.toScreen, - toTime: body.util.toTime - }; this.dom = {}; this.props = {}; this.hammer = null; @@ -71,6 +39,8 @@ function Linegraph(body, options) { this.selection = []; // list with the ids of all selected nodes this.lastStart = this.body.range.start; this.touchParams = {}; // stores properties while dragging + this.lines = []; + this.redundantLines = []; // create the HTML DOM this._create(); @@ -99,14 +69,6 @@ function Linegraph(body, options) { Linegraph.prototype = new Component(); -// available item types will be registered here -Linegraph.types = { - box: ItemBox, - range: ItemRange, - rangeoverflow: ItemRangeOverflow, - point: ItemPoint -}; - /** * Create the HTML DOM for the ItemSet */ @@ -128,33 +90,13 @@ Linegraph.prototype._create = function(){ frame.appendChild(foreground); this.dom.foreground = foreground; + // create svg element for graph drawing. this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg"); this.svg.style.position = "relative" this.svg.style.height = "300px"; -// this.svg.style.width = this.svg.style.display = "block"; - this.path = document.createElementNS('http://www.w3.org/2000/svg',"path"); - this.path.setAttributeNS(null, "fill","none"); - this.path.setAttributeNS(null, "stroke","blue"); - this.path.setAttributeNS(null, "stroke-width","1"); - - this.path2 = document.createElementNS('http://www.w3.org/2000/svg',"path"); - this.path2.setAttributeNS(null, "fill","none"); - this.path2.setAttributeNS(null, "stroke","red"); - this.path2.setAttributeNS(null, "stroke-width","1"); - - this.path3 = document.createElementNS('http://www.w3.org/2000/svg',"path"); - this.path3.setAttributeNS(null, "fill","none"); - this.path3.setAttributeNS(null, "stroke","green"); - this.path3.setAttributeNS(null, "stroke-width","1"); - frame.appendChild(this.svg); - - this.svg.appendChild(this.path3); - this.svg.appendChild(this.path2); - this.svg.appendChild(this.path); - // panel with time axis this.yAxis = new DataAxis(this.body, { orientation: 'left', @@ -170,7 +112,38 @@ Linegraph.prototype._create = function(){ Linegraph.prototype.setOptions = function(options) { if (options) { - + var fields = ['catmullRom']; + util.selectiveExtend(fields, this.options, options); + console.log(this.options); + if (options.catmullRom) { + if (typeof options.catmullRom == 'boolean') { + this.options.catmullRom.enabled = options.catmullRom; + } + else { + if (options.catmullRom.enabled) { + this.options.catmullRom.enabled = options.catmullRom.enabled; + } + else { + this.options.catmullRom.enabled = true; + } + if (options.catmullRom.parametrization) { + this.options.catmullRom.parametrization = options.catmullRom.parametrization; + if (options.catmullRom.parametrization == 'uniform') { + this.options.catmullRom.alpha = 0; + } + else if (options.catmullRom.parametrization == 'chordal') { + this.options.catmullRom.alpha = 1.0; + } + else { + this.options.catmullRom.parametrization = 'centripetal' + this.options.catmullRom.alpha = 0.5; + } + } + if (options.catmullRom.alpha) { + this.options.catmullRom.alpha = options.catmullRom.alpha; + } + } + } } }; @@ -230,36 +203,35 @@ Linegraph.prototype.setItems = function(items) { } if (this.itemsData) { -// // subscribe to new dataset -// var id = this.id; -// util.forEach(this.itemListeners, function (callback, event) { -// me.itemsData.on(event, callback, id); -// }); -// -// // add all new items -// ids = this.itemsData.getIds(); -// this._onAdd(ids); + // subscribe to new dataset + var id = this.id; + util.forEach(this.itemListeners, function (callback, event) { + me.itemsData.on(event, callback, id); + }); + + // add all new items + ids = this.itemsData.getIds(); + this._onAdd(ids); } this.redraw(); }; - /** * Handle added items * @param {Number[]} ids * @protected */ -Linegraph.prototype._onAdd = Linegraph.prototype._onUpdate; + /** * Handle updated items * @param {Number[]} ids * @protected */ -Linegraph.prototype._onUpdate = function(ids) { -}; - +Linegraph.prototype._onUpdate = function(ids) {}; +Linegraph.prototype._onAdd = Linegraph.prototype._onUpdate; +Linegraph.prototype._onRemove = function(ids) {}; @@ -294,55 +266,82 @@ Linegraph.prototype.redraw = function() { }; -Linegraph.prototype._extractData = function(dataset) { - var extractedData = []; +Linegraph.prototype.updateGraph = function() { + // reset the lines + this.redundantLines = this.lines; + this.lines = []; - var low = dataset[0].y; - var high = dataset[0].y; + if (this.width != 0 && this.itemsData != null) { + // get the range for the y Axis and draw it + var yRange = {start:this.itemsData.min('y').y,end:this.itemsData.max('y').y}; + this.yAxis.setRange(yRange); + this.yAxis.redraw(); - for (var i = 0; i < dataset.length; i++) { - var val = this.body.util.toScreen(new Date(dataset[i].x)) + this.width; - extractedData.push({x:val, y:dataset[i].y}); - if (low > dataset[i].y) { - low = dataset[i].y; + console.log(this.itemsData); + // look at different lines + var classes = this.itemsData.distinct('className'); + var datapoints; + + if (classes.length == 0) { + datapoints = this.itemsData.get(); + this.drawGraph(datapoints, 'default'); } - if (high < dataset[i].y) { - high = dataset[i].y; + else { + for (var i = 0; i < classes.length; i++) { + datapoints = this.itemsData.get({filter: function(item) {return item.className == classes[i];}}); + this.drawGraph(datapoints, classes[i]); + } } } -// extractedData.sort(function (a,b) {return a.x - b.x;}); - return {range:{low:low,high:high},data:extractedData}; + // cleanup the redundant lines; + for (var i = 0; i < this.redundantLines.length; i++) { + this.redundantLines[i].parentNode.removeChild(this.redundantLines[i]); + } + this.redundantLines = []; } -Linegraph.prototype.updateGraph = function() { - if (this.width != 0 && this.itemsData != null) { - - var datapoints = this.itemsData.get(); - if (datapoints != null) { - if (datapoints.length > 0) { - var dataset = this._extractData(datapoints); - var data = dataset.data; - - this.yAxis.setRange({start:dataset.range.low,end:dataset.range.high}); - this.yAxis.redraw(); - data = this.yAxis.convertValues(data); - - var d, d2, d3; - d = this._catmullRom(data,0.5); - d2 = this._catmullRom(data,0); - d3 = this._linear(data); +Linegraph.prototype.drawGraph = function(datapoints, className) { + if (datapoints != null) { + if (datapoints.length > 0) { + var dataset = this._prepareData(datapoints); + var path, d; + if (this.redundantLines.length != 0) { + path = this.redundantLines[this.redundantLines.length-1]; + this.redundantLines.pop() + } + else { + path = document.createElementNS('http://www.w3.org/2000/svg',"path"); + this.svg.appendChild(path); + } + path.setAttributeNS(null, "class",className); + this.lines.push(path); -// this.path.setAttributeNS(null, "d",d); -// this.path2.setAttributeNS(null, "d",d2); - this.path3.setAttributeNS(null, "d",d3); + if (this.options.catmullRom.enabled == true) { + d = this._catmullRom(dataset,this.options.catmullRom.alpha); + } + else { + d = this._linear(dataset); } + + path.setAttributeNS(null, "d",d); } } } +Linegraph.prototype._prepareData = function(dataset) { + var extractedData = []; + for (var i = 0; i < dataset.length; i++) { + var xValue = this.body.util.toScreen(new Date(dataset[i].x)) + this.width; + var yValue = this.yAxis.convertValue(dataset[i].y); + extractedData.push({x:xValue, y:yValue}); + } +// extractedData.sort(function (a,b) {return a.x - b.x;}); + return extractedData; +} + Linegraph.prototype._catmullRomUniform = function(data) { // catmull rom var p0, p1, p2, p3, bp1, bp2 diff --git a/src/timeline/component/css/dataaxis.css b/src/timeline/component/css/dataaxis.css index a1a9a56c..8caab08f 100644 --- a/src/timeline/component/css/dataaxis.css +++ b/src/timeline/component/css/dataaxis.css @@ -17,7 +17,7 @@ .vis.timeline .dataaxis .yAxis.major { - font-size:12px; + font-size:10px; width: 100%; position: absolute; color: #4d4d4d; @@ -26,9 +26,27 @@ .vis.timeline .dataaxis .yAxis.minor{ - font-size:9px; + font-size:10px; position: absolute; width: 100%; - color: #4d4d4d; + color: #979797; white-space: nowrap; +} + +.vis.timeline .default { + fill:none; + stroke-width:1px; + stroke: #5388ff; +} + +.vis.timeline .redd { + fill:none; + stroke-width:1px; + stroke: #ff0000; +} + +.vis.timeline .greenn { + fill:none; + stroke-width:1px; + stroke: #00ff00; } \ No newline at end of file