@antv/layout 2.0.0-beta.0 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +296 -209
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +2 -2
- package/dist/index.min.js.map +1 -1
- package/dist/worker.js +1 -1
- package/dist/worker.js.map +1 -1
- package/lib/algorithm/antv-dagre/index.js +8 -7
- package/lib/algorithm/antv-dagre/index.js.map +1 -1
- package/lib/algorithm/antv-dagre/types.d.ts +3 -14
- package/lib/algorithm/circular/index.js +8 -7
- package/lib/algorithm/circular/index.js.map +1 -1
- package/lib/algorithm/circular/types.d.ts +0 -16
- package/lib/algorithm/combo-combined/index.js +9 -7
- package/lib/algorithm/combo-combined/index.js.map +1 -1
- package/lib/algorithm/combo-combined/types.d.ts +6 -18
- package/lib/algorithm/concentric/index.js +10 -16
- package/lib/algorithm/concentric/index.js.map +1 -1
- package/lib/algorithm/concentric/types.d.ts +3 -17
- package/lib/algorithm/d3-force/index.js +16 -12
- package/lib/algorithm/d3-force/index.js.map +1 -1
- package/lib/algorithm/d3-force/types.d.ts +10 -24
- package/lib/algorithm/d3-force-3d/index.js +1 -1
- package/lib/algorithm/d3-force-3d/index.js.map +1 -1
- package/lib/algorithm/d3-force-3d/types.d.ts +5 -4
- package/lib/algorithm/dagre/index.js +10 -7
- package/lib/algorithm/dagre/index.js.map +1 -1
- package/lib/algorithm/dagre/types.d.ts +8 -14
- package/lib/algorithm/force/index.d.ts +1 -1
- package/lib/algorithm/force/index.js +56 -44
- package/lib/algorithm/force/index.js.map +1 -1
- package/lib/algorithm/force/types.d.ts +39 -36
- package/lib/algorithm/force-atlas2/index.d.ts +1 -1
- package/lib/algorithm/force-atlas2/index.js +8 -7
- package/lib/algorithm/force-atlas2/index.js.map +1 -1
- package/lib/algorithm/force-atlas2/types.d.ts +0 -14
- package/lib/algorithm/fruchterman/index.d.ts +1 -1
- package/lib/algorithm/fruchterman/index.js +8 -10
- package/lib/algorithm/fruchterman/index.js.map +1 -1
- package/lib/algorithm/fruchterman/simulation.js +2 -1
- package/lib/algorithm/fruchterman/simulation.js.map +1 -1
- package/lib/algorithm/fruchterman/types.d.ts +2 -1
- package/lib/algorithm/grid/index.d.ts +1 -1
- package/lib/algorithm/grid/index.js +29 -34
- package/lib/algorithm/grid/index.js.map +1 -1
- package/lib/algorithm/grid/types.d.ts +5 -24
- package/lib/algorithm/mds/index.js +1 -0
- package/lib/algorithm/mds/index.js.map +1 -1
- package/lib/algorithm/radial/index.js +8 -5
- package/lib/algorithm/radial/index.js.map +1 -1
- package/lib/algorithm/radial/radial-nonoverlap-force.js +2 -4
- package/lib/algorithm/radial/radial-nonoverlap-force.js.map +1 -1
- package/lib/algorithm/radial/types.d.ts +3 -16
- package/lib/algorithm/random/index.js +1 -0
- package/lib/algorithm/random/index.js.map +1 -1
- package/lib/algorithm/types.d.ts +16 -0
- package/lib/index.d.ts +5 -3
- package/lib/index.js +3 -1
- package/lib/index.js.map +1 -1
- package/lib/node_modules/@antv/expr/dist/index.esm.js +4 -0
- package/lib/node_modules/@antv/expr/dist/index.esm.js.map +1 -0
- package/lib/types/common.d.ts +17 -1
- package/lib/types/data.d.ts +1 -1
- package/lib/util/expr.d.ts +12 -0
- package/lib/util/expr.js +26 -0
- package/lib/util/expr.js.map +1 -0
- package/lib/util/format.d.ts +37 -0
- package/lib/util/format.js +61 -17
- package/lib/util/format.js.map +1 -1
- package/lib/util/order.d.ts +3 -4
- package/lib/util/order.js.map +1 -1
- package/lib/util/size.d.ts +2 -1
- package/lib/util/size.js +9 -1
- package/lib/util/size.js.map +1 -1
- package/lib/worker.js +283 -227
- package/lib/worker.js.map +1 -1
- package/package.json +2 -1
- package/src/algorithm/antv-dagre/index.ts +15 -12
- package/src/algorithm/antv-dagre/types.ts +3 -14
- package/src/algorithm/circular/index.ts +5 -4
- package/src/algorithm/circular/types.ts +0 -15
- package/src/algorithm/combo-combined/index.ts +21 -17
- package/src/algorithm/combo-combined/types.ts +6 -21
- package/src/algorithm/concentric/index.ts +18 -16
- package/src/algorithm/concentric/types.ts +2 -16
- package/src/algorithm/d3-force/index.ts +25 -18
- package/src/algorithm/d3-force/types.ts +9 -22
- package/src/algorithm/d3-force-3d/index.ts +1 -1
- package/src/algorithm/d3-force-3d/types.ts +5 -0
- package/src/algorithm/dagre/index.ts +9 -7
- package/src/algorithm/dagre/types.ts +7 -15
- package/src/algorithm/force/index.ts +64 -40
- package/src/algorithm/force/types.ts +76 -45
- package/src/algorithm/force-atlas2/index.ts +13 -15
- package/src/algorithm/force-atlas2/types.ts +0 -12
- package/src/algorithm/fruchterman/index.ts +7 -15
- package/src/algorithm/fruchterman/simulation.ts +2 -2
- package/src/algorithm/fruchterman/types.ts +5 -2
- package/src/algorithm/grid/index.ts +45 -46
- package/src/algorithm/grid/types.ts +6 -35
- package/src/algorithm/radial/index.ts +14 -6
- package/src/algorithm/radial/radial-nonoverlap-force.ts +11 -6
- package/src/algorithm/radial/types.ts +2 -15
- package/src/algorithm/types.ts +18 -0
- package/src/types/common.ts +22 -0
- package/src/types/data.ts +1 -1
- package/src/util/expr.ts +26 -0
- package/src/util/format.ts +71 -27
- package/src/util/index.ts +2 -0
- package/src/util/order.ts +3 -9
- package/src/util/size.ts +8 -0
package/lib/worker.js
CHANGED
|
@@ -634,21 +634,6 @@ function isEmpty(value) {
|
|
|
634
634
|
return true;
|
|
635
635
|
}
|
|
636
636
|
|
|
637
|
-
/**
|
|
638
|
-
* https://github.com/developit/dlv/blob/master/index.js
|
|
639
|
-
* @param obj
|
|
640
|
-
* @param key
|
|
641
|
-
* @param defaultValue
|
|
642
|
-
*/
|
|
643
|
-
var get$1 = (function (obj, key, defaultValue) {
|
|
644
|
-
var p = 0;
|
|
645
|
-
var keyArr = isString(key) ? key.split('.') : key;
|
|
646
|
-
while (obj && p < keyArr.length) {
|
|
647
|
-
obj = obj[keyArr[p++]];
|
|
648
|
-
}
|
|
649
|
-
return obj === undefined || p < keyArr.length ? defaultValue : obj;
|
|
650
|
-
});
|
|
651
|
-
|
|
652
637
|
var hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
653
638
|
var pick = (function (object, keys) {
|
|
654
639
|
if (object === null || !isPlainObject(object)) {
|
|
@@ -681,6 +666,156 @@ function applySingleNodeLayout(model, center, dimensions = 2) {
|
|
|
681
666
|
}
|
|
682
667
|
}
|
|
683
668
|
|
|
669
|
+
const e={abs:Math.abs,ceil:Math.ceil,floor:Math.floor,max:Math.max,min:Math.min,round:Math.round,sqrt:Math.sqrt,pow:Math.pow};class n extends Error{constructor(e,t,n){super(e),this.position=t,this.token=n,this.name="ExpressionError";}}var r;!function(e){e[e.STRING=0]="STRING",e[e.NUMBER=1]="NUMBER",e[e.BOOLEAN=2]="BOOLEAN",e[e.NULL=3]="NULL",e[e.IDENTIFIER=4]="IDENTIFIER",e[e.OPERATOR=5]="OPERATOR",e[e.FUNCTION=6]="FUNCTION",e[e.DOT=7]="DOT",e[e.BRACKET_LEFT=8]="BRACKET_LEFT",e[e.BRACKET_RIGHT=9]="BRACKET_RIGHT",e[e.PAREN_LEFT=10]="PAREN_LEFT",e[e.PAREN_RIGHT=11]="PAREN_RIGHT",e[e.COMMA=12]="COMMA",e[e.QUESTION=13]="QUESTION",e[e.COLON=14]="COLON",e[e.DOLLAR=15]="DOLLAR";}(r||(r={}));const o=new Set([32,9,10,13]),a$2=new Set([43,45,42,47,37,33,38,124,61,60,62]),s=new Map([["true",r.BOOLEAN],["false",r.BOOLEAN],["null",r.NULL]]),i=new Map([["===",true],["!==",true],["<=",true],[">=",true],["&&",true],["||",true],["+",true],["-",true],["*",true],["/",true],["%",true],["!",true],["<",true],[">",true]]),u=new Map([[46,r.DOT],[91,r.BRACKET_LEFT],[93,r.BRACKET_RIGHT],[40,r.PAREN_LEFT],[41,r.PAREN_RIGHT],[44,r.COMMA],[63,r.QUESTION],[58,r.COLON],[36,r.DOLLAR]]),c$2=new Map;for(const[e,t]of u.entries())c$2.set(e,{type:t,value:String.fromCharCode(e)});function p(e){return e>=48&&e<=57}function l(e){return e>=97&&e<=122||e>=65&&e<=90||95===e}function f(e){return l(e)||p(e)}function E(e){return a$2.has(e)}var h;!function(e){e[e.Program=0]="Program",e[e.Literal=1]="Literal",e[e.Identifier=2]="Identifier",e[e.MemberExpression=3]="MemberExpression",e[e.CallExpression=4]="CallExpression",e[e.BinaryExpression=5]="BinaryExpression",e[e.UnaryExpression=6]="UnaryExpression",e[e.ConditionalExpression=7]="ConditionalExpression";}(h||(h={}));const d=new Map([["||",2],["&&",3],["===",4],["!==",4],[">",5],[">=",5],["<",5],["<=",5],["+",6],["-",6],["*",7],["/",7],["%",7],["!",8]]),R={type:h.Literal,value:null},T={type:h.Literal,value:true},w={type:h.Literal,value:false},y$4=e=>{let t=0;const o=e.length,a=()=>t>=o?null:e[t],s=()=>e[t++],i=e=>{const t=a();return null!==t&&t.type===e},u=e=>e.type===r.OPERATOR?d.get(e.value)||-1:e.type===r.DOT||e.type===r.BRACKET_LEFT?9:e.type===r.QUESTION?1:-1,c=e=>{let o,u;if(s().type===r.DOT){if(!i(r.IDENTIFIER)){const e=a();throw new n("Expected property name",t,e?e.value:"<end of input>")}const e=s();o={type:h.Identifier,name:e.value},u=false;}else {if(o=l(0),!i(r.BRACKET_RIGHT)){const e=a();throw new n("Expected closing bracket",t,e?e.value:"<end of input>")}s(),u=true;}return {type:h.MemberExpression,object:e,property:o,computed:u}},p=()=>{const e=a();if(!e)throw new n("Unexpected end of input",t,"<end of input>");if(e.type===r.OPERATOR&&("!"===e.value||"-"===e.value)){s();const t=p();return {type:h.UnaryExpression,operator:e.value,argument:t,prefix:true}}switch(e.type){case r.NUMBER:return s(),{type:h.Literal,value:Number(e.value)};case r.STRING:return s(),{type:h.Literal,value:e.value};case r.BOOLEAN:return s(),"true"===e.value?T:w;case r.NULL:return s(),R;case r.IDENTIFIER:return s(),{type:h.Identifier,name:e.value};case r.FUNCTION:return (()=>{const e=s(),o=[];if(!i(r.PAREN_LEFT)){const e=a();throw new n("Expected opening parenthesis after function name",t,e?e.value:"<end of input>")}for(s();;){if(i(r.PAREN_RIGHT)){s();break}if(!a()){const e=a();throw new n("Expected closing parenthesis",t,e?e.value:"<end of input>")}if(o.length>0){if(!i(r.COMMA)){const e=a();throw new n("Expected comma between function arguments",t,e?e.value:"<end of input>")}s();}const e=l(0);o.push(e);}return {type:h.CallExpression,callee:{type:h.Identifier,name:e.value},arguments:o}})();case r.PAREN_LEFT:{s();const e=l(0);if(!i(r.PAREN_RIGHT)){const e=a();throw new n("Expected closing parenthesis",t,e?e.value:"<end of input>")}return s(),e}default:throw new n(`Unexpected token: ${e.type}`,t,e.value)}},l=(f=0)=>{let E=p();for(;t<o;){const o=e[t],p=u(o);if(p<=f)break;if(o.type!==r.QUESTION)if(o.type!==r.OPERATOR){if(o.type!==r.DOT&&o.type!==r.BRACKET_LEFT)break;E=c(E);}else {s();const e=l(p);E={type:h.BinaryExpression,operator:o.value,left:E,right:e};}else {s();const e=l(0);if(!i(r.COLON)){const e=a();throw new n("Expected : in conditional expression",t,e?e.value:"<end of input>")}s();const o=l(0);E={type:h.ConditionalExpression,test:E,consequent:e,alternate:o};}}return E},f=l();return {type:h.Program,body:f}},O=(e,t,r)=>{let o=t;r&&(o={...t,context:{...t.context,...r}});const a=e=>{switch(e.type){case h.Literal:return (e=>e.value)(e);case h.Identifier:return (e=>{if(!(e.name in o.context))throw new n(`Undefined variable: ${e.name}`);return o.context[e.name]})(e);case h.MemberExpression:return (e=>{const t=a(e.object);if(null==t)throw new n("Cannot access property of null or undefined");return t[e.computed?a(e.property):e.property.name]})(e);case h.CallExpression:return (e=>{const t=o.functions[e.callee.name];if(!t)throw new n(`Undefined function: ${e.callee.name}`);return t(...e.arguments.map((e=>a(e))))})(e);case h.BinaryExpression:return (e=>{if("&&"===e.operator){const t=a(e.left);return t?a(e.right):t}if("||"===e.operator){return a(e.left)||a(e.right)}const t=a(e.left),r=a(e.right);switch(e.operator){case "+":return t+r;case "-":return t-r;case "*":return t*r;case "/":return t/r;case "%":return t%r;case "===":return t===r;case "!==":return t!==r;case ">":return t>r;case ">=":return t>=r;case "<":return t<r;case "<=":return t<=r;default:throw new n(`Unknown operator: ${e.operator}`)}})(e);case h.UnaryExpression:return (e=>{const t=a(e.argument);if(e.prefix)switch(e.operator){case "!":return !t;case "-":if("number"!=typeof t)throw new n(`Cannot apply unary - to non-number: ${t}`);return -t;default:throw new n(`Unknown operator: ${e.operator}`)}throw new n(`Postfix operators are not supported: ${e.operator}`)})(e);case h.ConditionalExpression:return (e=>{const t=a(e.test);return a(t?e.consequent:e.alternate)})(e);default:throw new n(`Evaluation error: Unsupported node type: ${e.type}`)}};return a(e.body)};function A(t){const a=(e=>{const t=e,a=t.length,u=new Array(Math.ceil(a/3));let h=0,d=0;function R(e){const o=d+1;d++;let s="",i=false;for(;d<a;){const n=t.charCodeAt(d);if(n===e)return i||(s=t.substring(o,d)),d++,{type:r.STRING,value:s};92===n?(i||(s=t.substring(o,d),i=true),d++,s+=t[d]):i&&(s+=t[d]),d++;}throw new n(`Unterminated string starting with ${String.fromCharCode(e)}`,d,t.substring(Math.max(0,d-10),d))}function T(){const e=d;for(45===t.charCodeAt(d)&&d++;d<a&&p(t.charCodeAt(d));)d++;if(d<a&&46===t.charCodeAt(d))for(d++;d<a&&p(t.charCodeAt(d));)d++;const n=t.slice(e,d);return {type:r.NUMBER,value:n}}function w(){d++;const e=d;if(d<a&&l(t.charCodeAt(d)))for(d++;d<a&&f(t.charCodeAt(d));)d++;const n=t.slice(e,d);return {type:r.FUNCTION,value:n}}function y(){const e=d++;for(;d<a&&f(t.charCodeAt(d));)d++;const n=t.slice(e,d),o=s.get(n);return o?{type:o,value:n}:{type:r.IDENTIFIER,value:n}}function O(){if(d+2<a){const e=t.substring(d,d+3);if(i.has(e))return d+=3,{type:r.OPERATOR,value:e}}if(d+1<a){const e=t.substring(d,d+2);if(i.has(e))return d+=2,{type:r.OPERATOR,value:e}}const e=t[d];if(i.has(e))return d++,{type:r.OPERATOR,value:e};throw new n(`Unknown operator at position ${d}: ${t.substring(d,d+1)}`,d,t.substring(Math.max(0,d-10),d))}for(;d<a;){const e=t.charCodeAt(d);if(A=e,o.has(A)){d++;continue}const r=c$2.get(e);if(r)u[h++]=r,d++;else if(34!==e&&39!==e)if(p(e)||45===e&&d+1<a&&p(t.charCodeAt(d+1)))u[h++]=T();else if(64!==e)if(l(e))u[h++]=y();else {if(!E(e))throw new n(`Unexpected character: ${t[d]}`,d,t.substring(Math.max(0,d-10),d));u[h++]=O();}else u[h++]=w();else u[h++]=R(e);}var A;return h===u.length?u:u.slice(0,h)})(t),u=y$4(a),h=((e={},t={})=>({context:e,functions:t}))({},e);return (e={})=>O(u,h,e)}function N(e,t={}){return A(e)(t)}
|
|
670
|
+
|
|
671
|
+
/**
|
|
672
|
+
* Evaluate an expression if (and only if) it's a valid string expression.
|
|
673
|
+
* - Returns `undefined` when `expression` is not a string, empty, or invalid.
|
|
674
|
+
*
|
|
675
|
+
* @example
|
|
676
|
+
* evaluateExpression('x + y', { x: 10, y: 20 }) // 30
|
|
677
|
+
*/
|
|
678
|
+
function evaluateExpression(expression, context) {
|
|
679
|
+
if (typeof expression !== 'string')
|
|
680
|
+
return undefined;
|
|
681
|
+
const source = expression.trim();
|
|
682
|
+
if (!source)
|
|
683
|
+
return undefined;
|
|
684
|
+
try {
|
|
685
|
+
A(source);
|
|
686
|
+
return N(source, context);
|
|
687
|
+
}
|
|
688
|
+
catch (_a) {
|
|
689
|
+
return undefined;
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
function parseSize(size) {
|
|
694
|
+
if (!size)
|
|
695
|
+
return [0, 0, 0];
|
|
696
|
+
if (isNumber(size))
|
|
697
|
+
return [size, size, size];
|
|
698
|
+
else if (Array.isArray(size) && size.length === 0)
|
|
699
|
+
return [0, 0, 0];
|
|
700
|
+
const [x, y = x, z = x] = size;
|
|
701
|
+
return [x, y, z];
|
|
702
|
+
}
|
|
703
|
+
function isSize(value) {
|
|
704
|
+
if (isNumber(value))
|
|
705
|
+
return true;
|
|
706
|
+
if (Array.isArray(value)) {
|
|
707
|
+
return value.every((item) => isNumber(item));
|
|
708
|
+
}
|
|
709
|
+
return false;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Format a value into a callable function when it is a string expression.
|
|
714
|
+
* - `string` => `(context) => evaluateExpression(string, context)`
|
|
715
|
+
* - `function` => returned as-is
|
|
716
|
+
* - other => returned as-is
|
|
717
|
+
*/
|
|
718
|
+
function formatFn(value, argNames) {
|
|
719
|
+
if (typeof value === 'function')
|
|
720
|
+
return value;
|
|
721
|
+
if (typeof value === 'string') {
|
|
722
|
+
const expr = value;
|
|
723
|
+
return (...argv) => {
|
|
724
|
+
const ctx = {};
|
|
725
|
+
for (let i = 0; i < argNames.length; i++) {
|
|
726
|
+
ctx[argNames[i]] = argv[i];
|
|
727
|
+
}
|
|
728
|
+
return evaluateExpression(expr, ctx);
|
|
729
|
+
};
|
|
730
|
+
}
|
|
731
|
+
return () => value;
|
|
732
|
+
}
|
|
733
|
+
/**
|
|
734
|
+
* Format value with multiple types into a function that returns a number
|
|
735
|
+
* @param value The value to be formatted
|
|
736
|
+
* @param defaultValue The default value when value is invalid
|
|
737
|
+
* @returns A function that returns a number
|
|
738
|
+
*/
|
|
739
|
+
function formatNumberFn(value, defaultValue, type = 'node') {
|
|
740
|
+
// If value is undefined, return default value function
|
|
741
|
+
if (isNil(value)) {
|
|
742
|
+
return () => defaultValue;
|
|
743
|
+
}
|
|
744
|
+
// If value is an expression, return a function that evaluates the expression
|
|
745
|
+
if (isString(value)) {
|
|
746
|
+
const numberFn = formatFn(value, [type]);
|
|
747
|
+
return (d) => {
|
|
748
|
+
const evaluated = numberFn(d);
|
|
749
|
+
if (isNumber(evaluated))
|
|
750
|
+
return evaluated;
|
|
751
|
+
return defaultValue;
|
|
752
|
+
};
|
|
753
|
+
}
|
|
754
|
+
// If value is a function, return it directly
|
|
755
|
+
if (isFunction(value)) {
|
|
756
|
+
return value;
|
|
757
|
+
}
|
|
758
|
+
// If value is a number, return a function that returns this number
|
|
759
|
+
if (isNumber(value)) {
|
|
760
|
+
return () => value;
|
|
761
|
+
}
|
|
762
|
+
// For other cases (undefined or invalid values), return default value function
|
|
763
|
+
return () => defaultValue;
|
|
764
|
+
}
|
|
765
|
+
/**
|
|
766
|
+
* Format size config with multiple types into a function that returns a size
|
|
767
|
+
* @param value The value to be formatted
|
|
768
|
+
* @param defaultValue The default value when value is invalid
|
|
769
|
+
* @param resultIsNumber Whether to return a number (max of width/height) or size array
|
|
770
|
+
* @returns A function that returns a size
|
|
771
|
+
*/
|
|
772
|
+
function formatSizeFn(value, defaultValue = 10, type = 'node') {
|
|
773
|
+
// If value is undefined, return default value function
|
|
774
|
+
if (isNil(value)) {
|
|
775
|
+
return () => defaultValue;
|
|
776
|
+
}
|
|
777
|
+
// If value is an expression, return a function that evaluates the expression
|
|
778
|
+
if (isString(value)) {
|
|
779
|
+
const sizeFn = formatFn(value, [type]);
|
|
780
|
+
return (d) => {
|
|
781
|
+
const evaluated = sizeFn(d);
|
|
782
|
+
if (isSize(evaluated))
|
|
783
|
+
return evaluated;
|
|
784
|
+
return defaultValue;
|
|
785
|
+
};
|
|
786
|
+
}
|
|
787
|
+
// If value is a function, return it directly
|
|
788
|
+
if (isFunction(value)) {
|
|
789
|
+
return value;
|
|
790
|
+
}
|
|
791
|
+
// If value is a number, return a function that returns this number
|
|
792
|
+
if (isNumber(value)) {
|
|
793
|
+
return () => value;
|
|
794
|
+
}
|
|
795
|
+
// If value is an array, return max or the array itself
|
|
796
|
+
if (Array.isArray(value)) {
|
|
797
|
+
return () => value;
|
|
798
|
+
}
|
|
799
|
+
return () => defaultValue;
|
|
800
|
+
}
|
|
801
|
+
/**
|
|
802
|
+
* Format nodeSize and nodeSpacing into a function that returns the total size
|
|
803
|
+
* @param nodeSize The size of the node
|
|
804
|
+
* @param nodeSpacing The spacing around the node
|
|
805
|
+
* @param defaultNodeSize The default node size when value is invalid
|
|
806
|
+
* @param defaultNodeSpacing The default node spacing when value is invalid
|
|
807
|
+
* @returns A function that returns the total size (node size + spacing)
|
|
808
|
+
*/
|
|
809
|
+
const formatNodeSizeFn = (nodeSize, nodeSpacing, defaultNodeSize = 10, defaultNodeSpacing = 0) => {
|
|
810
|
+
const nodeSpacingFunc = formatSizeFn(nodeSpacing, defaultNodeSpacing);
|
|
811
|
+
const nodeSizeFunc = formatSizeFn(nodeSize, defaultNodeSize);
|
|
812
|
+
return (d) => {
|
|
813
|
+
const [sizeW, sizeH, sizeD] = parseSize(nodeSizeFunc(d));
|
|
814
|
+
const [spacingW, spacingH, spacingD] = parseSize(nodeSpacingFunc(d));
|
|
815
|
+
return [sizeW + spacingW, sizeH + spacingH, sizeD + spacingD];
|
|
816
|
+
};
|
|
817
|
+
};
|
|
818
|
+
|
|
684
819
|
/**
|
|
685
820
|
* Get the adjacency list of the graph model.
|
|
686
821
|
*/
|
|
@@ -816,14 +951,6 @@ class MinHeap {
|
|
|
816
951
|
}
|
|
817
952
|
}
|
|
818
953
|
|
|
819
|
-
/**
|
|
820
|
-
* Get nested property value
|
|
821
|
-
* For example: getNestedValue(obj, 'a.b.c') will return obj.a.b.c
|
|
822
|
-
*/
|
|
823
|
-
function getNestedValue(obj, path) {
|
|
824
|
-
const keys = String(path).split('.');
|
|
825
|
-
return get$1(obj, keys);
|
|
826
|
-
}
|
|
827
954
|
/**
|
|
828
955
|
* Merge objects, but undefined values in source objects will not override existing values
|
|
829
956
|
* @param target - The target object
|
|
@@ -960,17 +1087,6 @@ function parsePoint(point) {
|
|
|
960
1087
|
return [point.x, point.y, (_a = point.z) !== null && _a !== void 0 ? _a : 0];
|
|
961
1088
|
}
|
|
962
1089
|
|
|
963
|
-
function parseSize(size) {
|
|
964
|
-
if (!size)
|
|
965
|
-
return [0, 0, 0];
|
|
966
|
-
if (isNumber(size))
|
|
967
|
-
return [size, size, size];
|
|
968
|
-
else if (Array.isArray(size) && size.length === 0)
|
|
969
|
-
return [0, 0, 0];
|
|
970
|
-
const [x, y = x, z = x] = size;
|
|
971
|
-
return [x, y, z];
|
|
972
|
-
}
|
|
973
|
-
|
|
974
1090
|
/**
|
|
975
1091
|
* Viewport configuration such as width, height and center point.
|
|
976
1092
|
*/
|
|
@@ -986,71 +1102,6 @@ const normalizeViewport = (options) => {
|
|
|
986
1102
|
};
|
|
987
1103
|
};
|
|
988
1104
|
|
|
989
|
-
/**
|
|
990
|
-
* Format value with multiple types into a function that returns a number
|
|
991
|
-
* @param value The value to be formatted
|
|
992
|
-
* @param defaultValue The default value when value is invalid
|
|
993
|
-
* @returns A function that returns a number
|
|
994
|
-
*/
|
|
995
|
-
function formatNumberFn(value, defaultValue) {
|
|
996
|
-
// If value is a function, return it directly
|
|
997
|
-
if (isFunction(value)) {
|
|
998
|
-
return value;
|
|
999
|
-
}
|
|
1000
|
-
// If value is a number, return a function that returns this number
|
|
1001
|
-
if (isNumber(value)) {
|
|
1002
|
-
return () => value;
|
|
1003
|
-
}
|
|
1004
|
-
// For other cases (undefined or invalid values), return default value function
|
|
1005
|
-
return () => defaultValue;
|
|
1006
|
-
}
|
|
1007
|
-
/**
|
|
1008
|
-
* Format size config with multiple types into a function that returns a size
|
|
1009
|
-
* @param value The value to be formatted
|
|
1010
|
-
* @param defaultValue The default value when value is invalid
|
|
1011
|
-
* @param resultIsNumber Whether to return a number (max of width/height) or size array
|
|
1012
|
-
* @returns A function that returns a size
|
|
1013
|
-
*/
|
|
1014
|
-
function formatSizeFn(value, defaultValue = 10) {
|
|
1015
|
-
// If value is undefined, return default value function
|
|
1016
|
-
if (!value) {
|
|
1017
|
-
return () => defaultValue;
|
|
1018
|
-
}
|
|
1019
|
-
// If value is a function, return it directly
|
|
1020
|
-
if (isFunction(value)) {
|
|
1021
|
-
return value;
|
|
1022
|
-
}
|
|
1023
|
-
// If value is a number, return a function that returns this number
|
|
1024
|
-
if (isNumber(value)) {
|
|
1025
|
-
return () => value;
|
|
1026
|
-
}
|
|
1027
|
-
// If value is an array, return max or the array itself
|
|
1028
|
-
if (Array.isArray(value)) {
|
|
1029
|
-
return () => value;
|
|
1030
|
-
}
|
|
1031
|
-
// If value is an object with width and height
|
|
1032
|
-
if (isObject(value) && value.width && value.height) {
|
|
1033
|
-
return () => [value.width, value.height];
|
|
1034
|
-
}
|
|
1035
|
-
return () => defaultValue;
|
|
1036
|
-
}
|
|
1037
|
-
/**
|
|
1038
|
-
* Format nodeSize and nodeSpacing into a function that returns the total size
|
|
1039
|
-
* @param nodeSize The size of the node
|
|
1040
|
-
* @param nodeSpacing The spacing around the node
|
|
1041
|
-
* @param defaultNodeSize The default node size when value is invalid
|
|
1042
|
-
* @returns A function that returns the total size (node size + spacing)
|
|
1043
|
-
*/
|
|
1044
|
-
const formatNodeSizeFn = (nodeSize, nodeSpacing, defaultNodeSize = 10) => {
|
|
1045
|
-
const nodeSpacingFunc = formatNumberFn(nodeSpacing, 0);
|
|
1046
|
-
const nodeSizeFunc = formatSizeFn(nodeSize, defaultNodeSize);
|
|
1047
|
-
return (node) => {
|
|
1048
|
-
const size = nodeSizeFunc(node);
|
|
1049
|
-
const spacing = nodeSpacingFunc(node);
|
|
1050
|
-
return Math.max(...parseSize(size)) + spacing;
|
|
1051
|
-
};
|
|
1052
|
-
};
|
|
1053
|
-
|
|
1054
1105
|
class GraphLib {
|
|
1055
1106
|
constructor(data, options = {}) {
|
|
1056
1107
|
this.edgeIdCounter = new Map();
|
|
@@ -4911,6 +4962,7 @@ const canonicalize = (attrs = {}) => {
|
|
|
4911
4962
|
|
|
4912
4963
|
const DEFAULTS_LAYOUT_OPTIONS$8 = {
|
|
4913
4964
|
nodeSize: 10,
|
|
4965
|
+
nodeSpacing: 0,
|
|
4914
4966
|
rankdir: 'TB',
|
|
4915
4967
|
nodesep: 50,
|
|
4916
4968
|
ranksep: 50,
|
|
@@ -4935,27 +4987,27 @@ class AntVDagreLayout extends BaseLayout {
|
|
|
4935
4987
|
}
|
|
4936
4988
|
layout(options) {
|
|
4937
4989
|
return __awaiter(this, void 0, void 0, function* () {
|
|
4938
|
-
const { nodeSize, align, rankdir = 'TB', ranksep, nodesep, edgeLabelSpace, ranker = 'tight-tree', nodeOrder, begin, controlPoints, radial, sortByCombo,
|
|
4990
|
+
const { nodeSize, nodeSpacing, align, rankdir = 'TB', ranksep, nodesep, edgeLabelSpace, ranker = 'tight-tree', nodeOrder, begin, controlPoints, radial, sortByCombo,
|
|
4939
4991
|
// focusNode,
|
|
4940
4992
|
preset, ranksepFunc, nodesepFunc, } = options;
|
|
4941
|
-
const ranksepfunc = formatNumberFn(ranksepFunc, ranksep !== null && ranksep !== void 0 ? ranksep : 50);
|
|
4942
|
-
const nodesepfunc = formatNumberFn(nodesepFunc, nodesep !== null && nodesep !== void 0 ? nodesep : 50);
|
|
4993
|
+
const ranksepfunc = formatNumberFn(ranksepFunc, ranksep !== null && ranksep !== void 0 ? ranksep : 50, 'node');
|
|
4994
|
+
const nodesepfunc = formatNumberFn(nodesepFunc, nodesep !== null && nodesep !== void 0 ? nodesep : 50, 'node');
|
|
4943
4995
|
let horisep = nodesepfunc;
|
|
4944
4996
|
let vertisep = ranksepfunc;
|
|
4945
4997
|
if (rankdir === 'LR' || rankdir === 'RL') {
|
|
4946
4998
|
horisep = ranksepfunc;
|
|
4947
4999
|
vertisep = nodesepfunc;
|
|
4948
5000
|
}
|
|
4949
|
-
const nodeSizeFunc = formatSizeFn(nodeSize, DEFAULTS_LAYOUT_OPTIONS$8.nodeSize);
|
|
4950
5001
|
// Create internal graph
|
|
4951
5002
|
const g = new DagreGraph({ tree: [] });
|
|
4952
5003
|
// copy graph to g
|
|
4953
5004
|
const nodes = this.model.nodes();
|
|
4954
5005
|
const edges = this.model.edges();
|
|
5006
|
+
const sizeFn = formatNodeSizeFn(nodeSize, nodeSpacing, DEFAULTS_LAYOUT_OPTIONS$8.nodeSize, DEFAULTS_LAYOUT_OPTIONS$8.nodeSpacing);
|
|
4955
5007
|
nodes.forEach((node) => {
|
|
4956
5008
|
var _a;
|
|
4957
5009
|
const raw = node._original;
|
|
4958
|
-
const size =
|
|
5010
|
+
const size = sizeFn(raw);
|
|
4959
5011
|
const verti = vertisep(raw);
|
|
4960
5012
|
const hori = horisep(raw);
|
|
4961
5013
|
const width = size[0] + 2 * hori;
|
|
@@ -5237,7 +5289,7 @@ const getControlPoints = (points, sourceNode, targetNode, layerCoordsArr, isHori
|
|
|
5237
5289
|
return controlPoints;
|
|
5238
5290
|
};
|
|
5239
5291
|
|
|
5240
|
-
const DEFAULT_LAYOUT_OPTIONS = {
|
|
5292
|
+
const DEFAULT_LAYOUT_OPTIONS$1 = {
|
|
5241
5293
|
radius: null,
|
|
5242
5294
|
startRadius: null,
|
|
5243
5295
|
endRadius: null,
|
|
@@ -5248,6 +5300,7 @@ const DEFAULT_LAYOUT_OPTIONS = {
|
|
|
5248
5300
|
ordering: null,
|
|
5249
5301
|
angleRatio: 1,
|
|
5250
5302
|
nodeSize: 10,
|
|
5303
|
+
nodeSpacing: 0,
|
|
5251
5304
|
};
|
|
5252
5305
|
/**
|
|
5253
5306
|
* <zh/> 环形布局
|
|
@@ -5260,7 +5313,7 @@ class CircularLayout extends BaseLayout {
|
|
|
5260
5313
|
this.id = 'circular';
|
|
5261
5314
|
}
|
|
5262
5315
|
getDefaultOptions() {
|
|
5263
|
-
return DEFAULT_LAYOUT_OPTIONS;
|
|
5316
|
+
return DEFAULT_LAYOUT_OPTIONS$1;
|
|
5264
5317
|
}
|
|
5265
5318
|
layout() {
|
|
5266
5319
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -5286,11 +5339,11 @@ class CircularLayout extends BaseLayout {
|
|
|
5286
5339
|
}
|
|
5287
5340
|
let { radius, startRadius, endRadius } = this.options;
|
|
5288
5341
|
const nodes = this.model.nodes();
|
|
5289
|
-
const
|
|
5290
|
-
if (
|
|
5342
|
+
const sizeFn = formatNodeSizeFn(nodeSize, nodeSpacing, DEFAULT_LAYOUT_OPTIONS$1.nodeSize, DEFAULT_LAYOUT_OPTIONS$1.nodeSpacing);
|
|
5343
|
+
if (nodeSpacing) {
|
|
5291
5344
|
let perimeter = 0;
|
|
5292
5345
|
for (const node of nodes) {
|
|
5293
|
-
perimeter +=
|
|
5346
|
+
perimeter += Math.max(...sizeFn(node._original));
|
|
5294
5347
|
}
|
|
5295
5348
|
radius = perimeter / (2 * Math.PI);
|
|
5296
5349
|
}
|
|
@@ -5367,17 +5420,10 @@ class ConcentricLayout extends BaseLayout {
|
|
|
5367
5420
|
applySingleNodeLayout(this.model, center);
|
|
5368
5421
|
return;
|
|
5369
5422
|
}
|
|
5370
|
-
const { sortBy: propsSortBy, maxLevelDiff: propsMaxLevelDiff, sweep: propsSweep, clockwise, equidistant, preventOverlap, startAngle = DEFAULTS_LAYOUT_OPTIONS$7.startAngle, nodeSize
|
|
5371
|
-
|
|
5372
|
-
|
|
5373
|
-
|
|
5374
|
-
const testValue = propsSortBy(testNode._original);
|
|
5375
|
-
if (typeof testValue !== 'number')
|
|
5376
|
-
sortBy = 'degree';
|
|
5377
|
-
}
|
|
5378
|
-
else {
|
|
5379
|
-
sortBy = 'degree';
|
|
5380
|
-
}
|
|
5423
|
+
const { sortBy: propsSortBy, maxLevelDiff: propsMaxLevelDiff, sweep: propsSweep, clockwise, equidistant, preventOverlap, startAngle = DEFAULTS_LAYOUT_OPTIONS$7.startAngle, nodeSize, nodeSpacing, } = this.options;
|
|
5424
|
+
const sortBy = !propsSortBy || propsSortBy === 'degree'
|
|
5425
|
+
? 'degree'
|
|
5426
|
+
: formatFn(propsSortBy, ['node']);
|
|
5381
5427
|
if (sortBy === 'degree') {
|
|
5382
5428
|
orderByDegree(this.model);
|
|
5383
5429
|
}
|
|
@@ -5394,15 +5440,15 @@ class ConcentricLayout extends BaseLayout {
|
|
|
5394
5440
|
for (const node of nodes) {
|
|
5395
5441
|
const v = sortBy === 'degree'
|
|
5396
5442
|
? this.model.degree(node.id)
|
|
5397
|
-
: sortBy
|
|
5443
|
+
: sortBy(node._original);
|
|
5398
5444
|
sortKeys.set(node.id, v);
|
|
5399
5445
|
}
|
|
5400
5446
|
const maxValueNode = this.model.firstNode();
|
|
5401
5447
|
const maxLevelDiff = propsMaxLevelDiff || sortKeys.get(maxValueNode.id) / 4;
|
|
5402
|
-
const
|
|
5448
|
+
const sizeFn = formatNodeSizeFn(nodeSize, nodeSpacing, DEFAULTS_LAYOUT_OPTIONS$7.nodeSize, DEFAULTS_LAYOUT_OPTIONS$7.nodeSpacing);
|
|
5403
5449
|
const nodeDistances = new Map();
|
|
5404
5450
|
for (const node of nodes) {
|
|
5405
|
-
nodeDistances.set(node.id,
|
|
5451
|
+
nodeDistances.set(node.id, Math.max(...sizeFn(node._original)));
|
|
5406
5452
|
}
|
|
5407
5453
|
// put the values into levels
|
|
5408
5454
|
const levels = [{ nodes: [] }];
|
|
@@ -7128,9 +7174,7 @@ function forceInABox() {
|
|
|
7128
7174
|
}
|
|
7129
7175
|
|
|
7130
7176
|
const DEFAULTS_LAYOUT_OPTIONS$6 = {
|
|
7131
|
-
|
|
7132
|
-
id: (d) => String(d.id),
|
|
7133
|
-
},
|
|
7177
|
+
edgeId: 'edge.id',
|
|
7134
7178
|
manyBody: {
|
|
7135
7179
|
strength: -30,
|
|
7136
7180
|
},
|
|
@@ -7385,7 +7429,9 @@ class D3ForceLayout extends BaseLayoutWithIterations {
|
|
|
7385
7429
|
if (options.manyBody === false)
|
|
7386
7430
|
return undefined;
|
|
7387
7431
|
return assignDefined({}, options.manyBody || {}, {
|
|
7388
|
-
strength: options.nodeStrength
|
|
7432
|
+
strength: options.nodeStrength
|
|
7433
|
+
? formatFn(options.nodeStrength, ['node'])
|
|
7434
|
+
: undefined,
|
|
7389
7435
|
distanceMin: options.distanceMin,
|
|
7390
7436
|
distanceMax: options.distanceMax,
|
|
7391
7437
|
theta: options.theta,
|
|
@@ -7418,9 +7464,13 @@ class D3ForceLayout extends BaseLayoutWithIterations {
|
|
|
7418
7464
|
if (options.link === false)
|
|
7419
7465
|
return undefined;
|
|
7420
7466
|
return assignDefined({}, options.link || {}, {
|
|
7421
|
-
id: options.edgeId,
|
|
7422
|
-
distance: options.linkDistance
|
|
7423
|
-
|
|
7467
|
+
id: options.edgeId ? formatFn(options.edgeId, ['edge']) : undefined,
|
|
7468
|
+
distance: options.linkDistance
|
|
7469
|
+
? formatFn(options.linkDistance, ['edge'])
|
|
7470
|
+
: undefined,
|
|
7471
|
+
strength: options.edgeStrength
|
|
7472
|
+
? formatFn(options.edgeStrength, ['edge'])
|
|
7473
|
+
: undefined,
|
|
7424
7474
|
iterations: options.edgeIterations,
|
|
7425
7475
|
});
|
|
7426
7476
|
}
|
|
@@ -7452,9 +7502,8 @@ class D3ForceLayout extends BaseLayoutWithIterations {
|
|
|
7452
7502
|
if (options.preventOverlap === false &&
|
|
7453
7503
|
(options.collide === false || options.collide === undefined))
|
|
7454
7504
|
return undefined;
|
|
7455
|
-
const
|
|
7456
|
-
|
|
7457
|
-
: undefined;
|
|
7505
|
+
const sizeFn = formatNodeSizeFn(options.nodeSize, options.nodeSpacing, DEFAULTS_LAYOUT_OPTIONS$6.nodeSize, DEFAULTS_LAYOUT_OPTIONS$6.nodeSpacing);
|
|
7506
|
+
const radius = (d) => Math.max(...sizeFn(d._original)) / 2;
|
|
7458
7507
|
return assignDefined({}, options.collide || {}, {
|
|
7459
7508
|
radius: (options.collide && options.collide.radius) || radius,
|
|
7460
7509
|
strength: options.collideStrength,
|
|
@@ -7595,7 +7644,7 @@ class D3ForceLayout extends BaseLayoutWithIterations {
|
|
|
7595
7644
|
['centerY', center && center.y],
|
|
7596
7645
|
['template', 'force'],
|
|
7597
7646
|
['strength', clusterFociStrength],
|
|
7598
|
-
['groupBy', clusterBy],
|
|
7647
|
+
['groupBy', clusterBy ? formatFn(clusterBy, ['node']) : undefined],
|
|
7599
7648
|
['nodes', this.model.nodes()],
|
|
7600
7649
|
['links', this.model.edges()],
|
|
7601
7650
|
['forceLinkDistance', clusterEdgeDistance],
|
|
@@ -9327,7 +9376,7 @@ class D3Force3DLayout extends D3ForceLayout {
|
|
|
9327
9376
|
return {
|
|
9328
9377
|
numDimensions: 3,
|
|
9329
9378
|
link: {
|
|
9330
|
-
id: (edge) =>
|
|
9379
|
+
id: (edge) => edge.id,
|
|
9331
9380
|
},
|
|
9332
9381
|
manyBody: {},
|
|
9333
9382
|
center: {
|
|
@@ -23108,11 +23157,13 @@ class DagreLayout extends BaseLayout {
|
|
|
23108
23157
|
}
|
|
23109
23158
|
});
|
|
23110
23159
|
const { edgeLabelSize, edgeLabelOffset, edgeLabelPos, edgeMinLen, edgeWeight, } = this.options;
|
|
23111
|
-
const edgeLabelSizeFn = formatSizeFn(edgeLabelSize, 0);
|
|
23112
|
-
const edgeLabelOffsetFn = formatNumberFn(edgeLabelOffset, 10);
|
|
23113
|
-
const edgeLabelPosFn = typeof edgeLabelPos === '
|
|
23114
|
-
|
|
23115
|
-
|
|
23160
|
+
const edgeLabelSizeFn = formatSizeFn(edgeLabelSize, 0, 'edge');
|
|
23161
|
+
const edgeLabelOffsetFn = formatNumberFn(edgeLabelOffset, 10, 'edge');
|
|
23162
|
+
const edgeLabelPosFn = typeof edgeLabelPos === 'string'
|
|
23163
|
+
? () => edgeLabelPos
|
|
23164
|
+
: formatFn(edgeLabelPos, ['edge']);
|
|
23165
|
+
const edgeMinLenFn = formatNumberFn(edgeMinLen, 1, 'edge');
|
|
23166
|
+
const edgeWeightFn = formatNumberFn(edgeWeight, 1, 'edge');
|
|
23116
23167
|
this.model.forEachEdge((edge) => {
|
|
23117
23168
|
const raw = edge._original;
|
|
23118
23169
|
const [lw, lh] = parseSize(edgeLabelSizeFn(raw));
|
|
@@ -24162,28 +24213,43 @@ class ForceLayout extends BaseLayoutWithIterations {
|
|
|
24162
24213
|
*/
|
|
24163
24214
|
parseOptions(options) {
|
|
24164
24215
|
const _ = Object.assign(Object.assign({}, options), normalizeViewport(options));
|
|
24216
|
+
// Format nodeClusterBy (for clustering / leafCluster)
|
|
24217
|
+
if (_.nodeClusterBy) {
|
|
24218
|
+
_.nodeClusterBy = formatFn(_.nodeClusterBy, ['node']);
|
|
24219
|
+
}
|
|
24165
24220
|
// Format node mass
|
|
24166
24221
|
if (!options.getMass) {
|
|
24167
|
-
_.getMass = (
|
|
24168
|
-
if (!
|
|
24222
|
+
_.getMass = (node) => {
|
|
24223
|
+
if (!node)
|
|
24169
24224
|
return 1;
|
|
24170
24225
|
const massWeight = 1;
|
|
24171
|
-
const degree = this.model.degree(
|
|
24226
|
+
const degree = this.model.degree(node.id, 'both');
|
|
24172
24227
|
return !degree || degree < 5 ? massWeight : degree * 5 * massWeight;
|
|
24173
24228
|
};
|
|
24174
24229
|
}
|
|
24230
|
+
else {
|
|
24231
|
+
_.getMass = formatNumberFn(options.getMass, 1);
|
|
24232
|
+
}
|
|
24233
|
+
// Format per-node center force callback
|
|
24234
|
+
if (options.getCenter) {
|
|
24235
|
+
const params = ['node', 'degree'];
|
|
24236
|
+
_.getCenter = formatFn(options.getCenter, params);
|
|
24237
|
+
}
|
|
24175
24238
|
// Format node size
|
|
24176
|
-
|
|
24239
|
+
const nodeSizeVec = formatNodeSizeFn(options.nodeSize, options.nodeSpacing);
|
|
24240
|
+
_.nodeSize = (node) => {
|
|
24241
|
+
if (!node)
|
|
24242
|
+
return 0;
|
|
24243
|
+
const [w, h, z] = nodeSizeVec(node);
|
|
24244
|
+
return Math.max(w, h, z);
|
|
24245
|
+
};
|
|
24177
24246
|
// Format node / edge strengths
|
|
24178
24247
|
_.linkDistance = options.linkDistance
|
|
24179
|
-
?
|
|
24180
|
-
: (
|
|
24181
|
-
return (1 +
|
|
24182
|
-
_.nodeSize(this.model.node(edge.source)._original) +
|
|
24183
|
-
_.nodeSize(this.model.node(edge.target)._original));
|
|
24184
|
-
};
|
|
24248
|
+
? formatFn(options.linkDistance, ['edge', 'source', 'target'])
|
|
24249
|
+
: (_, source, target) => 1 + _.nodeSize(source) + _.nodeSize(target);
|
|
24185
24250
|
_.nodeStrength = formatNumberFn(options.nodeStrength, 1);
|
|
24186
|
-
_.edgeStrength = formatNumberFn(options.edgeStrength, 1);
|
|
24251
|
+
_.edgeStrength = formatNumberFn(options.edgeStrength, 1, 'edge');
|
|
24252
|
+
_.clusterNodeStrength = formatNumberFn(options.clusterNodeStrength, 1);
|
|
24187
24253
|
// Format centripetal options
|
|
24188
24254
|
this.formatCentripetal(_);
|
|
24189
24255
|
return _;
|
|
@@ -24192,23 +24258,30 @@ class ForceLayout extends BaseLayoutWithIterations {
|
|
|
24192
24258
|
* Format centripetal options
|
|
24193
24259
|
*/
|
|
24194
24260
|
formatCentripetal(options) {
|
|
24195
|
-
var _a;
|
|
24196
|
-
const { dimensions, centripetalOptions, center,
|
|
24197
|
-
|
|
24198
|
-
const
|
|
24199
|
-
|
|
24200
|
-
|
|
24201
|
-
|
|
24202
|
-
|
|
24203
|
-
|
|
24204
|
-
|
|
24205
|
-
|
|
24206
|
-
|
|
24207
|
-
|
|
24208
|
-
|
|
24209
|
-
|
|
24210
|
-
|
|
24211
|
-
|
|
24261
|
+
var _a, _b;
|
|
24262
|
+
const { dimensions, centripetalOptions, center, leafCluster, clustering, nodeClusterBy, } = options;
|
|
24263
|
+
const leafParams = ['node', 'nodes', 'edges'];
|
|
24264
|
+
const leafFn = formatFn(centripetalOptions === null || centripetalOptions === void 0 ? void 0 : centripetalOptions.leaf, leafParams);
|
|
24265
|
+
const singleFn = formatNumberFn(centripetalOptions === null || centripetalOptions === void 0 ? void 0 : centripetalOptions.single, 2);
|
|
24266
|
+
const othersFn = formatNumberFn(centripetalOptions === null || centripetalOptions === void 0 ? void 0 : centripetalOptions.others, 1);
|
|
24267
|
+
const centerRaw = (_a = centripetalOptions === null || centripetalOptions === void 0 ? void 0 : centripetalOptions.center) !== null && _a !== void 0 ? _a : ((_) => {
|
|
24268
|
+
return {
|
|
24269
|
+
x: center[0],
|
|
24270
|
+
y: center[1],
|
|
24271
|
+
z: dimensions === 3 ? center[2] : undefined,
|
|
24272
|
+
};
|
|
24273
|
+
});
|
|
24274
|
+
const centerFn = formatFn(centerRaw, [
|
|
24275
|
+
'node',
|
|
24276
|
+
'nodes',
|
|
24277
|
+
'edges',
|
|
24278
|
+
'width',
|
|
24279
|
+
'height',
|
|
24280
|
+
]);
|
|
24281
|
+
const basicCentripetal = Object.assign(Object.assign({}, centripetalOptions), { leaf: leafFn, single: singleFn, others: othersFn, center: centerFn });
|
|
24282
|
+
// If user provided centripetalOptions, normalize them even without clustering modes.
|
|
24283
|
+
if (centripetalOptions) {
|
|
24284
|
+
options.centripetalOptions = basicCentripetal;
|
|
24212
24285
|
}
|
|
24213
24286
|
let sameTypeLeafMap;
|
|
24214
24287
|
let clusters;
|
|
@@ -24216,8 +24289,8 @@ class ForceLayout extends BaseLayoutWithIterations {
|
|
|
24216
24289
|
if (leafCluster && nodeClusterBy) {
|
|
24217
24290
|
sameTypeLeafMap = this.getSameTypeLeafMap(nodeClusterBy);
|
|
24218
24291
|
clusters =
|
|
24219
|
-
Array.from(new Set((
|
|
24220
|
-
.nodes()) === null ||
|
|
24292
|
+
Array.from(new Set((_b = this.model
|
|
24293
|
+
.nodes()) === null || _b === void 0 ? void 0 : _b.map((node) => nodeClusterBy(node._original)))) || [];
|
|
24221
24294
|
options.centripetalOptions = Object.assign({}, basicCentripetal, {
|
|
24222
24295
|
single: () => 100,
|
|
24223
24296
|
leaf: (node) => {
|
|
@@ -24290,17 +24363,6 @@ class ForceLayout extends BaseLayoutWithIterations {
|
|
|
24290
24363
|
},
|
|
24291
24364
|
});
|
|
24292
24365
|
}
|
|
24293
|
-
// Normalize functions
|
|
24294
|
-
const { leaf, single, others } = options.centripetalOptions || {};
|
|
24295
|
-
if (leaf && typeof leaf !== 'function') {
|
|
24296
|
-
options.centripetalOptions.leaf = () => leaf;
|
|
24297
|
-
}
|
|
24298
|
-
if (single && typeof single !== 'function') {
|
|
24299
|
-
options.centripetalOptions.single = () => single;
|
|
24300
|
-
}
|
|
24301
|
-
if (others && typeof others !== 'function') {
|
|
24302
|
-
options.centripetalOptions.others = () => others;
|
|
24303
|
-
}
|
|
24304
24366
|
}
|
|
24305
24367
|
/**
|
|
24306
24368
|
* Get same type leaf map for clustering
|
|
@@ -25136,9 +25198,9 @@ class ForceAtlas2Layout extends BaseLayoutWithIterations {
|
|
|
25136
25198
|
}
|
|
25137
25199
|
getSizes(nodeSize, nodeSpacing) {
|
|
25138
25200
|
const result = {};
|
|
25201
|
+
const nodeSizeFn = formatNodeSizeFn(nodeSize, nodeSpacing, DEFAULTS_LAYOUT_OPTIONS$4.nodeSize, DEFAULTS_LAYOUT_OPTIONS$4.nodeSpacing);
|
|
25139
25202
|
this.model.forEachNode((node) => {
|
|
25140
|
-
|
|
25141
|
-
result[node.id] = nodeSizeFn(node._original);
|
|
25203
|
+
result[node.id] = Math.max(...nodeSizeFn(node._original));
|
|
25142
25204
|
});
|
|
25143
25205
|
return result;
|
|
25144
25206
|
}
|
|
@@ -25150,7 +25212,7 @@ class ForceAtlas2Layout extends BaseLayoutWithIterations {
|
|
|
25150
25212
|
return this.simulation;
|
|
25151
25213
|
}
|
|
25152
25214
|
parseOptions(options = {}) {
|
|
25153
|
-
const { barnesHut, prune, maxIteration, kr, kg
|
|
25215
|
+
const { barnesHut, prune, maxIteration, kr, kg } = options;
|
|
25154
25216
|
const auto = {};
|
|
25155
25217
|
const n = this.model.nodeCount();
|
|
25156
25218
|
if (barnesHut === undefined && n > 250)
|
|
@@ -25185,7 +25247,7 @@ class ForceAtlas2Layout extends BaseLayoutWithIterations {
|
|
|
25185
25247
|
else if (n > 500)
|
|
25186
25248
|
auto.kg = 1;
|
|
25187
25249
|
}
|
|
25188
|
-
return Object.assign(Object.assign(Object.assign(
|
|
25250
|
+
return Object.assign(Object.assign(Object.assign({}, options), auto), normalizeViewport(options));
|
|
25189
25251
|
}
|
|
25190
25252
|
stop() {
|
|
25191
25253
|
var _a;
|
|
@@ -25570,7 +25632,7 @@ const DEFAULTS_LAYOUT_OPTIONS$3 = {
|
|
|
25570
25632
|
clusterGravity: 10,
|
|
25571
25633
|
width: 300,
|
|
25572
25634
|
height: 300,
|
|
25573
|
-
nodeClusterBy: '
|
|
25635
|
+
nodeClusterBy: 'node.cluster',
|
|
25574
25636
|
dimensions: 2,
|
|
25575
25637
|
};
|
|
25576
25638
|
class FruchtermanLayout extends BaseLayoutWithIterations {
|
|
@@ -25582,15 +25644,12 @@ class FruchtermanLayout extends BaseLayoutWithIterations {
|
|
|
25582
25644
|
getDefaultOptions() {
|
|
25583
25645
|
return DEFAULTS_LAYOUT_OPTIONS$3;
|
|
25584
25646
|
}
|
|
25585
|
-
parseOptions(options) {
|
|
25647
|
+
parseOptions(options = {}) {
|
|
25586
25648
|
const { clustering, nodeClusterBy } = this.options;
|
|
25587
25649
|
const clusteringEnabled = clustering && !!nodeClusterBy;
|
|
25588
|
-
|
|
25589
|
-
? (node) => getNestedValue(node, nodeClusterBy)
|
|
25590
|
-
: nodeClusterBy;
|
|
25591
|
-
Object.assign((options || (options = {})), normalizeViewport(options), {
|
|
25650
|
+
Object.assign(options, normalizeViewport(options), {
|
|
25592
25651
|
clustering: clusteringEnabled,
|
|
25593
|
-
nodeClusterBy:
|
|
25652
|
+
nodeClusterBy: formatFn(nodeClusterBy, ['node']),
|
|
25594
25653
|
});
|
|
25595
25654
|
return options;
|
|
25596
25655
|
}
|
|
@@ -25645,6 +25704,19 @@ class FruchtermanLayout extends BaseLayoutWithIterations {
|
|
|
25645
25704
|
}
|
|
25646
25705
|
}
|
|
25647
25706
|
|
|
25707
|
+
const DEFAULT_LAYOUT_OPTIONS = {
|
|
25708
|
+
begin: [0, 0],
|
|
25709
|
+
preventOverlap: true,
|
|
25710
|
+
condense: false,
|
|
25711
|
+
rows: undefined,
|
|
25712
|
+
cols: undefined,
|
|
25713
|
+
position: undefined,
|
|
25714
|
+
sortBy: 'degree',
|
|
25715
|
+
nodeSize: 30,
|
|
25716
|
+
nodeSpacing: 10,
|
|
25717
|
+
width: 300,
|
|
25718
|
+
height: 300,
|
|
25719
|
+
};
|
|
25648
25720
|
/**
|
|
25649
25721
|
* <zh/> 网格布局
|
|
25650
25722
|
*
|
|
@@ -25656,23 +25728,10 @@ class GridLayout extends BaseLayout {
|
|
|
25656
25728
|
this.id = 'grid';
|
|
25657
25729
|
}
|
|
25658
25730
|
getDefaultOptions() {
|
|
25659
|
-
return
|
|
25660
|
-
begin: [0, 0],
|
|
25661
|
-
preventOverlap: true,
|
|
25662
|
-
preventOverlapPadding: 10,
|
|
25663
|
-
condense: false,
|
|
25664
|
-
rows: undefined,
|
|
25665
|
-
cols: undefined,
|
|
25666
|
-
position: undefined,
|
|
25667
|
-
sortBy: 'degree',
|
|
25668
|
-
nodeSize: 30,
|
|
25669
|
-
width: 300,
|
|
25670
|
-
height: 300,
|
|
25671
|
-
};
|
|
25731
|
+
return DEFAULT_LAYOUT_OPTIONS;
|
|
25672
25732
|
}
|
|
25673
|
-
|
|
25674
|
-
|
|
25675
|
-
const { rows: propRows, cols: propCols } = options;
|
|
25733
|
+
parseOptions(options = {}, model) {
|
|
25734
|
+
const { rows: propRows, cols: propCols, position: propPosition, sortBy: propSortBy, } = options;
|
|
25676
25735
|
const { width, height, center } = normalizeViewport(options);
|
|
25677
25736
|
let rows = options.rows;
|
|
25678
25737
|
let cols = options.cols;
|
|
@@ -25727,20 +25786,20 @@ class GridLayout extends BaseLayout {
|
|
|
25727
25786
|
}
|
|
25728
25787
|
}
|
|
25729
25788
|
}
|
|
25730
|
-
const
|
|
25731
|
-
|
|
25732
|
-
|
|
25733
|
-
|
|
25734
|
-
|
|
25735
|
-
|
|
25789
|
+
const sortBy = !propSortBy
|
|
25790
|
+
? DEFAULT_LAYOUT_OPTIONS.sortBy
|
|
25791
|
+
: propSortBy === 'degree' || propSortBy === 'id'
|
|
25792
|
+
? propSortBy
|
|
25793
|
+
: formatFn(propSortBy, ['nodeA', 'nodeB']);
|
|
25794
|
+
return Object.assign(Object.assign({}, options), { sortBy,
|
|
25736
25795
|
rcs,
|
|
25737
25796
|
center,
|
|
25738
25797
|
width,
|
|
25739
|
-
height });
|
|
25798
|
+
height, position: formatFn(propPosition, ['node']) });
|
|
25740
25799
|
}
|
|
25741
25800
|
layout() {
|
|
25742
25801
|
return __awaiter(this, void 0, void 0, function* () {
|
|
25743
|
-
const { begin, rcs, sortBy, width, height, condense,
|
|
25802
|
+
const { begin, rcs, sortBy, width, height, condense, preventOverlap, nodeSpacing, nodeSize, position, } = this.parseOptions(this.options, this.model);
|
|
25744
25803
|
const n = this.model.nodeCount();
|
|
25745
25804
|
if (!n || n === 1) {
|
|
25746
25805
|
applySingleNodeLayout(this.model, begin);
|
|
@@ -25758,14 +25817,9 @@ class GridLayout extends BaseLayout {
|
|
|
25758
25817
|
let cellWidth = condense ? 0 : width / rcs.cols;
|
|
25759
25818
|
let cellHeight = condense ? 0 : height / rcs.rows;
|
|
25760
25819
|
if (preventOverlap) {
|
|
25820
|
+
const sizeFn = formatNodeSizeFn(nodeSize, nodeSpacing, DEFAULT_LAYOUT_OPTIONS.nodeSize, DEFAULT_LAYOUT_OPTIONS.nodeSpacing);
|
|
25761
25821
|
this.model.forEachNode((node) => {
|
|
25762
|
-
const
|
|
25763
|
-
const [nodeW, nodeH] = parseSize(nodeSize(nodeData) || 30);
|
|
25764
|
-
const p = nodeSpacing !== undefined
|
|
25765
|
-
? nodeSpacing(nodeData)
|
|
25766
|
-
: preventOverlapPadding;
|
|
25767
|
-
const w = nodeW + p;
|
|
25768
|
-
const h = nodeH + p;
|
|
25822
|
+
const [w, h] = sizeFn(node._original);
|
|
25769
25823
|
cellWidth = Math.max(cellWidth, w);
|
|
25770
25824
|
cellHeight = Math.max(cellHeight, h);
|
|
25771
25825
|
});
|
|
@@ -31848,8 +31902,8 @@ const getRepulsion = (model, displacements, k, radiiMap, nodeSizeFunc) => {
|
|
|
31848
31902
|
vecx = 0.01 * sign;
|
|
31849
31903
|
vecy = 0.01 * sign;
|
|
31850
31904
|
}
|
|
31851
|
-
const nodeSizeU = Math.max(...
|
|
31852
|
-
const nodeSizeV = Math.max(...
|
|
31905
|
+
const nodeSizeU = Math.max(...nodeSizeFunc(nodeU._original));
|
|
31906
|
+
const nodeSizeV = Math.max(...nodeSizeFunc(nodeV._original));
|
|
31853
31907
|
// these two nodes overlap
|
|
31854
31908
|
if (vecLength < nodeSizeV / 2 + nodeSizeU / 2) {
|
|
31855
31909
|
const common = (k * k) / vecLength;
|
|
@@ -31932,6 +31986,8 @@ const DEFAULTS_LAYOUT_OPTIONS = {
|
|
|
31932
31986
|
sortStrength: 10,
|
|
31933
31987
|
strictRadial: true,
|
|
31934
31988
|
unitRadius: null,
|
|
31989
|
+
nodeSize: 10,
|
|
31990
|
+
nodeSpacing: 0,
|
|
31935
31991
|
};
|
|
31936
31992
|
/**
|
|
31937
31993
|
* <zh/> 径向布局
|
|
@@ -32000,7 +32056,7 @@ class RadialLayout extends BaseLayout {
|
|
|
32000
32056
|
});
|
|
32001
32057
|
// stagger the overlapped nodes
|
|
32002
32058
|
if (preventOverlap) {
|
|
32003
|
-
const nodeSizeFunc = formatNodeSizeFn(nodeSize, nodeSpacing);
|
|
32059
|
+
const nodeSizeFunc = formatNodeSizeFn(nodeSize, nodeSpacing, DEFAULTS_LAYOUT_OPTIONS.nodeSize, DEFAULTS_LAYOUT_OPTIONS.nodeSpacing);
|
|
32004
32060
|
const nonoverlapForceParams = {
|
|
32005
32061
|
nodeSizeFunc,
|
|
32006
32062
|
radiiMap,
|
|
@@ -32079,7 +32135,7 @@ const eIdealDisMatrix = (model, distances, linkDistance, radii, unitRadius, sort
|
|
|
32079
32135
|
radiusScale[i] = radii[i] / unitRadius;
|
|
32080
32136
|
const baseLink = (linkDistance + unitRadius) / 2;
|
|
32081
32137
|
const sortCache = new Map();
|
|
32082
|
-
const sortFn =
|
|
32138
|
+
const sortFn = !sortBy || sortBy === 'data' ? null : formatFn(sortBy, ['node']);
|
|
32083
32139
|
const isDataSort = sortBy === 'data';
|
|
32084
32140
|
for (let i = 0; i < n; i++) {
|
|
32085
32141
|
const row = distances[i];
|