UNPKG

@sigma/node-border

Version:

A node program that renders concentric discs in nodes for sigma.js

402 lines (369 loc) 17.2 kB
'use strict'; Object.defineProperty(exports, '__esModule', { value: true }); var rendering = require('sigma/rendering'); var utils = require('sigma/utils'); function _arrayWithHoles(r) { if (Array.isArray(r)) return r; } function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } } function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; } function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } } function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _slicedToArray(r, e) { return _arrayWithHoles(r) || _iterableToArrayLimit(r, e) || _unsupportedIterableToArray(r, e) || _nonIterableRest(); } function _classCallCheck(a, n) { if (!(a instanceof n)) throw new TypeError("Cannot call a class as a function"); } function _toPrimitive(t, r) { if ("object" != typeof t || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != typeof i) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); } function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == typeof i ? i : i + ""; } function _defineProperties(e, r) { for (var t = 0; t < r.length; t++) { var o = r[t]; o.enumerable = o.enumerable || !1, o.configurable = !0, "value" in o && (o.writable = !0), Object.defineProperty(e, _toPropertyKey(o.key), o); } } function _createClass(e, r, t) { return r && _defineProperties(e.prototype, r), t && _defineProperties(e, t), Object.defineProperty(e, "prototype", { writable: !1 }), e; } function _getPrototypeOf(t) { return _getPrototypeOf = Object.setPrototypeOf ? Object.getPrototypeOf.bind() : function (t) { return t.__proto__ || Object.getPrototypeOf(t); }, _getPrototypeOf(t); } function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function () { return !!t; })(); } function _assertThisInitialized(e) { if (void 0 === e) throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); return e; } function _possibleConstructorReturn(t, e) { if (e && ("object" == typeof e || "function" == typeof e)) return e; if (void 0 !== e) throw new TypeError("Derived constructors may only return object or undefined"); return _assertThisInitialized(t); } function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); } function _setPrototypeOf(t, e) { return _setPrototypeOf = Object.setPrototypeOf ? Object.setPrototypeOf.bind() : function (t, e) { return t.__proto__ = e, t; }, _setPrototypeOf(t, e); } function _inherits(t, e) { if ("function" != typeof e && null !== e) throw new TypeError("Super expression must either be null or a function"); t.prototype = Object.create(e && e.prototype, { constructor: { value: t, writable: !0, configurable: !0 } }), Object.defineProperty(t, "prototype", { writable: !1 }), e && _setPrototypeOf(t, e); } function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; } function _arrayWithoutHoles(r) { if (Array.isArray(r)) return _arrayLikeToArray(r); } function _iterableToArray(r) { if ("undefined" != typeof Symbol && null != r[Symbol.iterator] || null != r["@@iterator"]) return Array.from(r); } function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } function _toConsumableArray(r) { return _arrayWithoutHoles(r) || _iterableToArray(r) || _unsupportedIterableToArray(r) || _nonIterableSpread(); } function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; } function _objectSpread2(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } var DEFAULT_BORDER_SIZE_MODE = "relative"; var DEFAULT_CREATE_NODE_BORDER_OPTIONS = { drawLabel: undefined, drawHover: undefined, borders: [{ size: { value: 0.1 }, color: { attribute: "borderColor" } }, { size: { fill: true }, color: { attribute: "color" } }] }; var DEFAULT_COLOR = "#000000"; function getFragmentShader(_ref) { var borders = _ref.borders; var fillCounts = rendering.numberToGLSLFloat(borders.filter(function (_ref2) { var size = _ref2.size; return "fill" in size; }).length); // language=GLSL var SHADER = /*glsl*/"\nprecision highp float;\n\nvarying vec2 v_diffVector;\nvarying float v_radius;\n\n#ifdef PICKING_MODE\nvarying vec4 v_color;\n#else\n// For normal mode, we use the border colors defined in the program:\n".concat(borders.flatMap(function (_ref3, i) { var size = _ref3.size; return "attribute" in size ? ["varying float v_borderSize_".concat(i + 1, ";")] : []; }).join("\n"), "\n").concat(borders.flatMap(function (_ref4, i) { var color = _ref4.color; return "attribute" in color ? ["varying vec4 v_borderColor_".concat(i + 1, ";")] : "value" in color ? ["uniform vec4 u_borderColor_".concat(i + 1, ";")] : []; }).join("\n"), "\n#endif\n\nuniform float u_correctionRatio;\n\nconst float bias = 255.0 / 254.0;\nconst vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);\n\nvoid main(void) {\n float dist = length(v_diffVector);\n float aaBorder = 2.0 * u_correctionRatio;\n float v_borderSize_0 = v_radius;\n vec4 v_borderColor_0 = transparent;\n\n // No antialiasing for picking mode:\n #ifdef PICKING_MODE\n if (dist > v_radius)\n gl_FragColor = transparent;\n else {\n gl_FragColor = v_color;\n gl_FragColor.a *= bias;\n }\n #else\n // Sizes:\n").concat(borders.flatMap(function (_ref5, i) { var size = _ref5.size; if ("fill" in size) return []; size = size; var value = "attribute" in size ? "v_borderSize_".concat(i + 1) : rendering.numberToGLSLFloat(size.value); var factor = (size.mode || DEFAULT_BORDER_SIZE_MODE) === "pixels" ? "u_correctionRatio" : "v_radius"; return [" float borderSize_".concat(i + 1, " = ").concat(factor, " * ").concat(value, ";")]; }).join("\n"), "\n // Now, let's split the remaining space between \"fill\" borders:\n float fillBorderSize = (v_radius - (").concat(borders.flatMap(function (_ref6, i) { var size = _ref6.size; return !("fill" in size) ? ["borderSize_".concat(i + 1)] : []; }).join(" + "), ") ) / ").concat(fillCounts, ";\n").concat(borders.flatMap(function (_ref7, i) { var size = _ref7.size; return "fill" in size ? [" float borderSize_".concat(i + 1, " = fillBorderSize;")] : []; }).join("\n"), "\n\n // Finally, normalize all border sizes, to start from the full size and to end with the smallest:\n float adjustedBorderSize_0 = v_radius;\n").concat(borders.map(function (_, i) { return " float adjustedBorderSize_".concat(i + 1, " = adjustedBorderSize_").concat(i, " - borderSize_").concat(i + 1, ";"); }).join("\n"), "\n\n // Colors:\n vec4 borderColor_0 = transparent;\n").concat(borders.map(function (_ref8, i) { var color = _ref8.color; var res = []; if ("attribute" in color) { res.push(" vec4 borderColor_".concat(i + 1, " = v_borderColor_").concat(i + 1, ";")); } else if ("transparent" in color) { res.push(" vec4 borderColor_".concat(i + 1, " = vec4(0.0, 0.0, 0.0, 0.0);")); } else { res.push(" vec4 borderColor_".concat(i + 1, " = u_borderColor_").concat(i + 1, ";")); } res.push(" borderColor_".concat(i + 1, ".a *= bias;")); res.push(" if (borderSize_".concat(i + 1, " <= 1.0 * u_correctionRatio) { borderColor_").concat(i + 1, " = borderColor_").concat(i, "; }")); return res.join("\n"); }).join("\n"), "\n if (dist > adjustedBorderSize_0) {\n gl_FragColor = borderColor_0;\n } else ").concat(borders.map(function (_, i) { return "if (dist > adjustedBorderSize_".concat(i, " - aaBorder) {\n gl_FragColor = mix(borderColor_").concat(i + 1, ", borderColor_").concat(i, ", (dist - adjustedBorderSize_").concat(i, " + aaBorder) / aaBorder);\n } else if (dist > adjustedBorderSize_").concat(i + 1, ") {\n gl_FragColor = borderColor_").concat(i + 1, ";\n } else "); }).join(""), " { /* Nothing to add here */ }\n #endif\n}\n"); return SHADER; } function getVertexShader(_ref) { var borders = _ref.borders; // language=GLSL var SHADER = /*glsl*/"\nattribute vec2 a_position;\nattribute float a_size;\nattribute float a_angle;\n\nuniform mat3 u_matrix;\nuniform float u_sizeRatio;\nuniform float u_correctionRatio;\n\nvarying vec2 v_diffVector;\nvarying float v_radius;\n\n#ifdef PICKING_MODE\nattribute vec4 a_id;\nvarying vec4 v_color;\n#else\n".concat(borders.flatMap(function (_ref2, i) { var size = _ref2.size; return "attribute" in size ? ["attribute float a_borderSize_".concat(i + 1, ";"), "varying float v_borderSize_".concat(i + 1, ";")] : []; }).join("\n"), "\n").concat(borders.flatMap(function (_ref3, i) { var color = _ref3.color; return "attribute" in color ? ["attribute vec4 a_borderColor_".concat(i + 1, ";"), "varying vec4 v_borderColor_".concat(i + 1, ";")] : []; }).join("\n"), "\n#endif\n\nconst float bias = 255.0 / 254.0;\nconst vec4 transparent = vec4(0.0, 0.0, 0.0, 0.0);\n\nvoid main() {\n float size = a_size * u_correctionRatio / u_sizeRatio * 4.0;\n vec2 diffVector = size * vec2(cos(a_angle), sin(a_angle));\n vec2 position = a_position + diffVector;\n gl_Position = vec4(\n (u_matrix * vec3(position, 1)).xy,\n 0,\n 1\n );\n\n v_radius = size / 2.0;\n v_diffVector = diffVector;\n\n #ifdef PICKING_MODE\n v_color = a_id;\n #else\n").concat(borders.flatMap(function (_ref4, i) { var size = _ref4.size; return "attribute" in size ? [" v_borderSize_".concat(i + 1, " = a_borderSize_").concat(i + 1, ";")] : []; }).join("\n"), "\n").concat(borders.flatMap(function (_ref5, i) { var color = _ref5.color; return "attribute" in color ? [" v_borderColor_".concat(i + 1, " = a_borderColor_").concat(i + 1, ";")] : []; }).join("\n"), "\n #endif\n}\n"); return SHADER; } var _WebGLRenderingContex = WebGLRenderingContext, UNSIGNED_BYTE = _WebGLRenderingContex.UNSIGNED_BYTE, FLOAT = _WebGLRenderingContex.FLOAT; function createNodeBorderProgram(inputOptions) { var _NodeBorderProgram; var options = _objectSpread2(_objectSpread2({}, DEFAULT_CREATE_NODE_BORDER_OPTIONS), inputOptions || {}); var borders = options.borders, drawLabel = options.drawLabel, drawHover = options.drawHover; var UNIFORMS = ["u_sizeRatio", "u_correctionRatio", "u_matrix"].concat(_toConsumableArray(borders.flatMap(function (_ref, i) { var color = _ref.color; return "value" in color ? ["u_borderColor_".concat(i + 1)] : []; }))); return _NodeBorderProgram = /*#__PURE__*/function (_NodeProgram) { _inherits(NodeBorderProgram, _NodeProgram); function NodeBorderProgram() { var _this; _classCallCheck(this, NodeBorderProgram); for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) { args[_key] = arguments[_key]; } _this = _callSuper(this, NodeBorderProgram, [].concat(args)); _defineProperty(_assertThisInitialized(_this), "drawLabel", drawLabel); _defineProperty(_assertThisInitialized(_this), "drawHover", drawHover); return _this; } _createClass(NodeBorderProgram, [{ key: "getDefinition", value: function getDefinition() { return { VERTICES: 3, VERTEX_SHADER_SOURCE: getVertexShader(options), FRAGMENT_SHADER_SOURCE: getFragmentShader(options), METHOD: WebGLRenderingContext.TRIANGLES, UNIFORMS: UNIFORMS, ATTRIBUTES: [{ name: "a_position", size: 2, type: FLOAT }, { name: "a_id", size: 4, type: UNSIGNED_BYTE, normalized: true }, { name: "a_size", size: 1, type: FLOAT }].concat(_toConsumableArray(borders.flatMap(function (_ref2, i) { var color = _ref2.color; return "attribute" in color ? [{ name: "a_borderColor_".concat(i + 1), size: 4, type: UNSIGNED_BYTE, normalized: true }] : []; })), _toConsumableArray(borders.flatMap(function (_ref3, i) { var size = _ref3.size; return "attribute" in size ? [{ name: "a_borderSize_".concat(i + 1), size: 1, type: FLOAT }] : []; }))), CONSTANT_ATTRIBUTES: [{ name: "a_angle", size: 1, type: FLOAT }], CONSTANT_DATA: [[NodeBorderProgram.ANGLE_1], [NodeBorderProgram.ANGLE_2], [NodeBorderProgram.ANGLE_3]] }; } }, { key: "processVisibleItem", value: function processVisibleItem(nodeIndex, startIndex, data) { var array = this.array; array[startIndex++] = data.x; array[startIndex++] = data.y; array[startIndex++] = nodeIndex; array[startIndex++] = data.size; borders.forEach(function (_ref4) { var color = _ref4.color; if ("attribute" in color) array[startIndex++] = utils.floatColor(data[color.attribute] || color.defaultValue || DEFAULT_COLOR); }); borders.forEach(function (_ref5) { var size = _ref5.size; if ("attribute" in size) array[startIndex++] = data[size.attribute] || size.defaultValue; }); } }, { key: "setUniforms", value: function setUniforms(params, _ref6) { var gl = _ref6.gl, uniformLocations = _ref6.uniformLocations; var u_sizeRatio = uniformLocations.u_sizeRatio, u_correctionRatio = uniformLocations.u_correctionRatio, u_matrix = uniformLocations.u_matrix; gl.uniform1f(u_correctionRatio, params.correctionRatio); gl.uniform1f(u_sizeRatio, params.sizeRatio); gl.uniformMatrix3fv(u_matrix, false, params.matrix); borders.forEach(function (_ref7, i) { var color = _ref7.color; if ("value" in color) { var location = uniformLocations["u_borderColor_".concat(i + 1)]; var _colorToArray = utils.colorToArray(color.value), _colorToArray2 = _slicedToArray(_colorToArray, 4), r = _colorToArray2[0], g = _colorToArray2[1], b = _colorToArray2[2], a = _colorToArray2[3]; gl.uniform4f(location, r / 255, g / 255, b / 255, a / 255); } }); } }]); return NodeBorderProgram; }(rendering.NodeProgram), _defineProperty(_NodeBorderProgram, "ANGLE_1", 0), _defineProperty(_NodeBorderProgram, "ANGLE_2", 2 * Math.PI / 3), _defineProperty(_NodeBorderProgram, "ANGLE_3", 4 * Math.PI / 3), _NodeBorderProgram; } var NodeBorderProgram = createNodeBorderProgram(); exports.NodeBorderProgram = NodeBorderProgram; exports.createNodeBorderProgram = createNodeBorderProgram;