Browse Source

graph is drawing

css_transitions
Alex de Mulder 10 years ago
parent
commit
37ced4311f
4 changed files with 306 additions and 150 deletions
  1. +150
    -72
      dist/vis.js
  2. +6
    -6
      examples/Graph2d/01_basic.html
  3. +7
    -7
      src/timeline/component/DataAxis.js
  4. +143
    -65
      src/timeline/component/Linegraph.js

+ 150
- 72
dist/vis.js View File

@ -2631,9 +2631,9 @@ DataAxis.prototype.repaint = function () {
this._calculateCharSize();
// TODO: recalculate sizes only needed when parent is resized or options is changed
var orientation = this.getOption('orientation');
var showMinorLabels = this.getOption('showMinorLabels');
var showMajorLabels = this.getOption('showMajorLabels');
var orientation = this.options['orientation'];
var showMinorLabels = this.options['showMinorLabels'];
var showMajorLabels = this.options['showMajorLabels'];
// determine the width and height of the elemens for the axis
props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0;
@ -2671,7 +2671,7 @@ DataAxis.prototype.repaint = function () {
* @private
*/
DataAxis.prototype._repaintLabels = function () {
var orientation = this.getOption('orientation');
var orientation = this.options['orientation'];
// calculate range and step (step such that we have space for 7 characters per label)
var start = this.range.start;
@ -2705,11 +2705,11 @@ DataAxis.prototype._repaintLabels = function () {
y = y.toPrecision(5)
var isMajor = step.isMajor();
if (this.getOption('showMinorLabels') && isMajor == false) {
if (this.options['showMinorLabels'] && isMajor == false) {
this._repaintMinorText(y, step.getLabelMinor(), orientation);
}
if (isMajor && this.getOption('showMajorLabels')) {
if (isMajor && this.options['showMajorLabels']) {
if (y > 0) {
if (xFirstMajorLabel == undefined) {
xFirstMajorLabel = y;
@ -2733,7 +2733,7 @@ DataAxis.prototype._repaintLabels = function () {
// create a major label on the left when needed
if (this.getOption('showMajorLabels')) {
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
@ -2943,18 +2943,10 @@ DataAxis.prototype.snap = function snap (date) {
return this.step.snap(date);
};
var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items
/**
* An ItemSet holds a set of items and ranges which can be displayed in a
* range. The width is determined by the parent of the ItemSet, and the height
* is determined by the size of the items.
* @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} body
* @param {Object} [options] See Linegraph.setOptions for the available options.
* @constructor ItemSet
* @extends Component
*/
function Linegraph(body, options) {
this.id = util.randomUUID();
this.body = body;
this.defaultOptions = {
@ -3027,10 +3019,22 @@ function Linegraph(body, options) {
// create the HTML DOM
this._create();
this.body.emitter.on("drag", this._onDrag.bind(this))
this.body.emitter.on("dragEnd", this._onDragEnd.bind(this))
this.setOptions(options);
}
Linegraph.prototype._onDrag = function (event) {
if (this.svg) {
}
}
Linegraph.prototype._onDragEnd = function (event) {
this.updateGraph();
}
Linegraph.prototype = new Component();
// available item types will be registered here
@ -3062,9 +3066,35 @@ Linegraph.prototype._create = function(){
frame.appendChild(foreground);
this.dom.foreground = foreground;
this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
this.svg.style.position = "relative"
this.svg.style.height = "300px";
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
var dataAxisOptions = {
range: this.range,
range: this.body.range,
left: null,
top: null,
width: null,
@ -3074,7 +3104,6 @@ Linegraph.prototype._create = function(){
this.yAxis = new DataAxis(dataAxisOptions);
this.dom.axis = this.yAxis.getFrame();
this.show();
};
@ -3155,24 +3184,91 @@ Linegraph.prototype.show = function() {
}
};
/**
* Set items
* @param {vis.DataSet | null} items
*/
Linegraph.prototype.setItems = function(items) {
var me = this,
ids,
oldItemsData = this.itemsData;
// replace the dataset
if (!items) {
this.itemsData = null;
}
else if (items instanceof DataSet || items instanceof DataView) {
this.itemsData = items;
}
else {
throw new TypeError('Data must be an instance of DataSet or DataView');
}
if (oldItemsData) {
// unsubscribe from old dataset
util.forEach(this.itemListeners, function (callback, event) {
oldItemsData.off(event, callback);
});
// remove all drawn items
ids = oldItemsData.getIds();
this._onRemove(ids);
}
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);
}
this.updateGraph();
};
/**
* 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) {
};
/**
* Repaint the component
* @return {boolean} Returns true if the component is resized
*/
Linegraph.prototype.redraw = function() {
console.log('redraw')
// check whether zoomed (in that case we need to re-stack everything)
var visibleInterval = this.range.end - this.range.start;
var visibleInterval = this.body.range.end - this.body.range.start;
var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.width != this.lastWidth);
if (zoomed) this.stackDirty = true;
this.lastVisibleInterval = visibleInterval;
this.lastWidth = this.width;
// calculate actual size and position
this.width = this.frame.offsetWidth;
this.width = this.dom.frame.offsetWidth;
// check if this component is resized
resized = this._isResized();
var resized = this._isResized();
if (resized) {
this.svg.style.width = asSize(3*this.width);
this.svg.style.left = asSize(-this.width);
@ -3182,32 +3278,45 @@ Linegraph.prototype.redraw = function() {
}
};
/**
* Get the first group, aligned with the axis
* @return {Group | null} firstGroup
* @private
*/
Linegraph.prototype._firstGroup = function() {
var firstGroupIndex = (this.options.orientation == 'top') ? 0 : (this.groupIds.length - 1);
var firstGroupId = this.groupIds[firstGroupIndex];
var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED];
return firstGroup || null;
};
Linegraph.prototype._extractData = function(dataset) {
var extractedData = [];
var low = dataset[0].y;
var high = dataset[0].y;
var range = this.body.range.end - this.body.range.start;
var rangePerPixel = range/this.width;
var rangePerPixelInv = this.width/range;
var xOffset = -this.body.range.start + this.width*rangePerPixel;
for (var i = 0; i < dataset.length; i++) {
var val = new Date(dataset[i].x).getTime();
val += xOffset;
val *= rangePerPixelInv;
extractedData.push({x:val, y:dataset[i].y});
if (low > dataset[i].y) {
low = dataset[i].y;
}
if (high < dataset[i].y) {
high = dataset[i].y;
}
}
// extractedData.sort(function (a,b) {return a.x - b.x;});
return {range:{low:low,high:high},data:extractedData};
}
Linegraph.prototype.updateGraph = function() {
if (this.width != 0) {
var dataview = new DataView(this.timeline.itemsData,
{filter: function (item) {return (item.value);}})
if (this.width != 0 && this.itemsData != null) {
var datapoints = dataview.get();
var datapoints = this.itemsData.get();
if (datapoints != null) {
if (datapoints.length > 0) {
var dataset = this._extractData(datapoints);
var data = dataset.data;
console.log("height",data,datapoints, dataset);
this.yAxis.setRange({start:dataset.range.low,end:dataset.range.high});
this.yAxis.repaint();
data = this.yAxis.convertValues(data);
@ -3217,29 +3326,6 @@ Linegraph.prototype.updateGraph = function() {
d3 = this._catmullRom(data,0);
d2 = this._catmullRom(data,1);
// var data2 = [];
// this.startTime = this.range.start;
// var min = Date.now() - 3600000 * 24 * 30;
// var max = Date.now() + 3600000 * 24 * 10;
// var count = 60;
// var step = (max-min) / count;
//
// var range = this.range.end - this.range.start;
// var rangePerPixel = range/this.width;
// var rangePerPixelInv = this.width/range;
// var xOffset = -this.range.start + this.width*rangePerPixel;
//
// for (var i = 0; i < count; i++) {
// data2.push({x:(min + i*step + xOffset) * rangePerPixelInv, y: 250*(i%2) + 25})
// }
//
// var d2 = this._catmullRom(data2);
this.path.setAttributeNS(null, "d",d);
this.path2.setAttributeNS(null, "d",d2);
this.path3.setAttributeNS(null, "d",d3);
@ -3248,14 +3334,6 @@ Linegraph.prototype.updateGraph = function() {
}
}
/**
* Set items
* @param {vis.DataSet | null} items
*/
Linegraph.prototype.setItems = function(items) {
};
Linegraph.prototype._catmullRomUniform = function(data) {
// catmull rom

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

@ -18,12 +18,12 @@
<script type="text/javascript">
var container = document.getElementById('visualization');
var items = [
{id: 1, content: 'item 1', x: '2014-04-01', y: 10},
{id: 2, content: 'item 2', x: '2014-04-02', y: 20},
{id: 3, content: 'item 3', x: '2014-04-03', y: 30},
{id: 4, content: 'item 4', x: '2014-04-04', y: 10},
{id: 5, content: 'item 5', x: '2014-04-05', y: 20},
{id: 6, content: 'item 6', x: '2014-04-06', y: 30}
{id: 1, content: 'item 1', x: '2014-06-01', y: 10},
{id: 2, content: 'item 2', x: '2014-06-02', y: 20},
{id: 3, content: 'item 3', x: '2014-06-03', y: 30},
{id: 4, content: 'item 4', x: '2014-06-04', y: 10},
{id: 5, content: 'item 5', x: '2014-06-05', y: 20},
{id: 6, content: 'item 6', x: '2014-06-06', y: 30}
];
var options = {};
var graph2d = new vis.Graph2d(container, items, options);

+ 7
- 7
src/timeline/component/DataAxis.js View File

@ -92,9 +92,9 @@ DataAxis.prototype.repaint = function () {
this._calculateCharSize();
// TODO: recalculate sizes only needed when parent is resized or options is changed
var orientation = this.getOption('orientation');
var showMinorLabels = this.getOption('showMinorLabels');
var showMajorLabels = this.getOption('showMajorLabels');
var orientation = this.options['orientation'];
var showMinorLabels = this.options['showMinorLabels'];
var showMajorLabels = this.options['showMajorLabels'];
// determine the width and height of the elemens for the axis
props.minorLabelHeight = showMinorLabels ? props.minorCharHeight : 0;
@ -132,7 +132,7 @@ DataAxis.prototype.repaint = function () {
* @private
*/
DataAxis.prototype._repaintLabels = function () {
var orientation = this.getOption('orientation');
var orientation = this.options['orientation'];
// calculate range and step (step such that we have space for 7 characters per label)
var start = this.range.start;
@ -166,11 +166,11 @@ DataAxis.prototype._repaintLabels = function () {
y = y.toPrecision(5)
var isMajor = step.isMajor();
if (this.getOption('showMinorLabels') && isMajor == false) {
if (this.options['showMinorLabels'] && isMajor == false) {
this._repaintMinorText(y, step.getLabelMinor(), orientation);
}
if (isMajor && this.getOption('showMajorLabels')) {
if (isMajor && this.options['showMajorLabels']) {
if (y > 0) {
if (xFirstMajorLabel == undefined) {
xFirstMajorLabel = y;
@ -194,7 +194,7 @@ DataAxis.prototype._repaintLabels = function () {
// create a major label on the left when needed
if (this.getOption('showMajorLabels')) {
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

+ 143
- 65
src/timeline/component/Linegraph.js View File

@ -1,15 +1,7 @@
var UNGROUPED = '__ungrouped__'; // reserved group id for ungrouped items
/**
* An ItemSet holds a set of items and ranges which can be displayed in a
* range. The width is determined by the parent of the ItemSet, and the height
* is determined by the size of the items.
* @param {{dom: Object, domProps: Object, emitter: Emitter, range: Range}} body
* @param {Object} [options] See Linegraph.setOptions for the available options.
* @constructor ItemSet
* @extends Component
*/
function Linegraph(body, options) {
this.id = util.randomUUID();
this.body = body;
this.defaultOptions = {
@ -82,10 +74,22 @@ function Linegraph(body, options) {
// create the HTML DOM
this._create();
this.body.emitter.on("drag", this._onDrag.bind(this))
this.body.emitter.on("dragEnd", this._onDragEnd.bind(this))
this.setOptions(options);
}
Linegraph.prototype._onDrag = function (event) {
if (this.svg) {
}
}
Linegraph.prototype._onDragEnd = function (event) {
this.updateGraph();
}
Linegraph.prototype = new Component();
// available item types will be registered here
@ -117,9 +121,35 @@ Linegraph.prototype._create = function(){
frame.appendChild(foreground);
this.dom.foreground = foreground;
this.svg = document.createElementNS('http://www.w3.org/2000/svg',"svg");
this.svg.style.position = "relative"
this.svg.style.height = "300px";
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
var dataAxisOptions = {
range: this.range,
range: this.body.range,
left: null,
top: null,
width: null,
@ -129,7 +159,6 @@ Linegraph.prototype._create = function(){
this.yAxis = new DataAxis(dataAxisOptions);
this.dom.axis = this.yAxis.getFrame();
this.show();
};
@ -210,24 +239,91 @@ Linegraph.prototype.show = function() {
}
};
/**
* Set items
* @param {vis.DataSet | null} items
*/
Linegraph.prototype.setItems = function(items) {
var me = this,
ids,
oldItemsData = this.itemsData;
// replace the dataset
if (!items) {
this.itemsData = null;
}
else if (items instanceof DataSet || items instanceof DataView) {
this.itemsData = items;
}
else {
throw new TypeError('Data must be an instance of DataSet or DataView');
}
if (oldItemsData) {
// unsubscribe from old dataset
util.forEach(this.itemListeners, function (callback, event) {
oldItemsData.off(event, callback);
});
// remove all drawn items
ids = oldItemsData.getIds();
this._onRemove(ids);
}
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);
}
this.updateGraph();
};
/**
* 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) {
};
/**
* Repaint the component
* @return {boolean} Returns true if the component is resized
*/
Linegraph.prototype.redraw = function() {
console.log('redraw')
// check whether zoomed (in that case we need to re-stack everything)
var visibleInterval = this.range.end - this.range.start;
var visibleInterval = this.body.range.end - this.body.range.start;
var zoomed = (visibleInterval != this.lastVisibleInterval) || (this.width != this.lastWidth);
if (zoomed) this.stackDirty = true;
this.lastVisibleInterval = visibleInterval;
this.lastWidth = this.width;
// calculate actual size and position
this.width = this.frame.offsetWidth;
this.width = this.dom.frame.offsetWidth;
// check if this component is resized
resized = this._isResized();
var resized = this._isResized();
if (resized) {
this.svg.style.width = asSize(3*this.width);
this.svg.style.left = asSize(-this.width);
@ -237,32 +333,45 @@ Linegraph.prototype.redraw = function() {
}
};
/**
* Get the first group, aligned with the axis
* @return {Group | null} firstGroup
* @private
*/
Linegraph.prototype._firstGroup = function() {
var firstGroupIndex = (this.options.orientation == 'top') ? 0 : (this.groupIds.length - 1);
var firstGroupId = this.groupIds[firstGroupIndex];
var firstGroup = this.groups[firstGroupId] || this.groups[UNGROUPED];
return firstGroup || null;
};
Linegraph.prototype._extractData = function(dataset) {
var extractedData = [];
var low = dataset[0].y;
var high = dataset[0].y;
var range = this.body.range.end - this.body.range.start;
var rangePerPixel = range/this.width;
var rangePerPixelInv = this.width/range;
var xOffset = -this.body.range.start + this.width*rangePerPixel;
for (var i = 0; i < dataset.length; i++) {
var val = new Date(dataset[i].x).getTime();
val += xOffset;
val *= rangePerPixelInv;
extractedData.push({x:val, y:dataset[i].y});
if (low > dataset[i].y) {
low = dataset[i].y;
}
if (high < dataset[i].y) {
high = dataset[i].y;
}
}
// extractedData.sort(function (a,b) {return a.x - b.x;});
return {range:{low:low,high:high},data:extractedData};
}
Linegraph.prototype.updateGraph = function() {
if (this.width != 0) {
var dataview = new DataView(this.timeline.itemsData,
{filter: function (item) {return (item.value);}})
if (this.width != 0 && this.itemsData != null) {
var datapoints = dataview.get();
var datapoints = this.itemsData.get();
if (datapoints != null) {
if (datapoints.length > 0) {
var dataset = this._extractData(datapoints);
var data = dataset.data;
console.log("height",data,datapoints, dataset);
this.yAxis.setRange({start:dataset.range.low,end:dataset.range.high});
this.yAxis.repaint();
data = this.yAxis.convertValues(data);
@ -272,29 +381,6 @@ Linegraph.prototype.updateGraph = function() {
d3 = this._catmullRom(data,0);
d2 = this._catmullRom(data,1);
// var data2 = [];
// this.startTime = this.range.start;
// var min = Date.now() - 3600000 * 24 * 30;
// var max = Date.now() + 3600000 * 24 * 10;
// var count = 60;
// var step = (max-min) / count;
//
// var range = this.range.end - this.range.start;
// var rangePerPixel = range/this.width;
// var rangePerPixelInv = this.width/range;
// var xOffset = -this.range.start + this.width*rangePerPixel;
//
// for (var i = 0; i < count; i++) {
// data2.push({x:(min + i*step + xOffset) * rangePerPixelInv, y: 250*(i%2) + 25})
// }
//
// var d2 = this._catmullRom(data2);
this.path.setAttributeNS(null, "d",d);
this.path2.setAttributeNS(null, "d",d2);
this.path3.setAttributeNS(null, "d",d3);
@ -303,14 +389,6 @@ Linegraph.prototype.updateGraph = function() {
}
}
/**
* Set items
* @param {vis.DataSet | null} items
*/
Linegraph.prototype.setItems = function(items) {
};
Linegraph.prototype._catmullRomUniform = function(data) {
// catmull rom

Loading…
Cancel
Save