Is there a way to display a node label at the top inside the node?
Asked Answered
S

2

7

I am creating a graph using cytoscape.js and I have compounded nodes which are inside the parent node. I would like to have the title of the main/parent node at the top of the node but inside the node. Is that possible in cytoscape?

I have tried using using halign and valign. Whenever I use top value, it shows outside the box.

Is there a extension or a plugin that lets us do it?

Example with child node: https://stackblitz.com/edit/cytoscape-call-method-child-efmbaj?file=src%2Fapp%2FstylesheetObject.ts

Septuple answered 24/6, 2021 at 18:51 Comment(0)
B
4

What I understand is that you want to put the parent label inside the box above child? apologies if I'm wrong

enter image description here

If so, My solution will be to add a padding and then apply margin for alignment.

Modified your example

Styles updated:

  1. 'padding-top':60

    selector: 'node',
    css: {
      content: 'data(label)',
      'text-valign': 'center',
      'text-halign': 'center',
      'font-size': 28,
      'padding-top':60
    }
    
  2. 'text-valign': 'top', and 'text-margin-y': function(node) { return node.height() - 10; }

    selector: 'node[type="parent"]',
    style: {
      shape: 'rectangle',
      'background-color': 'grey',
      width: 300,
      height: 100,
      'font-size': 25.5,
      'font-family': 'Lato, Helvetica Neue, Helvetica, Arial, sans-serif',
      color: 'black',
      'text-valign': 'top',
      'text-halign': 'center',
      'text-margin-y': function(node) {
        return node.height() - 10;
      }
    }
    
Buttress answered 30/6, 2021 at 3:5 Comment(3)
This is working. The only thing, when I add padding top it does not just add padding at the top, it adds padding everywhere and makes the node of different size. Do you know a way of adding a space at the top like a margin instead of padding?Septuple
Try adding 'padding-top' to specific selector like 'node[type="parent"]'Buttress
I am adding padding top to selector like 'node[type="parent"]' It still adds padding everywhere so the node size increasesSeptuple
G
5

As you can read here, you can only place labels inside a node with the center option, a good configuration (label inside at the top) requires a margin to be added to your label:

.selector(':parent')
  .css({
    'text-valign': 'center',
    // the next line moves the parents label up to the top of the node and 5px down to create a padding 
    'text-margin-y': function (node) { return -node.height() + 5 }
})

Here is a working example:

var cy = cytoscape({
  container: document.getElementById('cy'),

  style: cytoscape.stylesheet()
    .selector(':parent')
    .css({
      'text-valign': 'center',
      'text-margin-y': function(node) {
        return -node.height() + 5
      }
    })
    .selector('node')
    .css({
      'height': 'data(size)',
      'width': 'data(size)',
      'border-color': '#000',
      'border-width': '1',
      'content': 'data(name)'
    })
    .selector('edge')
    .css({
      'width': 'data(strength)'
    })
    .selector('#1')
    .css({
      'background-color': 'red'
    })
    .selector('#4')
    .css({
      'background-color': 'green'
    }),

  elements: {
    nodes: [{
        data: {
          id: '1',
          size: 50,
          name: 'a'
        }
      },
      {
        data: {
          id: '2',
          size: 20,
          name: 'b',
          parent: '1'
        }
      },
      {
        data: {
          id: '3',
          size: 40,
          name: 'c',
          parent: '1'
        }
      },
      {
        data: {
          id: '4',
          size: 50,
          name: 'd'
        }
      },
      {
        data: {
          id: '5',
          size: 20,
          name: 'e',
          parent: '4'
        }
      },
      {
        data: {
          id: '6',
          size: 40,
          name: 'f',
          parent: '4'
        }
      }
    ],
  },
});
body {
  font: 14px helvetica neue, helvetica, arial, sans-serif;
}

#cy {
  height: 100%;
  width: 75%;
  position: absolute;
  left: 0;
  top: 0;
  float: left;
}
<html>

<head>
  <meta charset=utf-8 />
  <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/cytoscape/3.2.17/cytoscape.min.js"></script>
  <script src="https://unpkg.com/[email protected]/dist/jquery.js"></script>
</head>

<body>
  <div id="cy"></div>
</body>

</html>
Gipps answered 25/6, 2021 at 8:46 Comment(6)
This is not working if you have a node inside a node. The child node does not go down and make space for the title. The title just goes behind the child nodeSeptuple
Here is a simple example: stackblitz.com/edit/…Septuple
If I set this { selector: 'node[type="parent"]', style: { shape: 'rectangle', 'background-color': 'grey', width: 300, height: 100, 'font-size': 25.5, 'font-family': 'Lato, Helvetica Neue, Helvetica, Arial, sans-serif', color: 'black', 'text-valign': 'top', 'text-halign': 'center', 'text-margin-y': function(node) { return '40px'; } } }, I see the labels are behind the child nodeMetal
@Metal does this mean that this is not possible with cytoscape currently?Septuple
@LearnAspNet it might be impossible, not sure. I couldn't find a way. You might want to check issues in cytoscape.js repository. Also you might want to play with styles like z-compound-depth and z-index, background-opacity, opacity etc.. Logically if you want your child node to be visible, it should be rendered on top of its parent. So parent's z-index should be lower. So then its label should also be rendered before child. I think it is contradictory.Metal
If z-index of parent is greater then you can not see its childrenMetal
B
4

What I understand is that you want to put the parent label inside the box above child? apologies if I'm wrong

enter image description here

If so, My solution will be to add a padding and then apply margin for alignment.

Modified your example

Styles updated:

  1. 'padding-top':60

    selector: 'node',
    css: {
      content: 'data(label)',
      'text-valign': 'center',
      'text-halign': 'center',
      'font-size': 28,
      'padding-top':60
    }
    
  2. 'text-valign': 'top', and 'text-margin-y': function(node) { return node.height() - 10; }

    selector: 'node[type="parent"]',
    style: {
      shape: 'rectangle',
      'background-color': 'grey',
      width: 300,
      height: 100,
      'font-size': 25.5,
      'font-family': 'Lato, Helvetica Neue, Helvetica, Arial, sans-serif',
      color: 'black',
      'text-valign': 'top',
      'text-halign': 'center',
      'text-margin-y': function(node) {
        return node.height() - 10;
      }
    }
    
Buttress answered 30/6, 2021 at 3:5 Comment(3)
This is working. The only thing, when I add padding top it does not just add padding at the top, it adds padding everywhere and makes the node of different size. Do you know a way of adding a space at the top like a margin instead of padding?Septuple
Try adding 'padding-top' to specific selector like 'node[type="parent"]'Buttress
I am adding padding top to selector like 'node[type="parent"]' It still adds padding everywhere so the node size increasesSeptuple

© 2022 - 2024 — McMap. All rights reserved.