Related
I modified this component in a seperate project. It was working just fine. Then i copied that segment into my main project. The graph is rendered with no problem however, when i try to change position of any node it does not work and creates these errors.
enter image description here
The versions of d3 are the same in both of the projects. I thought it might be caused by some other component and i tried to render it in app.js on its own and it still did not work. I wonder what causes this and cannot find it.
import * as React from "react";
import { Graph } from "react-d3-graph";
const data = { nodes: [
{ id: "NEWS1", color: "black", size: 800 },
{ id: "NEWS2", color: "black", size: 800 },
{ id: "NEWS3", color: "black", size: 800 },
{ id: "NEWS4", color: "black", size: 800 },
{ id: "Sharer1", color: "red", size: 300 },
{ id: "Sharer2", color: "green", size: 300 },
{ id: "Sharer3", color: "red", size: 300 },
{ id: "Sharer4", color: "red", size: 300 },
{ id: "Sharer11", color: "red", size: 300 },
{ id: "Sharer12", color: "red", size: 300 },
{ id: "Sharer13", color: "red", size: 300 },
{ id: "Sharer21", color: "red", size: 300 },
{ id: "Sharer22", color: "red", size: 300 },
{ id: "Sharer23", color: "red", size: 300 },
{ id: "Sharer31", color: "red", size: 300 },
{ id: "Sharer32", color: "red", size: 300 },
{ id: "Sharer33", color: "red", size: 300 },
{ id: "Sharer41", color: "red", size: 300 },
{ id: "Sharer411", color: "red", size: 300 },
{ id: "Sharer4111", color: "red", size: 300 } ],
links: [
{ source: "NEWS1", target: "Sharer1" },
{ source: "NEWS2", target: "Sharer2" },
{ source: "NEWS3", target: "Sharer3" },
{ source: "NEWS4", target: "Sharer4" },
{ source: "Sharer1", target: "Sharer11" },
{ source: "Sharer1", target: "Sharer12" },
{ source: "Sharer1", target: "Sharer13" },
{ source: "Sharer2", target: "Sharer21" },
{ source: "Sharer2", target: "Sharer22" },
{ source: "Sharer2", target: "Sharer23" },
{ source: "Sharer3", target: "Sharer31" },
{ source: "Sharer3", target: "Sharer32" },
{ source: "Sharer3", target: "Sharer33" },
{ source: "Sharer4", target: "Sharer41" },
{ source: "Sharer41", target: "Sharer411" },
{ source: "Sharer411", target: "Sharer4111" } ] };
const myConfig = { nodeHighlightBehavior: true, node: {
color: "lightgreen",
size: 120,
labelProperty: "id",
highlightStrokeColor: "blue" }, link: {
type: "LINE_SMOOTH",
highlightColor: "red" } };
function NetworkGraph() {
const [state,showModal] = React.useState(false)
const handleShowMessageClick = (id) => showModal(true);
const handleCloseModal = (id) => showModal(false); const onClickGraph = () => {
// window.alert(`Clicked the graph background`); };
const onClickNode = (nodeId) => {
// };
const onDoubleClickNode = (nodeId) => {
// window.alert(`Double clicked node ${nodeId}`); };
const onRightClickNode = (event, nodeId) => {
// window.alert(`Right clicked node ${nodeId}`); };
const onMouseOverNode = (nodeId) => {
//handleShowMessageClick(nodeId); };
const onMouseOutNode = (nodeId) => {
//handleCloseModal(nodeId); };
const onClickLink = (source, target) => {
// window.alert(`Clicked link between ${source} and ${target}`); };
const onRightClickLink = (event, source, target) => {
// window.alert(`Right clicked link between ${source} and ${target}`); };
const onMouseOverLink = (source, target) => {
// window.alert(`Mouse over in link between ${source} and ${target}`); };
const onMouseOutLink = (source, target) => {
// window.alert(`Mouse out link between ${source} and ${target}`); };
return (
<div>
<Graph
id="graph-id"
data={data}
config={myConfig}
onClickNode={onClickNode}
onRightClickNode={onRightClickNode}
onClickGraph={onClickGraph}
onClickLink={onClickLink}
onRightClickLink={onRightClickLink}
onMouseOverNode={onMouseOverNode}
onMouseOutNode={onMouseOutNode}
onMouseOverLink={onMouseOverLink}
onMouseOutLink={onMouseOutLink}
/>
</div> ); }
export default NetworkGraph
I'm traying to contain the objects inside of cytoscape canvas without moving outside of max width and height, but if i drag the objects inside of canvas , they go outside of canvas border:
Actually i'm not using the canvas from HTML5, instead im using the canvas from cytoscape.js plugin so this makes more complicated to fix it.
I already saw cystoscape documentation to see if there are any kind of option to make the borders fixed and make the content inside resposive,but didnt found anything.
I would like to kow if there any way to trick this.
my code test:
cystoscape box test
``
$(document).ready(function () {
// document.addEventListener('DOMContentLoaded', function() {
$('#cyto').attr("title", "try clicking and dragging around the canvas and nodes");
tippy('#cyto')
cy = cytoscape({
container: document.getElementById('cyto'),
style: cytoscape.stylesheet()
// style for the nodes
.selector('node')
.css({
'width': 70,
'height': 70,
'content': 'data(id)',
'text-align': 'center',
'color': '#506874',
'background-color': '#20b2aa',
'font-family': 'Oswald',
'shape': 'roundrectangle',
'font-size': 20
})
// style for the connecting lines
.selector('edge')
.css({
'width': .9,
'height': 0.2,
'curve-style': 'bezier',
'target-arrow-shape': 'triangle',
'target-arrow-color': '#F3A712',
'line-color': '#F3A712',
// 'line-color': '#C40E0E',
})
.selector(':selected')
.css({
'background-color': '#428bca',
'line-color': '#C40E0E',
'target-arrow-color': '#C40E0E',
'source-arrow-color': '#C40E0E'
})
.selector('.faded')
.css({
'opacity': 1,
'text-opacity': 0
}),
elements: [
{
group: 'nodes',
data: {
id: 'WORDS'
}
}, {
group: 'nodes',
data: {
id: 'REALITY'
}
},
{
group: 'nodes',
data: {
id: 'THE WORLD'
}
},
{
group: 'nodes',
data: {
id: 'PEOPLE'
}
},
{
group: 'nodes',
data: {
id: 'ME'
}
},
{
group: 'edges',
data: {
id: 'edge1',
source: 'PEOPLE',
target: 'WORDS'
}
},
{
group: 'edges',
data: {
id: 'edge2',
source: 'PEOPLE',
target: 'REALITY'
}
},
{
group: 'edges',
data: {
id: 'edge3',
source: 'ME',
target: 'WORDS'
}
},
{
group: 'edges',
data: {
id: 'edge4',
source: 'WORDS',
target: 'THE WORLD'
}
},
{
group: 'edges',
data: {
id: 'edge',
source: 'THE WORLD',
target: 'ME'
}
},
{
group: 'edges',
data: {
id: 'edge6',
source: 'PEOPLE',
target: 'THE WORLD'
}
},
{
group: 'edges',
data: {
id: 'edge7',
source: 'ME',
target: 'THE WORLD'
}
},
{
group: 'edges',
data: {
id: 'edge9',
source: 'WORDS',
target: 'REALITY'
}
},
{
group: 'edges',
data: {
id: 'edge5',
source: 'REALITY',
target: 'ME'
}
}
],
}); // end cytoscape
}, false);
``
Just like with any canvas object, you need to "listen" to the drag event and take action based on the position.
The code below is a push in the right direction, I'm just showing the position of the element as it is dragged, next you need to set your area boundaries and prevent the element from moving outside
tippy("#cyto");
cy = cytoscape({
container: document.getElementById("cyto"),
style: cytoscape
.stylesheet()
.selector("node")
.css({content: "data(id)"}),
elements: [
{data: { id: "WORDS" }},
{data: { id: "REALITY" }}
]
});
cy.on('drag', 'node', function (evt) {
var node = evt.target;
var point = node.point();
console.log(node.id() + " " + point.x + " " + point.y);
if (point.y < 10)
node.style({ 'background-color': 'red' });
else
node.style({ 'background-color': 'blue' });
});
.container {
display: grid;
border: 2px blue solid;
height: 160px;
width: 400px;
}
#cyto {
grid-row: 2/ span 1;
grid-column: 1/ span 6;
}
<script src="https://unpkg.com/tippy.js#2.0.8/dist/tippy.all.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.14.1/cytoscape.min.js"></script>
<div class="container">
<div id="cyto">
</div>
</div>
You could use the https://github.com/cytoscape/cytoscape.js-automove but I strongly recommend you to understand this clearly before you start using extensions
Key Words: vue echarts graph drag
I want to make a graph chart with draggable nodes.
I use graphic to create circles with the dragging function on nodes.
there are two bugs:
When I move one node, the other nodes will move too.
Although I update the option immediately when the data change, but the chart always change a few seconds later.
You can init a vue-project with vue-cli3 and npm install echarts.
Then you can copy the codes to instead of the App.vue.
<template>
<div id="app">
<div id="charts" ref="chart" style="height:70vh;"></div>
</div>
</template>
<script>
import echarts from 'echarts'
export default {
data () {
return {
myChart: null,
option: {},
graph: {
nodes: [
{
name: 'Node1',
x: 300,
y: 300
},
{
name: 'Node2',
x: 800,
y: 300
},
{
name: 'Node3',
x: 550,
y: 100
},
{
name: 'Node4',
x: 550,
y: 500
}
],
links: [
{
source: 0,
target: 1,
symbolSize: [5, 20],
label: {
normal: {
show: true
}
},
lineStyle: {
normal: {
width: 5,
curveness: 0.2
}
}
},
{
source: 'Node2',
target: 'Node1',
label: {
normal: {
show: true
}
},
lineStyle: {
normal: { curveness: 0.2 }
}
},
{
source: 'Node1',
target: 'Node3'
},
{
source: 'Node2',
target: 'Node3'
},
{
source: 'Node2',
target: 'Node4'
},
{
source: 'Node1',
target: 'Node4'
}
]
}
}
},
mounted () {
this.initChart()
this.renderChart()
},
methods: {
initChart () {
this.myChart = echarts.init(document.getElementById('charts'));
},
renderChart() {
this.myChart.showLoading();
this.formatOption();
this.initDrag();
},
formatOption () {
this.option = {
title: {
text: 'Graph 简单示例'
},
tooltip: {},
animationDurationUpdate: 1500,
animationEasingUpdate: 'quinticInOut',
series : [
{
type: 'graph',
layout: 'none',
symbolSize: 50,
roam: 'scale',
label: {
normal: {
show: true
}
},
edgeSymbol: ['circle', 'arrow'],
edgeSymbolSize: [4, 10],
edgeLabel: {
normal: {
textStyle: {
fontSize: 20
}
}
},
nodes: this.graph.nodes,
links: this.graph.links,
lineStyle: {
normal: {
opacity: 0.9,
width: 2,
curveness: 0
}
}
}
]
};
this.myChart.hideLoading();
this.myChart.setOption(this.option, true);
},
initDrag () {
this.option.graphic = echarts.util.map(this.graph.nodes, (item, dataIndex) => {
return {
type: 'circle',
position: this.myChart.convertToPixel({seriesIndex: 0}, [item.x, item.y]),
shape: {
r: 10
},
// invisible: true,
style: {
fill: 'blue'
},
draggable: true,
ondrag: echarts.util.curry(this.onPointDragging, dataIndex),
z: 100
}
});
this.myChart.setOption(this.option);
window.addEventListener('resize', this.updatePosition);
},
updatePosition () {
this.myChart.setOption({
graphic: echarts.util.map(this.graph.nodes, (item, dataIndex) => {
return {
position: this.myChart.convertToPixel({seriesIndex: 0}, [item.x, item.y])
};
})
});
},
onPointDragging (dataIndex, event) {
let pos = this.myChart.convertFromPixel({seriesIndex: 0}, [event.offsetX, event.offsetY]) // 将graphic的像素坐标转化为坐标系坐标
this.graph.nodes[dataIndex].x = pos[0] // 将新的坐标系坐标赋值给node
this.graph.nodes[dataIndex].y = pos[1]
this.myChart.setOption({
series: {
nodes: this.graph.nodes
}
})
this.updatePosition()
}
}
}
</script>
<style scoped>
#charts {
flex: 1;
border: 1px solid;
box-shadow: 0 0 20px rgba(18,208,253,.5);
}
</style>
I'm displaying a flowchart with values from a JSON file.
When I create my element in a static way, like this :
elements: {
nodes: [
{ data: { id: 'INIT' } },
{ data: { id: 'BUSINESS_RULES_1' } },
{ data: { id: 'EXPORT_STC' } },
{ data: { id: 'EXPORT_SPEC' } },
{ data: { id: 'COPY' } },
{ data: { id: 'MERGE' } },
{ data: { id: 'BUSINESS_RULES_2' } },
{ data: { id: 'TRANSFORM_ARP' } },
{ data: { id: 'TRANSFORM_APS' } },
{ data: { id: 'PUBLISH_APS' } },
{ data: { id: 'PUBLISH_ARP' } },
{ data: { id: 'ARCHIVE' } }
],
edges: [
{ data: { source: 'INIT', target: 'BUSINESS_RULES_1' } },
{ data: { source: 'BUSINESS_RULES_1', target: 'EXPORT_SPEC' } },
{ data: { source: 'BUSINESS_RULES_1', target: 'EXPORT_STC' } },
{ data: { source: 'EXPORT_STC', target: 'COPY' } },
{ data: { source: 'EXPORT_SPEC', target: 'COPY' } },
{ data: { source: 'COPY', target: 'MERGE' } },
{ data: { source: 'MERGE', target: 'BUSINESS_RULES_2' } },
{ data: { source: 'BUSINESS_RULES_2', target: 'TRANSFORM_APS' } },
{ data: { source: 'BUSINESS_RULES_2', target: 'TRANSFORM_ARP' } },
{ data: { source: 'TRANSFORM_ARP', target: 'PUBLISH_ARP' } },
{ data: { source: 'TRANSFORM_APS', target: 'PUBLISH_APS' } },
{ data: { source: 'PUBLISH_APS', target: 'ARCHIVE' } },
{ data: { source: 'PUBLISH_ARP', target: 'ARCHIVE' } }
]
}
It is well displayed as you can see :
But when I create the element in a dynamic way, like this :
// Fill array with nodes and edges
var arrayNodesAndEdges = [];
for (var i = 0; i < myJSONdata.length; i++) {
if(i < myJSONdata.length - 1 && (myJSONdata[i].OPERATION_NAME != myJSONdata[i+1].OPERATION_NAME)) {
console.log(i + " " +myJSONdata[i].OPERATION_NAME);
arrayNodesAndEdges.push({
group: "nodes",
data: {
id: myJSONdata[i].OPERATION_NAME
}
});
} else if(i == myJSONdata.length - 1) {
console.log(i + " " +myJSONdata[i].OPERATION_NAME);
arrayNodesAndEdges.push({
group: "nodes",
data: {
id: myJSONdata[i].OPERATION_NAME
}
});
}
}
for (var i = 0; i < myJSONdata.length; i++) {
var source = myJSONdata[i].OPERATION_NAME;
if(myJSONdata[i].NEXT_OPERATION_NAME !== "" && myJSONdata[i].NEXT_OPERATION_NAME !== null) {
console.log("Source: " + myJSONdata[i].OPERATION_NAME + ", " + "Target: " +myJSONdata[i].NEXT_OPERATION_NAME);
arrayNodesAndEdges.push({
group: "edges",
data: {
id: "e"+i,
source: source,
target: myJSONdata[i].NEXT_OPERATION_NAME
}
});
}
}
cy.add(arrayNodesAndEdges);
It is bad displayed, all nodes are on top of each other, as you can see:
(I moved some to explain how they are positionned, but they are all on top of each other)
Here's the console log, you can see this is the same structure in static or dynamic way :
NODES
0 INIT
2 BUSINESS_RULES_1
3 EXPORT_STC
4 EXPORT_SPEC
5 COPY
6 MERGE
8 BUSINESS_RULES_2
9 TRANSFORM_ARP
10 TRANSFORM_APS
11 PUBLISH_APS
12 PUBLISH_ARP
13 ARCHIVE
EDGES
Source: INIT, Target: BUSINESS_RULES_1
Source: BUSINESS_RULES_1, Target: EXPORT_SPEC
Source: BUSINESS_RULES_1, Target: EXPORT_STC
Source: EXPORT_STC, Target: COPY
Source: EXPORT_SPEC, Target: COPY
Source: COPY, Target: MERGE
Source: MERGE, Target: BUSINESS_RULES_2
Source: BUSINESS_RULES_2, Target: TRANSFORM_APS
Source: BUSINESS_RULES_2, Target: TRANSFORM_ARP
Source: TRANSFORM_ARP, Target: PUBLISH_ARP
Source: TRANSFORM_APS, Target: PUBLISH_APS
Source: PUBLISH_APS, Target: ARCHIVE
Source: PUBLISH_ARP, Target: ARCHIVE
I can't understand what I'm doing wrong ?
Thank you
EDIT ----------
This is my whole code :
var myJSONdata = data;
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: true,
autounselectify: true,
layout: {
name: 'dagre',
rankDir: 'LR' // 'TB' for top to bottom flow, 'LR' for left to right. default is undefined, making it plot top-bottom
},
style: [
{
selector: 'node',
style: {
'content': 'data(id)',
'width': 200,
'height': 50,
'text-opacity': 1,
'text-valign': 'center',
'text-halign': 'center',
'shape': 'square',
'label': 'data(id)',
'background-color': '#11479e',
'color': 'white'
}
},
{
selector: 'edge',
style: {
'width': 7,
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle',
'curve-style': 'bezier',
'line-color': '#9dbaea'
}
},
{
selector: ':selected',
style: {
'background-color': 'yellow',
'line-color': 'yellow',
'target-arrow-color': 'yellow',
'source-arrow-color': 'yellow',
}
}
]
/*,elements: {
nodes: [
{ data: { id: 'INIT' } },
{ data: { id: 'BUSINESS_RULES_1' } },
{ data: { id: 'EXPORT_STC' } },
{ data: { id: 'EXPORT_SPEC' } },
{ data: { id: 'COPY' } },
{ data: { id: 'MERGE' } },
{ data: { id: 'BUSINESS_RULES_2' } },
{ data: { id: 'TRANSFORM_ARP' } },
{ data: { id: 'TRANSFORM_APS' } },
{ data: { id: 'PUBLISH_APS' } },
{ data: { id: 'PUBLISH_ARP' } },
{ data: { id: 'ARCHIVE' } }
],
edges: [
{ data: { source: 'INIT', target: 'BUSINESS_RULES_1' } },
{ data: { source: 'BUSINESS_RULES_1', target: 'EXPORT_SPEC' } },
{ data: { source: 'BUSINESS_RULES_1', target: 'EXPORT_STC' } },
{ data: { source: 'EXPORT_STC', target: 'COPY' } },
{ data: { source: 'EXPORT_SPEC', target: 'COPY' } },
{ data: { source: 'COPY', target: 'MERGE' } },
{ data: { source: 'MERGE', target: 'BUSINESS_RULES_2' } },
{ data: { source: 'BUSINESS_RULES_2', target: 'TRANSFORM_APS' } },
{ data: { source: 'BUSINESS_RULES_2', target: 'TRANSFORM_ARP' } },
{ data: { source: 'TRANSFORM_ARP', target: 'PUBLISH_ARP' } },
{ data: { source: 'TRANSFORM_APS', target: 'PUBLISH_APS' } },
{ data: { source: 'PUBLISH_APS', target: 'ARCHIVE' } },
{ data: { source: 'PUBLISH_ARP', target: 'ARCHIVE' } }
]
}*/
});
// Fill array with nodes and edges
var arrayNodesAndEdges = [];
for (var i = 0; i < myJSONdata.length; i++) {
if(i < myJSONdata.length - 1 && (myJSONdata[i].OPERATION_NAME != myJSONdata[i+1].OPERATION_NAME)) {
console.log(i + " " +myJSONdata[i].OPERATION_NAME);
arrayNodesAndEdges.push({
group: "nodes",
data: {
id: myJSONdata[i].OPERATION_NAME
}
});
} else if(i == myJSONdata.length - 1) {
console.log(i + " " +myJSONdata[i].OPERATION_NAME);
arrayNodesAndEdges.push({
group: "nodes",
data: {
id: myJSONdata[i].OPERATION_NAME
}
});
}
}
for (var i = 0; i < myJSONdata.length; i++) {
var source = myJSONdata[i].OPERATION_NAME;
if(myJSONdata[i].NEXT_OPERATION_NAME !== "" && myJSONdata[i].NEXT_OPERATION_NAME !== null) {
console.log("Source: " + myJSONdata[i].OPERATION_NAME + ", " + "Target: " +myJSONdata[i].NEXT_OPERATION_NAME);
arrayNodesAndEdges.push({
group: "edges",
data: {
id: "e"+i,
source: source,
target: myJSONdata[i].NEXT_OPERATION_NAME
}
});
}
}
cy.add(arrayNodesAndEdges);
I finally manage to solve it thanks to this post right here
I created the array at the beginning and add them to the "element" property. But I still do not know why it was not working in the previous version.
This is my final code :
var myJSONdata = data;
// Fill array with nodes and edges
var arrayNodes = [];
for (var i = 0; i < myJSONdata.length; i++) {
if(i < myJSONdata.length - 1 && (myJSONdata[i].OPERATION_NAME != myJSONdata[i+1].OPERATION_NAME)) {
console.log(i + " " +myJSONdata[i].OPERATION_NAME);
arrayNodes.push({
group: "nodes",
data: {
id: myJSONdata[i].OPERATION_NAME
}
});
} else if(i == myJSONdata.length - 1) {
console.log(i + " " +myJSONdata[i].OPERATION_NAME);
arrayNodes.push({
group: "nodes",
data: {
id: myJSONdata[i].OPERATION_NAME
}
});
}
}
var arrayEdges = [];
for (var i = 0; i < myJSONdata.length; i++) {
var source = myJSONdata[i].OPERATION_NAME;
if(myJSONdata[i].NEXT_OPERATION_NAME !== "" && myJSONdata[i].NEXT_OPERATION_NAME !== null) {
console.log("Source: " + myJSONdata[i].OPERATION_NAME + ", " + "Target: " +myJSONdata[i].NEXT_OPERATION_NAME);
arrayEdges.push({
group: "edges",
data: {
id: "e"+i,
source: source,
target: myJSONdata[i].NEXT_OPERATION_NAME
}
});
}
}
var cy = window.cy = cytoscape({
container: document.getElementById('cy'),
boxSelectionEnabled: true,
autounselectify: true,
layout: {
name: 'dagre',
rankDir: 'LR' // 'TB' for top to bottom flow, 'LR' for left to right. default is undefined, making it plot top-bottom
},
style: [
{
selector: 'node',
style: {
'content': 'data(id)',
'width': 200,
'height': 50,
'text-opacity': 1,
'text-valign': 'center',
'text-halign': 'center',
'shape': 'square',
'label': 'data(id)',
'background-color': '#11479e',
'color': 'white'
}
},
{
selector: 'edge',
style: {
'width': 7,
'target-arrow-color': '#ccc',
'target-arrow-shape': 'triangle',
'curve-style': 'bezier',
'line-color': '#9dbaea'
}
},
{
selector: ':selected',
style: {
'background-color': 'yellow',
'line-color': 'yellow',
'target-arrow-color': 'yellow',
'source-arrow-color': 'yellow',
}
}
]
,elements: {
nodes: arrayNodes,
edges: arrayEdges
}
});
i can create a graph using cytoscape js library . i am following the this tutorial and i implement like this.
CODE:
$(function(){ // on dom ready
$('#cy').cytoscape({
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(id)'
})
.selector('edge')
.css({
'target-arrow-shape': 'triangle',
'width': 4,
'line-color': '#ddd',
'target-arrow-color': '#ddd'
})
.selector('.highlighted')
.css({
'background-color': '#61bffc',
'line-color': '#61bffc',
'target-arrow-color': '#61bffc',
'transition-property': 'background-color, line-color, target-arrow-color',
'transition-duration': '0.5s'
}),
elements: {
nodes: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'c' } },
{ data: { id: 'd' } },
{ data: { id: 'e' } },
{ data: { id: 'f' } },
{ data: { id: 'g' } }
],
edges: [
{ data: { id: 'ab', weight: 1, source: 'a', target: 'b' } },
{ data: { id: 'ac', weight: 2, source: 'a', target: 'c' } },
{ data: { id: 'bd', weight: 3, source: 'b', target: 'd' } },
{ data: { id: 'be', weight: 4, source: 'b', target: 'e' } },
{ data: { id: 'cf', weight: 5, source: 'c', target: 'f' } },
{ data: { id: 'cg', weight: 6, source: 'c', target: 'g' } }
]
},
layout: {
name: 'breadthfirst',
directed: true,
roots: '#a',
padding: 5
},
ready: function(){
window.cy = this;
var bfs = cy.elements().bfs('#a', function(){}, true);
var i = 0;
var highlightNextEle = function(){
bfs.path[i].addClass('highlighted');
if( i < bfs.path.length ){
i++;
setTimeout(highlightNextEle, 1000);
}
};
// kick off first highlight
highlightNextEle();
}
});
}); // on dom ready
on my implementation i need to highlight the path between the nodes d and g.
How to find the path between the nodes and highlight them?
Using dijkstra algorithm method we can find the path between the nodes.
var dijkstra = cy.elements().dijkstra('#e',function(){
return this.data('weight');
},false);
var bfs = dijkstra.pathTo( cy.$('#i') );
Complete CODE :
$(function(){ // on dom ready
$('#cy').cytoscape({
style: cytoscape.stylesheet()
.selector('node')
.css({
'content': 'data(id)'
})
.selector('edge')
.css({
'target-arrow-shape': 'triangle',
'width': 4,
'line-color': '#ddd',
'target-arrow-color': '#ddd'
})
.selector('.highlighted')
.css({
'background-color': '#61bffc',
'line-color': '#61bffc',
'target-arrow-color': '#61bffc',
'transition-property': 'background-color, line-color, target-arrow-color',
'transition-duration': '0.5s'
}),
elements: {
nodes: [
{ data: { id: 'a' } },
{ data: { id: 'b' } },
{ data: { id: 'c' } },
{ data: { id: 'd' } },
{ data: { id: 'e' } },
{ data: { id: 'f' } },
{ data: { id: 'g' } },
{ data: { id: 'h' } },
{ data: { id: 'i' } }
],
edges: [
{ data: { id: 'ab', weight: 1, source: 'a', target: 'b' } },
{ data: { id: 'ac', weight: 2, source: 'a', target: 'c' } },
{ data: { id: 'bd', weight: 3, source: 'b', target: 'd' } },
{ data: { id: 'be', weight: 4, source: 'b', target: 'e' } },
{ data: { id: 'cf', weight: 5, source: 'c', target: 'f' } },
{ data: { id: 'cg', weight: 6, source: 'c', target: 'g' } },
{ data: { id: 'ah', weight: 7, source: 'a', target: 'h' } },
{ data: { id: 'hi', weight: 8, source: 'h', target: 'i' } }
]
},
layout: {
name: 'breadthfirst',
directed: true,
roots: '#a',
padding: 5
},
ready: function(){
window.cy = this;
var dijkstra = cy.elements().dijkstra('#e',function(){
return this.data('weight');
},false);
var bfs = dijkstra.pathTo( cy.$('#i') );
var x=0;
var highlightNextEle = function(){
var el=bfs[x];
el.addClass('highlighted');
if(x<bfs.length){
x++;
setTimeout(highlightNextEle, 500);
}
};
highlightNextEle();
}
});
}); // on dom ready
I you want to highlight all the possible paths
event.target- is the starting node
event.target.successors().animate({
style: { lineColor: 'red' }
});
Assuming you have picked two nodes and stored them in source_node and target_node, and you want to label everything in between with class 'path_element':
p = cy.elements().aStar({root: source_node, goal: target_node, directed: true}).path;
if (p) {
p.filter(function(i,x) { return x != source_node && x != target_node; })
.addClass('path_element');
p.edgesWith(p)
.addClass('path_element');
}