Skip to content

Commit 0885006

Browse files
committed
Merge pull request jacomyal#725 from jotunacorn/master
Adding dots to the beginning and end of edges
2 parents 23efcdf + c27271f commit 0885006

File tree

5 files changed

+411
-2
lines changed

5 files changed

+411
-2
lines changed

Gruntfile.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@ module.exports = function(grunt) {
3939
'src/renderers/canvas/sigma.canvas.hovers.def.js',
4040
'src/renderers/canvas/sigma.canvas.nodes.def.js',
4141
'src/renderers/canvas/sigma.canvas.edges.def.js',
42-
'src/renderers/canvas/sigma.canvas.edges.curve.js',
42+
'src/renderers/canvas/sigma.canvas.edges.dotCurve.js',
4343
'src/renderers/canvas/sigma.canvas.edges.arrow.js',
44-
'src/renderers/canvas/sigma.canvas.edges.curvedArrow.js',
44+
'src/renderers/canvas/sigma.canvas.edges.dotCurvedArrow.js',
4545
'src/renderers/canvas/sigma.canvas.edgehovers.def.js',
4646
'src/renderers/canvas/sigma.canvas.edgehovers.curve.js',
4747
'src/renderers/canvas/sigma.canvas.edgehovers.arrow.js',
@@ -83,6 +83,7 @@ module.exports = function(grunt) {
8383
'plugins.relativeSize',
8484
'renderers.customEdgeShapes',
8585
'renderers.customShapes',
86+
'renderers.edgeDots',
8687
'renderers.edgeLabels',
8788
'renderers.parallelEdges',
8889
'renderers.snapshot',

examples/plugin-edgeDots.html

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<!-- START SIGMA IMPORTS -->
2+
<script src="../src/sigma.core.js"></script>
3+
<script src="../src/conrad.js"></script>
4+
<script src="../src/utils/sigma.utils.js"></script>
5+
<script src="../src/utils/sigma.polyfills.js"></script>
6+
<script src="../src/sigma.settings.js"></script>
7+
<script src="../src/classes/sigma.classes.dispatcher.js"></script>
8+
<script src="../src/classes/sigma.classes.configurable.js"></script>
9+
<script src="../src/classes/sigma.classes.graph.js"></script>
10+
<script src="../src/classes/sigma.classes.camera.js"></script>
11+
<script src="../src/classes/sigma.classes.quad.js"></script>
12+
<script src="../src/classes/sigma.classes.edgequad.js"></script>
13+
<script src="../src/captors/sigma.captors.mouse.js"></script>
14+
<script src="../src/captors/sigma.captors.touch.js"></script>
15+
<script src="../src/renderers/sigma.renderers.canvas.js"></script>
16+
<script src="../src/renderers/sigma.renderers.webgl.js"></script>
17+
<script src="../src/renderers/sigma.renderers.svg.js"></script>
18+
<script src="../src/renderers/sigma.renderers.def.js"></script>
19+
<script src="../src/renderers/webgl/sigma.webgl.nodes.def.js"></script>
20+
<script src="../src/renderers/webgl/sigma.webgl.nodes.fast.js"></script>
21+
<script src="../src/renderers/webgl/sigma.webgl.edges.def.js"></script>
22+
<script src="../src/renderers/webgl/sigma.webgl.edges.fast.js"></script>
23+
<script src="../src/renderers/webgl/sigma.webgl.edges.arrow.js"></script>
24+
<script src="../src/renderers/canvas/sigma.canvas.labels.def.js"></script>
25+
<script src="../src/renderers/canvas/sigma.canvas.hovers.def.js"></script>
26+
<script src="../src/renderers/canvas/sigma.canvas.nodes.def.js"></script>
27+
<script src="../src/renderers/canvas/sigma.canvas.edges.def.js"></script>
28+
<script src="../src/renderers/canvas/sigma.canvas.edges.curve.js"></script>
29+
<script src="../src/renderers/canvas/sigma.canvas.edges.arrow.js"></script>
30+
<script src="../src/renderers/canvas/sigma.canvas.edges.curvedArrow.js"></script>
31+
<script src="../src/renderers/canvas/sigma.canvas.edgehovers.def.js"></script>
32+
<script src="../src/renderers/canvas/sigma.canvas.edgehovers.curve.js"></script>
33+
<script src="../src/renderers/canvas/sigma.canvas.edgehovers.arrow.js"></script>
34+
<script src="../src/renderers/canvas/sigma.canvas.edgehovers.curvedArrow.js"></script>
35+
<script src="../src/renderers/canvas/sigma.canvas.extremities.def.js"></script>
36+
<script src="../src/renderers/svg/sigma.svg.utils.js"></script>
37+
<script src="../src/renderers/svg/sigma.svg.nodes.def.js"></script>
38+
<script src="../src/renderers/svg/sigma.svg.edges.def.js"></script>
39+
<script src="../src/renderers/svg/sigma.svg.edges.curve.js"></script>
40+
<script src="../src/renderers/svg/sigma.svg.labels.def.js"></script>
41+
<script src="../src/renderers/svg/sigma.svg.hovers.def.js"></script>
42+
<script src="../src/middlewares/sigma.middlewares.rescale.js"></script>
43+
<script src="../src/middlewares/sigma.middlewares.copy.js"></script>
44+
<script src="../src/misc/sigma.misc.animation.js"></script>
45+
<script src="../src/misc/sigma.misc.bindEvents.js"></script>
46+
<script src="../src/misc/sigma.misc.bindDOMEvents.js"></script>
47+
<script src="../src/misc/sigma.misc.drawHovers.js"></script>
48+
<!-- END SIGMA IMPORTS -->
49+
<script src="../plugins/sigma.renderers.edgeDots/sigma.canvas.edges.dotCurve.js"></script>
50+
<div id="container">
51+
<style>
52+
#graph-container {
53+
top: 0;
54+
bottom: 0;
55+
left: 0;
56+
right: 0;
57+
position: absolute;
58+
}
59+
</style>
60+
<div id="graph-container"></div>
61+
</div>
62+
<script>
63+
/**
64+
* This example shows how the edgeDots plugin can be used to display dots
65+
* on the edges near the nodes in the graph.
66+
*/
67+
var i,
68+
s,
69+
N = 2,
70+
E = 1,
71+
g = {
72+
nodes: [],
73+
edges: []
74+
};
75+
76+
// Generate a random graph:
77+
for (i = 0; i < N; i++)
78+
g.nodes.push({
79+
id: 'n' + i,
80+
label: 'Node ' + i,
81+
x: Math.random(),
82+
y: Math.random(),
83+
size: Math.random(),
84+
color: '#666'
85+
});
86+
// Some colors to use on the dots
87+
var colors = ["#ff0000", "#00ff00", "#0000ff"];
88+
for (i = 0; i < E; i++)
89+
g.edges.push({
90+
id: 'e' + i,
91+
label: 'Edge ' + i,
92+
source: 'n0',
93+
target: 'n1',
94+
size: Math.random(),
95+
color: '#ccc',
96+
type: 'curve',
97+
dotOffset:4,
98+
dotSize:1.2,
99+
sourceDotColor:colors[i%colors.length],
100+
targetDotColor:colors[(i+1)%colors.length]
101+
});
102+
103+
// Instantiate sigma:
104+
s = new sigma({
105+
graph: g,
106+
renderer: {
107+
container: document.getElementById('graph-container'),
108+
type: 'canvas'
109+
}
110+
});
111+
</script>
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
sigma.renderers.edgeDots
2+
========================
3+
4+
Plugin developed by [Joakim af Sandeberg](https://github.com/jotunacorn).
5+
6+
Contact: joakim.afs+github@gmail.com
7+
8+
---
9+
## General
10+
This plugin adds the option to show colored dots near the source and target of an edge when using the canvas renderer.
11+
12+
See the following [example](../../examples/plugin-edgeDots.html) for full usage.
13+
14+
To use it, include all .js files under this folder.
15+
16+
## Edges
17+
18+
This plugin extends Sigma.js canvas edges:
19+
* **sourceDotColor**
20+
* The value to use as color for the source dot. If left undefined there will be no dot at the source.
21+
* type: *string*
22+
* default value: undefined
23+
* **targetDotColor**
24+
* The value to use as color for the target dot. If left undefined there will be no dot at the target.
25+
* type: *string*
26+
* default value: undefined
27+
* **dotOffset**
28+
* The value which define the distance between the dots and the nodes, relative to the node size.
29+
* type: *number*
30+
* default value: 3
31+
* **dotSize**
32+
* The value which define the size of the dot relative to the edge.
33+
* type: *number*
34+
* default value: 1
35+
## Renderers
36+
37+
This plugin modifies the sigma.canvas.edges.curve and sigma.canvas.edges.curvedArrow
38+
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
;(function() {
2+
'use strict';
3+
4+
sigma.utils.pkg('sigma.canvas.edges');
5+
6+
/**
7+
* This edge renderer will display edges as curves.
8+
*
9+
* @param {object} edge The edge object.
10+
* @param {object} source node The edge source node.
11+
* @param {object} target node The edge target node.
12+
* @param {CanvasRenderingContext2D} context The canvas context.
13+
* @param {configurable} settings The settings function.
14+
*/
15+
sigma.canvas.edges.dotCurve = function(edge, source, target, context, settings) {
16+
var color = edge.color,
17+
prefix = settings('prefix') || '',
18+
size = edge[prefix + 'size'] || 1,
19+
edgeColor = settings('edgeColor'),
20+
defaultNodeColor = settings('defaultNodeColor'),
21+
defaultEdgeColor = settings('defaultEdgeColor'),
22+
cp = {},
23+
sSize = source[prefix + 'size'],
24+
sX = source[prefix + 'x'],
25+
sY = source[prefix + 'y'],
26+
tX = target[prefix + 'x'],
27+
tY = target[prefix + 'y'];
28+
29+
cp = (source.id === target.id) ?
30+
sigma.utils.getSelfLoopControlPoints(sX, sY, sSize) :
31+
sigma.utils.getQuadraticControlPoint(sX, sY, tX, tY);
32+
33+
if (!color)
34+
switch (edgeColor) {
35+
case 'source':
36+
color = source.color || defaultNodeColor;
37+
break;
38+
case 'target':
39+
color = target.color || defaultNodeColor;
40+
break;
41+
default:
42+
color = defaultEdgeColor;
43+
break;
44+
}
45+
46+
context.strokeStyle = color;
47+
context.lineWidth = size;
48+
context.beginPath();
49+
context.moveTo(sX, sY);
50+
if (source.id === target.id) {
51+
context.bezierCurveTo(cp.x1, cp.y1, cp.x2, cp.y2, tX, tY);
52+
} else {
53+
context.quadraticCurveTo(cp.x, cp.y, tX, tY);
54+
}
55+
context.stroke();
56+
if(edge.sourceDotColor != undefined || edge.targetDotColor != undefined) {
57+
var dotOffset = edge.dotOffset || 3;
58+
var dotSize = edge.dotSize || 1;
59+
dotSize = size*dotSize;
60+
dotOffset = dotOffset*sSize;
61+
if(edge.sourceDotColor != undefined) {
62+
createDot(context, sX, sY, cp, tX, tY, dotOffset, dotSize, edge.sourceDotColor);
63+
}
64+
if (edge.targetDotColor != undefined){
65+
createDot(context, tX, tY, cp, sX, sY, dotOffset, dotSize, edge.targetDotColor);
66+
}
67+
}
68+
};
69+
70+
function createDot(context, sX, sY, cp, tX, tY, offset, size, color) {
71+
context.beginPath();
72+
context.fillStyle = color;
73+
var dot = getPointOnBezier(sX, sY, cp.x, cp.y, tX, tY,
74+
offset);
75+
context.arc(dot.x, dot.y, size * 3, 0, 2 * Math.PI,
76+
false);
77+
context.fill();
78+
}
79+
80+
function getQBezierValue(t, p1, p2, p3) {
81+
var iT = 1 - t;
82+
return iT * iT * p1 + 2 * iT * t * p2 + t * t * p3;
83+
}
84+
85+
function getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, position) {
86+
return {
87+
x:getQBezierValue(position, startX, cpX, endX),
88+
y:getQBezierValue(position, startY, cpY, endY)
89+
};
90+
}
91+
function getDistanceBetweenPoints(x1, y1, x2, y2){
92+
return Math.sqrt((x2-x1)*(x2-x1) + (y2-y1)*(y2-y1));
93+
}
94+
/* Function to get a point on a bezier curve a certain distance away from
95+
its source. Needed since the position on a beziercurve is given to the
96+
formula as a percentage (t).*/
97+
function getPointOnBezier(startX, startY, cpX, cpY, endX, endY, distance){
98+
var bestT = 0;
99+
var bestAccuracy = 1000;
100+
var stepSize = 0.001;
101+
for(var t = 0; t<1; t+=stepSize){
102+
var currentPoint = getQuadraticCurvePoint(startX, startY, cpX, cpY,
103+
endX, endY, t);
104+
var currentDistance = getDistanceBetweenPoints(startX, startY,
105+
currentPoint.x, currentPoint.y);
106+
if(Math.abs(currentDistance-distance) < bestAccuracy){
107+
bestAccuracy = Math.abs(currentDistance-distance);
108+
bestT = t;
109+
}
110+
}
111+
return getQuadraticCurvePoint(startX, startY, cpX, cpY, endX, endY, bestT);
112+
}
113+
114+
})();

0 commit comments

Comments
 (0)