Sigma.js 5.67 KB
Newer Older
James Laver's avatar
James Laver committed
1 2
'use strict';

3
const sigma = require('sigma/src/garg.js').sigma;
James Laver's avatar
James Laver committed
4

James Laver's avatar
James Laver committed
5 6
if (typeof window !== 'undefined') {
  window.sigma = sigma;
James Laver's avatar
James Laver committed
7 8
}

9 10 11
const CustomShapes = require('sigma/plugins/garg.js').init(sigma, window).customShapes;
require('sigma/src/utils/sigma.utils.js').init(sigma);

12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
// Black circle around a node
(function() {
  var originalDef = sigma.canvas.nodes.def;

  sigma.canvas.nodes.def = (node, context, settings) => {
    var prefix = settings('prefix') || '';

    originalDef(node, context, settings);

    context.strokeStyle = '#000';
    context.lineWidth = 1;
    context.beginPath();
    context.arc(
      node[prefix + 'x'],
      node[prefix + 'y'],
      node[prefix + 'size'],
      0,
      Math.PI * 2,
      true
    );
    context.stroke();
  }
})()

36
sigma.canvas.nodes.selected = (node, context, settings) => {
37 38 39 40 41 42 43
  // hack
  // We need to temporarily set node.type to 'def'. This is for 2 reasons
  // 1. Make it render as a normal node
  // 2. Avoid infinite recursion (hovers.def calls node renderer and we would end up here back
  //    again with node.type = 'hovered')
  node.type = 'def';
  sigma.canvas.hovers.def(node, context, settings);
44
  node.type = 'selected';
45 46 47
};

CustomShapes.init();
48

49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
let sigmaMouseSelector = (sigma, options) => {
  sigma.plugins = sigma.plugins || {};

  sigma.plugins.mouseSelector = (s, renderer) => {
    var _self = this;
    var _offset = null;
    const _s = s;
    const _renderer = renderer;
    const _container = _renderer.container;
    //renderer.initDOM('canvas', 'mouseSelector');
    // A hack to force resize to be called (there is a width/height equality
    // check which can't be escaped in any other way).
    //renderer.resize(renderer.width - 1, renderer.height - 1);
    //renderer.resize(renderer.width + 1, renderer.height + 1);
    const _context = _renderer.contexts.mouseSelector;
64 65 66 67
    // These are used to prevent using the 'click' event when in fact this was a drag
    let _clickPositionX = null;
    let _clickPositionY = null;
    let _isValidClick = false;
68 69 70

    _container.onmousemove = function(e) { return mouseMove(e); };
    _context.canvas.onclick = function(e) { return onClick(e); };
71 72
    _container.onmousedown = function(e) { return onMouseDown(e); }
    _container.onmouseup = function(e) { return onMouseUp(e); }
73 74 75 76 77 78 79 80 81
    s.bind('click', function(e) { return onClick(e); })
    // The mouseSelector canvas will pass its events down to the "mouse" canvas.
    _context.canvas.style.pointerEvents = 'none';

    s.bind('kill', () => _self.unbindAll());

    this.unbindAll = () => {
      console.log('[sigmaMouseSelector] unbinding');
      _container.onclick = null;
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
      _context.canvas.onmousemove = null;
      _container.onmousedown = null;
      _container.onmouseup = null;
    }

    const onMouseDown = (e) => {
      _clickPositionX = e.clientX;
      _clickPositionY = e.clientY;
    }

    const onMouseUp = (e) => {
      // Prevent triggering click when in fact this was a drag
      if ((_clickPositionX != e.clientX) || (_clickPositionY != e.clientY)) {
        _clickPositionX = null;
        _clickPositionY = null;
        _isValidClick = false;
      } else {
        _isValidClick = true;
      }
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123
    }

    const mouseMove = (e) => {
      const size = _s.settings('mouseSelectorSize') || 3;
      const x = e.clientX - _offset.left - size/2;
      const y = e.clientY - _offset.top - size/2;
      _context.clearRect(0, 0, _context.canvas.width, _context.canvas.height);

      _context.fillStyle = 'rgba(91, 192, 222, 0.7)';
      _context.beginPath();
      _context.arc(
        x,
        y,
        size,
        0,
        Math.PI * 2,
        true
      );
      _context.closePath();
      _context.fill();
    }

    const onClick = (e) => {
124 125 126
      if(!_isValidClick) {
        return;
      }
127 128 129 130
      const size = _s.settings('mouseSelectorSize') || 3;
      const x = e.data.clientX - _offset.left - size/2;
      const y = e.data.clientY - _offset.top - size/2;
      const prefix = _renderer.options.prefix;
131
      //console.log('[sigmaMouseSelector] clicked', e, x, y, size);
132 133 134 135 136 137 138 139
      let nodes = [];
      _s.graph.nodes().forEach((node) => {
        const nodeX = node[prefix + 'x'];
        const nodeY = node[prefix + 'y'];
        if(sigma.utils.getDistance(x, y, nodeX, nodeY) <= size) {
          nodes.push(node);
        }
      });
140 141 142 143 144 145 146
      //console.log('[sigmaMouseSelector] nodes', nodes);
      _renderer.dispatchEvent('clickNodes', {
        node: nodes,
        captor: e.data
      })
      _clickPositionX = null;
      _clickPositionY = null;
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
    }

    const calculateOffset = (element) => {
      var style = window.getComputedStyle(element);
      var getCssProperty = function(prop) {
        return parseInt(style.getPropertyValue(prop).replace('px', '')) || 0;
      };
      return {
        left: element.getBoundingClientRect().left + getCssProperty('padding-left'),
        top: element.getBoundingClientRect().top + getCssProperty('padding-top')
      };
    };

    _offset = calculateOffset(renderer.container);

  }
}

sigmaMouseSelector(sigma);

James Laver's avatar
James Laver committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
function _sigma(left, right, opts) {
  try {
    return right(new sigma(opts));
  } catch(e) {
    return left(e);
  }
}

function addRenderer(left, right, sigma, renderer) {
  try {
    return right(sigma.addRenderer(renderer));
  } catch(e) {
    return left(e);
  }
}
182 183 184 185 186 187 188 189
function bindMouseSelectorPlugin(left, right, sig) {
  try {
    return right(sigma.plugins.mouseSelector(sig, sig.renderers[0]));
  } catch(e) {
    console.log('[bindMouseSelectorPlugin] error', e);
    return left(e);
  }
}
190
function bind(sigma, event, handler) { sigma.bind(event, handler); }
191

James Laver's avatar
James Laver committed
192 193
exports._sigma = _sigma;
exports._addRenderer = addRenderer;
194
exports._bindMouseSelectorPlugin = bindMouseSelectorPlugin;
195
exports._bind = bind;