currently I'm trying to realize this function:
I've created a color selector on the website. Once a user selects a specific color, the colors of nodes he/she selected and their neighbouring nodes will be changed into the color selected after tap.
For example, in the case below, if I select "red" and then choose the node "cytoscape", the "cytoscape" and the "cytoscape.js" will both be red. Now if I change the color into "green" and then I click on "test", the "test" node will change into green but the "cytoscape" and "cytoscape.js" still remain "red". Does someone know how to do this?
Thank you!
Here is my code:
var cy = cytoscape({
container: document.getElementById('cy'),
style: [
{
selector: 'node',
style: {
'label': 'data(name)',
'text-valign': 'center',
'color':"white",
'text-outline-color': 'orange',
'text-outline-width': 2,
'background-color': 'orange',
}
},
{
selector: 'edge',
style: {
'width':2,
'line-color':'grey',
}
},
{
selector: 'node.highlight',
style: {
'label': 'data(name)',
'text-valign': 'center',
'color':"white",
'text-outline-color': 'red',
'text-outline-width': 2,
'background-color': 'red',
}
},
{
selector: 'node.semitransp',
style:{ 'opacity': '0.5' }
},
],
elements: {
nodes: [
{ data: { id: 'desktop', name: 'Cytoscape' } },
{ data: { id: 'test', name: 'Test'} },
{ data: { id: 'js', name: 'Cytoscape.js'} },
],
edges: [
{ data: { source: 'desktop', target: 'js' } },
{ data: { source: 'js', target: 'desktop' } }
]
},
layout: {
name: 'cose',
idealEdgeLength: 100,
nodeOverlap: 20,
refresh: 20,
fit: true,
padding: 30,
randomize: false,
componentSpacing: 100,
nodeRepulsion: 400000,
edgeElasticity: 100,
nestingFactor: 5,
gravity: 80,
numIter: 1000,
initialTemp: 200,
coolingFactor: 0.95,
minTemp: 1.0
},
minZoom:0.5,
maxZoom:3,
motionBlur: true,
wheelSensitivity: 0.05,
});
cy.on('tap', 'node', function(e){
var ele = e.target;
if(cy.elements('node[background-color:orange]')){
cy.elements().difference(ele.outgoers());
ele.addClass('highlight').outgoers().addClass('highlight');
}
});
cy.on('cxttap', 'node', function(e){
var ele = e.target;
ele.removeClass('highlight').outgoers().removeClass('highlight');
});
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
<script src="https://unpkg.com/cytoscape/dist/cytoscape.min.js"></script>
<title></title>
<style>
#cy{
width: auto;
height: 500px;
display: block;
background-color: #F5F5F5;
}
#box{position: absolute;}
</style>
</head>
<body>
<select id="color_selector">
<option value="red">red</option>
<option value="green">green</option>
<option value="orange">orange</option>
</select>
<div id="cy"></div>
</body>
I suggest you read about the :selected
state and not fiddle with classes by yourself, unless you really need to.
Nonethless, to answer your question. You are not using the select's value anywhere in your code, hence, nothing happens. In the snippet you provided, no node ever turns green. There is only orange
(default state) and red
(highlighted state via class highlight
).
In order to obtain a dynamic background-color, you need to use either node.style(property, value)
or better yet, store the value in data
and create a generic style property that applies when a node has a specific datum. By using data
instead of style
the user preference will persist.
Here's your code updated - https://codepen.io/Raven0us/pen/zYvNyJR
I added
{
selector: 'node[background_color]',
style: {
'background-color': 'data(background_color)',
'text-outline-color': 'data(background_color)',
}
},
node[background-color]
means nodes that have background_color
within their data set.
It's important for this to be declared before the highlight
styling because you want highlight
to override everything, in order to provide the user with feedback that they have selected the nodes.
Also added
document.getElementById('color_selector').addEventListener('change', (e) => {
let nodes = cy.$('node.highlight');
nodes.forEach(node => {
node.data('background_color', e.target.value);
node.removeClass('highlight'); // need to remove class in order to display the updated background color
})
})
LE - The highlighting color should never be featured as an option for the user. Alternatively, you could enlarge the nodes in order to emphasize the fact that they are highlighted/selected.