mirror of
https://github.com/barsdeveloper/ueblueprint.git
synced 2026-05-22 06:13:23 +08:00
Better links curve for close-by nodes
This commit is contained in:
30
dist/ueblueprint.js
vendored
30
dist/ueblueprint.js
vendored
@@ -80,7 +80,7 @@ class Configuration {
|
|||||||
*/
|
*/
|
||||||
static linkRightSVGPath = (start, c1, c2) => {
|
static linkRightSVGPath = (start, c1, c2) => {
|
||||||
let end = 100 - start;
|
let end = 100 - start;
|
||||||
return `M ${start} 0 C ${c1} 0, ${c2} 0, 50 50 S ${end - c1 + start} 100, ${end} 100`
|
return `M ${start} 0 C ${c1.toFixed(3)} 0, ${c2.toFixed(3)} 0, 50 50 S ${(end - c1 + start).toFixed(3)} 100, ${end.toFixed(3)} 100`
|
||||||
}
|
}
|
||||||
static maxZoom = 7
|
static maxZoom = 7
|
||||||
static minZoom = -12
|
static minZoom = -12
|
||||||
@@ -448,6 +448,11 @@ class Utility {
|
|||||||
return 1 / (1 + (x / (1 - x) ** -curvature))
|
return 1 / (1 + (x / (1 - x) ** -curvature))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {Number} x */
|
||||||
|
static sigmoidPositive(x, curvature = 3.7, length = 1.1) {
|
||||||
|
return 1 - Math.exp(-((x / length) ** curvature))
|
||||||
|
}
|
||||||
|
|
||||||
/** @param {Number} value */
|
/** @param {Number} value */
|
||||||
static clamp(value, min = -Infinity, max = Infinity) {
|
static clamp(value, min = -Infinity, max = Infinity) {
|
||||||
return Math.min(Math.max(value, min), max)
|
return Math.min(Math.max(value, min), max)
|
||||||
@@ -5279,9 +5284,11 @@ class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
|
|
||||||
static c1DecreasingValue = LinkTemplate.decreasingValue(-0.15, [100, 15])
|
static c1DecreasingValue = LinkTemplate.decreasingValue(-0.15, [100, 15])
|
||||||
|
|
||||||
static c2DecreasingValue = LinkTemplate.decreasingValue(-0.06, [500, 130])
|
static c2DecreasingValue = LinkTemplate.decreasingValue(-0.05, [500, 130])
|
||||||
|
|
||||||
static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 30])
|
static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 40])
|
||||||
|
|
||||||
|
#uniqueId = `ueb-id-${Math.floor(Math.random() * 1E12)}`
|
||||||
|
|
||||||
/** @param {[Number, Number]} location */
|
/** @param {[Number, Number]} location */
|
||||||
#createKnot = location => {
|
#createKnot = location => {
|
||||||
@@ -5345,11 +5352,11 @@ class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
const dx = Math.max(Math.abs(this.element.fromX - this.element.toX), 1);
|
const dx = Math.max(Math.abs(this.element.fromX - this.element.toX), 1);
|
||||||
Math.max(Math.abs(this.element.fromY - this.element.toY), 1);
|
const dy = Math.max(Math.abs(this.element.fromY - this.element.toY), 1);
|
||||||
const width = Math.max(dx, Configuration.linkMinWidth);
|
const width = Math.max(dx, Configuration.linkMinWidth);
|
||||||
// const height = Math.max(Math.abs(link.fromY - link.toY), 1)
|
// const height = Math.max(Math.abs(link.fromY - link.toY), 1)
|
||||||
const fillRatio = dx / width;
|
const fillRatio = dx / width;
|
||||||
// const aspectRatio = width / height
|
const aspectRatio = dy / dx;
|
||||||
const xInverted = this.element.originatesFromInput
|
const xInverted = this.element.originatesFromInput
|
||||||
? this.element.fromX < this.element.toX
|
? this.element.fromX < this.element.toX
|
||||||
: this.element.toX < this.element.fromX;
|
: this.element.toX < this.element.fromX;
|
||||||
@@ -5357,15 +5364,15 @@ class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
? (width - dx) / 2 // Start from half the empty space
|
? (width - dx) / 2 // Start from half the empty space
|
||||||
: 0; // Otherwise start from the beginning
|
: 0; // Otherwise start from the beginning
|
||||||
this.element.startPercentage = xInverted ? this.element.startPixels + fillRatio * 100 : this.element.startPixels;
|
this.element.startPercentage = xInverted ? this.element.startPixels + fillRatio * 100 : this.element.startPixels;
|
||||||
const c1
|
const c1 =
|
||||||
= this.element.startPercentage
|
this.element.startPercentage
|
||||||
+ (xInverted
|
+ (xInverted
|
||||||
? LinkTemplate.c1DecreasingValue(width)
|
? LinkTemplate.c1DecreasingValue(width)
|
||||||
: 10
|
: 10
|
||||||
)
|
)
|
||||||
* fillRatio;
|
* fillRatio;
|
||||||
let c2 = LinkTemplate.c2Clamped(xInverted ? -dx : dx) + this.element.startPercentage;
|
let c2 = LinkTemplate.c2Clamped(dx) * Utility.sigmoidPositive(fillRatio + aspectRatio * 0.5, 1.5, 2) + this.element.startPercentage;
|
||||||
c2 = Math.min(c2, LinkTemplate.c2DecreasingValue(width));
|
c2 = xInverted ? Math.min(c2, LinkTemplate.c2DecreasingValue(width)) : c2;
|
||||||
this.element.svgPathD = Configuration.linkRightSVGPath(this.element.startPercentage, c1, c2);
|
this.element.svgPathD = Configuration.linkRightSVGPath(this.element.startPercentage, c1, c2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5385,12 +5392,11 @@ class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const uniqueId = `ueb-id-${Math.floor(Math.random() * 1E12)}`;
|
|
||||||
return y`
|
return y`
|
||||||
<svg version="1.2" baseProfile="tiny" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
|
<svg version="1.2" baseProfile="tiny" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||||
<g class="ueb-link-area">
|
<g class="ueb-link-area">
|
||||||
<path id="${uniqueId}" fill="none" vector-effect="non-scaling-stroke" d="${this.element.svgPathD}" />
|
<path id="${this.#uniqueId}" fill="none" vector-effect="non-scaling-stroke" d="${this.element.svgPathD}" />
|
||||||
<use href="#${uniqueId}" pointer-events="stroke" stroke-width="20" />
|
<use href="#${this.#uniqueId}" pointer-events="stroke" stroke-width="20" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
${this.element.linkMessageIcon || this.element.linkMessageText ? y`
|
${this.element.linkMessageIcon || this.element.linkMessageText ? y`
|
||||||
|
|||||||
6
dist/ueblueprint.min.js
vendored
6
dist/ueblueprint.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -56,7 +56,7 @@ export default class Configuration {
|
|||||||
*/
|
*/
|
||||||
static linkRightSVGPath = (start, c1, c2) => {
|
static linkRightSVGPath = (start, c1, c2) => {
|
||||||
let end = 100 - start
|
let end = 100 - start
|
||||||
return `M ${start} 0 C ${c1} 0, ${c2} 0, 50 50 S ${end - c1 + start} 100, ${end} 100`
|
return `M ${start} 0 C ${c1.toFixed(3)} 0, ${c2.toFixed(3)} 0, 50 50 S ${(end - c1 + start).toFixed(3)} 100, ${end.toFixed(3)} 100`
|
||||||
}
|
}
|
||||||
static maxZoom = 7
|
static maxZoom = 7
|
||||||
static minZoom = -12
|
static minZoom = -12
|
||||||
|
|||||||
@@ -35,6 +35,11 @@ export default class Utility {
|
|||||||
return 1 / (1 + (x / (1 - x) ** -curvature))
|
return 1 / (1 + (x / (1 - x) ** -curvature))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @param {Number} x */
|
||||||
|
static sigmoidPositive(x, curvature = 3.7, length = 1.1) {
|
||||||
|
return 1 - Math.exp(-((x / length) ** curvature))
|
||||||
|
}
|
||||||
|
|
||||||
/** @param {Number} value */
|
/** @param {Number} value */
|
||||||
static clamp(value, min = -Infinity, max = Infinity) {
|
static clamp(value, min = -Infinity, max = Infinity) {
|
||||||
return Math.min(Math.max(value, min), max)
|
return Math.min(Math.max(value, min), max)
|
||||||
|
|||||||
@@ -59,9 +59,11 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
|
|
||||||
static c1DecreasingValue = LinkTemplate.decreasingValue(-0.15, [100, 15])
|
static c1DecreasingValue = LinkTemplate.decreasingValue(-0.15, [100, 15])
|
||||||
|
|
||||||
static c2DecreasingValue = LinkTemplate.decreasingValue(-0.06, [500, 130])
|
static c2DecreasingValue = LinkTemplate.decreasingValue(-0.05, [500, 130])
|
||||||
|
|
||||||
static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 30])
|
static c2Clamped = LinkTemplate.clampedLine([0, 100], [200, 40])
|
||||||
|
|
||||||
|
#uniqueId = `ueb-id-${Math.floor(Math.random() * 1E12)}`
|
||||||
|
|
||||||
/** @param {[Number, Number]} location */
|
/** @param {[Number, Number]} location */
|
||||||
#createKnot = location => {
|
#createKnot = location => {
|
||||||
@@ -129,7 +131,7 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
const width = Math.max(dx, Configuration.linkMinWidth)
|
const width = Math.max(dx, Configuration.linkMinWidth)
|
||||||
// const height = Math.max(Math.abs(link.fromY - link.toY), 1)
|
// const height = Math.max(Math.abs(link.fromY - link.toY), 1)
|
||||||
const fillRatio = dx / width
|
const fillRatio = dx / width
|
||||||
// const aspectRatio = width / height
|
const aspectRatio = dy / dx
|
||||||
const xInverted = this.element.originatesFromInput
|
const xInverted = this.element.originatesFromInput
|
||||||
? this.element.fromX < this.element.toX
|
? this.element.fromX < this.element.toX
|
||||||
: this.element.toX < this.element.fromX
|
: this.element.toX < this.element.fromX
|
||||||
@@ -137,15 +139,15 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
? (width - dx) / 2 // Start from half the empty space
|
? (width - dx) / 2 // Start from half the empty space
|
||||||
: 0 // Otherwise start from the beginning
|
: 0 // Otherwise start from the beginning
|
||||||
this.element.startPercentage = xInverted ? this.element.startPixels + fillRatio * 100 : this.element.startPixels
|
this.element.startPercentage = xInverted ? this.element.startPixels + fillRatio * 100 : this.element.startPixels
|
||||||
const c1
|
const c1 =
|
||||||
= this.element.startPercentage
|
this.element.startPercentage
|
||||||
+ (xInverted
|
+ (xInverted
|
||||||
? LinkTemplate.c1DecreasingValue(width)
|
? LinkTemplate.c1DecreasingValue(width)
|
||||||
: 10
|
: 10
|
||||||
)
|
)
|
||||||
* fillRatio
|
* fillRatio
|
||||||
let c2 = LinkTemplate.c2Clamped(xInverted ? -dx : dx) + this.element.startPercentage
|
let c2 = LinkTemplate.c2Clamped(dx) * Utility.sigmoidPositive(fillRatio + aspectRatio * 0.5, 1.5, 2) + this.element.startPercentage
|
||||||
c2 = Math.min(c2, LinkTemplate.c2DecreasingValue(width))
|
c2 = xInverted ? Math.min(c2, LinkTemplate.c2DecreasingValue(width)) : c2
|
||||||
this.element.svgPathD = Configuration.linkRightSVGPath(this.element.startPercentage, c1, c2)
|
this.element.svgPathD = Configuration.linkRightSVGPath(this.element.startPercentage, c1, c2)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,12 +167,11 @@ export default class LinkTemplate extends IFromToPositionedTemplate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const uniqueId = `ueb-id-${Math.floor(Math.random() * 1E12)}`
|
|
||||||
return html`
|
return html`
|
||||||
<svg version="1.2" baseProfile="tiny" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
|
<svg version="1.2" baseProfile="tiny" width="100%" height="100%" viewBox="0 0 100 100" preserveAspectRatio="none">
|
||||||
<g class="ueb-link-area">
|
<g class="ueb-link-area">
|
||||||
<path id="${uniqueId}" fill="none" vector-effect="non-scaling-stroke" d="${this.element.svgPathD}" />
|
<path id="${this.#uniqueId}" fill="none" vector-effect="non-scaling-stroke" d="${this.element.svgPathD}" />
|
||||||
<use href="#${uniqueId}" pointer-events="stroke" stroke-width="20" />
|
<use href="#${this.#uniqueId}" pointer-events="stroke" stroke-width="20" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
${this.element.linkMessageIcon || this.element.linkMessageText ? html`
|
${this.element.linkMessageIcon || this.element.linkMessageText ? html`
|
||||||
|
|||||||
Reference in New Issue
Block a user