Browse Source

Merge pull request #1030 from mschallar/mschallar/develop

Added  feature drawPoints.onRender
flowchartTest
Alex 9 years ago
parent
commit
9d3157a9cb
7 changed files with 224 additions and 41 deletions
  1. +69
    -11
      docs/graph2d/index.html
  2. +81
    -11
      examples/graph2d/19_labels.html
  3. +15
    -15
      lib/DOMutil.js
  4. +7
    -0
      lib/timeline/Core.js
  5. +13
    -1
      lib/timeline/component/GraphGroup.js
  6. +37
    -2
      lib/timeline/component/graph2d_types/points.js
  7. +2
    -1
      lib/timeline/optionsGraph2d.js

+ 69
- 11
docs/graph2d/index.html View File

@ -158,7 +158,7 @@
<p>
The following code shows how to create a Graph2d and provide it with data.
More examples can be found in the <a href="../examples">examples</a> directory.</p>
More examples can be found in the <a href="../../examples">examples</a> directory.</p>
<pre class="prettyprint lang-html options">
&lt;!DOCTYPE HTML&gt;
@ -424,8 +424,8 @@ var options = {
<td>Boolean</td>
<td>false</td>
<td>If two datapoints of a barchart overlap, they are drawn over eachother by default. If sideBySide is set to true, they will be drawn side by side.
See <a href="../examples/graph2d/10_barsSideBySide.html">example 10</a> for more information.
When using groups, see <a href="../examples/graph2d/11_barsSideBySideGroups.html">example 11</a>.
See <a href="../../examples/graph2d/10_barsSideBySide.html">example 10</a> for more information.
When using groups, see <a href="../../examples/graph2d/11_barsSideBySideGroups.html">example 11</a>.
</td>
</tr>
<tr parent="barChart" class="hidden">
@ -546,15 +546,73 @@ function (value) {
</tr>
<tr class='toggle collapsible' onclick="toggleTable('g2dOptions','drawPoints', this);">
<td class="greenField"><span parent="drawPoints" class="right-caret"></span> drawPoints</td>
<td>Boolean or Object</td>
<td>Boolean, Object or Function</td>
<td>true</td>
<td>Toggle the drawing of the datapoints with the default settings.</td>
<td>Defines rendering options for the datapoints.
Three different types of objects can be assigned to this property. See <a href="../../examples/graph2d/19_labels.html">Example 19</a> for an illustration.<br />
1. <code>Boolean</code>: When true is provided every datapoint will be drawn, false otherwise.<br />
<pre class="prettyprint lang-js">
drawPoints: true // or false
</pre>
2. <code>Object</code> (the 'rendering' options): If an object is provided it may contain following properties which all can be optional: <code>onRender</code>, <code>className</code><code>size</code> and/or <code>style</code>. For more information check the property's documentation.<br />
<pre class="prettyprint lang-js">
drawPoints: {
size: 3,
style: 'square'
}
</pre>
3. <code>Function</code>: If a function is provided it will be used as a callback. The function may return values from listing 1 or 2.<br />
<pre class="prettyprint lang-js">
drawPoints: function(item, group, graph2d) {
...
}
</pre>
If a rendering property from the rendering option object is missing, the missing property will be fetched from the group's option.
<br />
All of these three options can be defined within the drawPoints properties separately as well.
</td>
</tr>
<tr parent="drawPoints" class="hidden">
<td class="greenField indent">drawPoints.enabled</td>
<td>Boolean</td>
<td>true</td>
<td>Toggle the drawing of the datapoints.</td>
<td>Toggles the drawing of the datapoints.</td>
</tr>
<tr parent="drawPoints" class="hidden">
<td class="greenField indent">drawPoints.onRender</td>
<td>function</td>
<td>none</td>
<td>Defines a render function for every datapoint.
If a group has no <code>drawPoints.onRender</code> callback, the graph2d <code>drawPoints.onRender</code> callback will be used.
If neither is defined, the datapoint will be rendered according to the group setting of <code>drawPoints.enabled</code>.
This callback must return <code>true</code> if the datapoint should be rendered, otherwise <code>false</code>.
<pre class="prettyprint lang-js">
drawPoints: {
enabled: true,
onRender: function(item, group, graph2d) {
// only renders items with labels
return item.label != null;
}
}
</pre>
This callback may also return an object containing a <code>size</code> and <code>style</code> property, both are optional, e.g.:
<pre class="prettyprint lang-js">
onRender: function(item, group, graph2d) {
if (item.label == null) {
return false;
}
return {
style: 'circle',
size: 30
};
}
</pre>
The properties <code>className</code>, <code>style</code> and <code>size</code> returned from the callback will be used for rendering the datapoint.
If a property is missing in the rendering option object, the missing property will be fetched from the group's option.
</td>
</tr>
<tr parent="drawPoints" class="hidden">
<td class="greenField indent">drawPoints.size</td>
@ -581,7 +639,7 @@ function (value) {
<td>Object</td>
<td></td>
<td>You can use this to toggle the visibility of groups per graph2D instance. This is different from setting the visibility flag of the groups since
this is not communicated across instances of graph2d. Take a look at <a href="../examples/graph2d/14_toggleGroups.html">Example 14</a>
this is not communicated across instances of graph2d. Take a look at <a href="../../examples/graph2d/14_toggleGroups.html">Example 14</a>
for more explanation.
</td>
</tr>
@ -601,7 +659,7 @@ function (value) {
<td class="greenField indent">interpolation.parametrization</td>
<td>String</td>
<td>'centripetal'</td>
<td>Define the type of parametrizaion for the catmullRom interpolation. <a href="../examples/graph2d/07_scrollingAndSorting.html">Example 7</a> shows the different parametrizations. The options are 'centripetal' (best results), 'chordal' and 'uniform'. Uniform is the computationally cheapest variant.
<td>Define the type of parametrizaion for the catmullRom interpolation. <a href="../../examples/graph2d/07_scrollingAndSorting.html">Example 7</a> shows the different parametrizations. The options are 'centripetal' (best results), 'chordal' and 'uniform'. Uniform is the computationally cheapest variant.
If interpolation is disabled, linear interpolation is used.</td>
</tr>
<tr class='toggle collapsible' onclick="toggleTable('g2dOptions','legend', this);">
@ -700,7 +758,7 @@ function (value) {
<td class="greenField">yAxisOrientation</td>
<td>String</td>
<td>'left'</td>
<td>This defines with which axis, left or right, the graph is coupled. <a href="../examples/graph2d/05_bothAxis.html">Example 5</a> shows groups with different Y axis. If no groups are coupled
<td>This defines with which axis, left or right, the graph is coupled. <a href="../../examples/graph2d/05_bothAxis.html">Example 5</a> shows groups with different Y axis. If no groups are coupled
with an axis, it will not be shown.</td>
</tr>
</table>
@ -1341,8 +1399,8 @@ Graph2d.off('rangechanged', onChange);
</p>
<p>
Additionally, Graph2d has 10 preset styles for graphs, which are cycled through when loading groups. These styles can be overwritten
as well, along with defining your own classes to style the graphs! <a href="../examples/graph2d/04_rightAxis.html">Example 4</a> and
<a href="../examples/graph2d/05_bothAxis.html">example 5</a> show the usage of custom styles.
as well, along with defining your own classes to style the graphs! <a href="../../examples/graph2d/04_rightAxis.html">Example 4</a> and
<a href="../../examples/graph2d/05_bothAxis.html">example 5</a> show the usage of custom styles.
</p>
</div>

+ 81
- 11
examples/graph2d/19_labels.html View File

@ -35,31 +35,101 @@
var container = document.getElementById('visualization');
var label1 = {
content: "offset label",
content: "Label 1 (with offset)",
xOffset: 20,
yOffset: 20
}
var label2 = {
content: "Label2",
content: "Label 2",
className: "red"
}
var label3 = {
content: "Label 3"
}
var items = [
{x: '2014-06-11', y: 10,label:label1},
{x: '2014-06-12', y: 25,label:label2},
{x: '2014-06-13', y: 30},
{x: '2014-06-14', y: 10},
{x: '2014-06-15', y: 15},
{x: '2014-06-16', y: 30}
{group: 1, x: '2014-06-11', y: 10, label: label1},
{group: 1, x: '2014-06-12', y: 25, label: label2},
{group: 1, x: '2014-06-13', y: 30},
{group: 1, x: '2014-06-14', y: 10},
{group: 1, x: '2014-06-15', y: 15, label: label3},
{group: 1, x: '2014-06-16', y: 30},
{group: 2, x: '2014-06-17', y: 10, label:label1},
{group: 2, x: '2014-06-18', y: 25, label:label2},
{group: 2, x: '2014-06-19', y: 30},
{group: 2, x: '2014-06-20', y: 10},
{group: 2, x: '2014-06-21', y: 15, label: label3},
{group: 2, x: '2014-06-22', y: 30},
{group: 3, x: '2014-06-23', y: 10, label:label1},
{group: 3, x: '2014-06-24', y: 25, label:label2},
{group: 3, x: '2014-06-25', y: 30},
{group: 3, x: '2014-06-26', y: 10},
{group: 3, x: '2014-06-27', y: 15, label: label3},
{group: 3, x: '2014-06-28', y: 30}
];
var groups = new vis.DataSet();
groups.add(
{
id: 1,
content: "Only draw items with labels. Make the data point bigger and a square.",
options: {
drawPoints: function group1Renderer(item, group, grap2d) {
if (item.label == null) {
return false;
}
return {
style: 'square',
size: 15
};
}
}
}
);
groups.add(
{
id: 2,
content: "Draw according to the Graph2d callback, but make it every datapoint square one.",
options: {
drawPoints: {
style: 'square'
}
}
}
);
groups.add(
{
id: 3,
content: "I want to render datapoints with no labels. Screw the graph2d options. Except the style/size should be according to the graph2d option.",
options: {
drawPoints: function(item, group, grap2d) {
return item.label == null;
}
}
}
);
var dataset = new vis.DataSet(items);
var options = {
start: '2014-06-10',
end: '2014-06-18',
style:'bar'
end: '2014-06-29',
style: 'bar',
drawPoints: {
onRender: function(item, group, grap2d) {
return item.label != null;
},
style: 'circle'
}
};
var graph2d = new vis.Graph2d(container, dataset, options);
var graph2d = new vis.Graph2d(container, dataset, groups, options);
</script>
</body>
</html>

+ 15
- 15
lib/DOMutil.js View File

@ -121,43 +121,43 @@ exports.getDOMElement = function (elementType, JSONcontainer, DOMContainer, inse
/**
* draw a point object. this is a seperate function because it can also be called by the legend.
* Draw a point object. This is a separate function because it can also be called by the legend.
* The reason the JSONcontainer and the target SVG svgContainer have to be supplied is so the legend can use these functions
* as well.
*
* @param x
* @param y
* @param group
* @param groupTemplate: A template containing the necessary information to draw the datapoint e.g., {style: 'circle', size: 5, className: 'className' }
* @param JSONcontainer
* @param svgContainer
* @param labelObj
* @returns {*}
*/
exports.drawPoint = function(x, y, group, JSONcontainer, svgContainer, labelObj) {
exports.drawPoint = function(x, y, groupTemplate, JSONcontainer, svgContainer, labelObj) {
var point;
if (group.options.drawPoints.style == 'circle') {
point = exports.getSVGElement('circle',JSONcontainer,svgContainer);
if (groupTemplate.style == 'circle') {
point = exports.getSVGElement('circle', JSONcontainer, svgContainer);
point.setAttributeNS(null, "cx", x);
point.setAttributeNS(null, "cy", y);
point.setAttributeNS(null, "r", 0.5 * group.options.drawPoints.size);
point.setAttributeNS(null, "r", 0.5 * groupTemplate.size);
}
else {
point = exports.getSVGElement('rect',JSONcontainer,svgContainer);
point.setAttributeNS(null, "x", x - 0.5*group.options.drawPoints.size);
point.setAttributeNS(null, "y", y - 0.5*group.options.drawPoints.size);
point.setAttributeNS(null, "width", group.options.drawPoints.size);
point.setAttributeNS(null, "height", group.options.drawPoints.size);
point = exports.getSVGElement('rect', JSONcontainer, svgContainer);
point.setAttributeNS(null, "x", x - 0.5 * groupTemplate.size);
point.setAttributeNS(null, "y", y - 0.5 * groupTemplate.size);
point.setAttributeNS(null, "width", groupTemplate.size);
point.setAttributeNS(null, "height", groupTemplate.size);
}
if(group.options.drawPoints.styles !== undefined) {
point.setAttributeNS(null, "style", group.group.options.drawPoints.styles);
if (groupTemplate.style !== undefined) {
point.setAttributeNS(null, "style", groupTemplate.style);
}
point.setAttributeNS(null, "class", group.className + " vis-point");
point.setAttributeNS(null, "class", groupTemplate.className + " vis-point");
//handle label
if (labelObj) {
var label = exports.getSVGElement('text',JSONcontainer,svgContainer);
var label = exports.getSVGElement('text', JSONcontainer, svgContainer);
if (labelObj.xOffset) {
x = x + labelObj.xOffset;
}

+ 7
- 0
lib/timeline/Core.js View File

@ -254,6 +254,13 @@ Core.prototype.setOptions = function (options) {
}
}
// if the graph2d's drawPoints is a function delegate the callback to the onRender property
if (typeof options.drawPoints == 'function') {
options.drawPoints = {
onRender: options.drawPoints
};
}
if ('hiddenDates' in this.options) {
DateUtil.convertHiddenOptions(this.body, this.options.hiddenDates);
}

+ 13
- 1
lib/timeline/component/GraphGroup.js View File

@ -69,6 +69,13 @@ GraphGroup.prototype.setOptions = function(options) {
var fields = ['sampling','style','sort','yAxisOrientation','barChart'];
util.selectiveDeepExtend(fields, this.options, options);
// if the group's drawPoints is a function delegate the callback to the onRender property
if (typeof options.drawPoints == 'function') {
options.drawPoints = {
onRender: options.drawPoints
}
}
util.mergeOptions(this.options, options,'interpolation');
util.mergeOptions(this.options, options,'drawPoints');
util.mergeOptions(this.options, options,'shaded');
@ -162,7 +169,12 @@ GraphGroup.prototype.drawIcon = function(x, y, JSONcontainer, SVGcontainer, icon
}
if (this.options.drawPoints.enabled == true) {
DOMutil.drawPoint(x + 0.5 * iconWidth,y, this, JSONcontainer, SVGcontainer);
var groupTemplate = {
style: this.options.drawPoints.style,
size:this.options.drawPoints.size,
className: this.className
};
DOMutil.drawPoint(x + 0.5 * iconWidth, y, groupTemplate, JSONcontainer, SVGcontainer);
}
}
else {

+ 37
- 2
lib/timeline/component/graph2d_types/points.js View File

@ -30,10 +30,45 @@ Points.prototype.draw = function(dataset, group, framework, offset) {
* @param {Number} [offset]
*/
Points.draw = function (dataset, group, framework, offset) {
if (offset === undefined) {offset = 0;}
offset = offset || 0;
var callback = getCallback();
for (var i = 0; i < dataset.length; i++) {
DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, group, framework.svgElements, framework.svg, dataset[i].label);
if (!callback) {
// draw the point the simple way.
DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, getGroupTemplate(), framework.svgElements, framework.svg, dataset[i].label);
} else {
var callbackResult = callback(dataset[i], group, framework); // result might be true, false or an object
if (callbackResult === true || typeof callbackResult === 'object') {
DOMutil.drawPoint(dataset[i].x + offset, dataset[i].y, getGroupTemplate(callbackResult), framework.svgElements, framework.svg, dataset[i].label);
}
}
}
function getGroupTemplate(callbackResult) {
callbackResult = (typeof callbackResult === 'undefined') ? {} : callbackResult;
return {
style: callbackResult.style || group.options.drawPoints.style,
size: callbackResult.size || group.options.drawPoints.size,
className: callbackResult.className || group.className
};
}
function getCallback() {
var callback = undefined;
// check for the graph2d onRender
if (framework.options.drawPoints.onRender && typeof framework.options.drawPoints.onRender == 'function') {
callback = framework.options.drawPoints.onRender;
}
// override it with the group onRender if defined
if (group.group.options && group.group.options.drawPoints && group.group.options.drawPoints.onRender && typeof group.group.options.drawPoints.onRender == 'function') {
callback = group.group.options.drawPoints.onRender;
}
return callback;
}
};
};

+ 2
- 1
lib/timeline/optionsGraph2d.js View File

@ -51,9 +51,10 @@ let allOptions = {
},
drawPoints: {
enabled: {boolean},
onRender: { 'function': 'function' },
size: {number},
style: {string:['square','circle']}, // square, circle
__type__: {object,boolean}
__type__: {object,boolean,'function': 'function'}
},
dataAxis: {
showMinorLabels: {boolean},

Loading…
Cancel
Save