@benson.liao/react-design-editor
Version:
Design Editor Tools with React.js + ant.design + fabric.js
275 lines (274 loc) • 10.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const fabric_1 = require("fabric");
class NodeHandler {
constructor(handler) {
/**
* Get the node path by target object
* @param {NodeObject} target
* @param {NodeObject[]} [nodes=[]]
* @param {string} [direction='init']
*/
this.getNodePath = (target, nodes = [], direction = 'init') => {
if (target) {
if (direction === 'to' || direction === 'init') {
if (target.toPort) {
target.toPort.links.forEach(link => {
if (link.fromNode) {
nodes.push(link.fromNode);
this.getNodePath(link.fromNode, nodes, 'to');
}
});
}
if (direction === 'init') {
nodes.push(target);
}
}
if (direction === 'from' || direction === 'init') {
target.fromPort.forEach(port => {
port.links.forEach(link => {
if (link.toNode) {
nodes.push(link.toNode);
this.getNodePath(link.toNode, nodes, 'from');
}
});
});
}
}
};
/**
* Select the node path
* @param {string[]} [path]
*/
this.selectByPath = (path) => {
if (!path || !path.length) {
return;
}
const targetObjects = this.handler.objects.filter(object => path.some(id => id === object.id));
const nonTargetObjects = this.handler.objects.filter(object => path.some(id => id !== object.id));
nonTargetObjects.forEach((object) => {
if (object.superType === 'link') {
const { fromNode, toNode } = object;
if (fromNode && toNode) {
const fromIndex = targetObjects.findIndex(obj => obj.id === fromNode.id);
const toIndex = targetObjects.findIndex(obj => obj.id === toNode.id);
if (fromIndex >= 0 && targetObjects[fromIndex] && toIndex >= 0 && targetObjects[toIndex]) {
object.set({
opacity: 1,
});
object.setShadow({
color: object.stroke,
});
this.highlightingNode(object, 300);
this.handler.canvas.requestRenderAll();
return;
}
}
}
object.set({
opacity: 0.2,
});
if (object.superType === 'node') {
if (object.toPort) {
object.toPort.set({
opacity: 0.2,
});
}
object.fromPort.forEach((port) => {
port.set({
opacity: 0.2,
});
});
}
if (!object.animating) {
object.setShadow({
blur: 0,
});
}
});
targetObjects.forEach((object) => {
object.set({
opacity: 1,
});
object.setShadow({
color: object.stroke,
});
this.highlightingNode(object, 300);
if (object.toPort) {
object.toPort.set({
opacity: 1,
});
}
if (object.fromPort) {
object.fromPort.forEach((port) => {
port.set({
opacity: 1,
});
});
}
});
this.handler.canvas.requestRenderAll();
};
/**
* Select node by id
* @param {string} id
*/
this.selectById = (id) => {
this.handler.objects.forEach((object) => {
if (id === object.id) {
object.setShadow({
color: object.stroke,
blur: 50,
});
return;
}
else if (id === object.nodeId) {
return;
}
object.setShadow({
blur: 0,
});
});
this.handler.canvas.requestRenderAll();
};
/**
* Deselect nodes
*/
this.deselect = () => {
this.handler.objects.forEach((object) => {
object.set({
opacity: 1,
});
if (object.superType === 'node') {
const node = object;
if (node.toPort) {
node.toPort.set({
opacity: 1,
});
}
node.fromPort.forEach(port => {
port.set({
opacity: 1,
});
});
}
if (!object.animating) {
const node = object;
node.setShadow({
blur: 0,
});
}
});
this.handler.canvas.renderAll();
};
/**
* Highlight node path
* @param {string[]} [path]
*/
this.highlightingByPath = (path) => {
if (!path || !path.length) {
return;
}
const targetObjects = this.handler.objects.filter((obj) => path.some(id => id === obj.id));
const nonTargetObjects = this.handler.objects.filter((obj) => path.some(id => id !== obj.id));
const lastObject = targetObjects.filter((obj) => obj.id === path[path.length - 1])[0];
targetObjects.forEach((object) => {
if (lastObject) {
object.setShadow({
color: lastObject.stroke,
});
}
else {
object.setShadow({
color: object.stroke,
});
}
this.highlightingNode(object);
this.handler.canvas.requestRenderAll();
});
nonTargetObjects.forEach((object) => {
if (object.superType === 'link') {
const { fromNode, toNode } = object;
if (fromNode && toNode) {
const fromIndex = targetObjects.findIndex((obj) => obj.id === fromNode.id);
const toIndex = targetObjects.findIndex((obj) => obj.id === toNode.id);
if (fromIndex >= 0 && targetObjects[fromIndex] && toIndex >= 0 && targetObjects[toIndex]) {
if (lastObject) {
object.setShadow({
color: lastObject.stroke,
});
}
else {
object.setShadow({
color: object.stroke,
});
}
this.highlightingNode(object);
this.highlightingLink(object, lastObject);
return;
}
}
}
});
this.handler.canvas.requestRenderAll();
};
/**
* Highlight link
* @param {FabricObject} object
* @param {FabricObject} targetObject
* @param {number} [duration=500]
*/
this.highlightingLink = (object, targetObject, duration = 500) => {
object.animation = {
duration,
type: 'flash',
stroke: targetObject ? targetObject.stroke : object.stroke,
loop: 1,
delay: 0,
};
this.handler.animationHandler.play(object.id, false);
};
/**
* Highlight node
*
* @param {*} object
* @param {number} [duration=500]
* @param {number} [minBlur=0]
* @param {number} [maxBlur=50]
*/
this.highlightingNode = (object, duration = 500, minBlur = 0, maxBlur = 50) => {
const onComplete = () => {
if (object.shadow.blur === maxBlur) {
object.animating = true;
object.animate('shadow.blur', minBlur, {
easing: fabric_1.fabric.util.ease.easeInOutQuad,
onChange: (value) => {
object.shadow.blur = value;
this.handler.canvas.requestRenderAll();
},
onComplete: () => {
object.animating = false;
if (object.superType === 'link') {
object.set({
stroke: object.originStroke,
});
}
},
});
}
};
object.animating = true;
object.animate('shadow.blur', maxBlur, {
easing: fabric_1.fabric.util.ease.easeInOutQuad,
duration,
onChange: (value) => {
object.shadow.blur = value;
this.handler.canvas.requestRenderAll();
},
onComplete,
});
};
this.handler = handler;
}
}
exports.default = NodeHandler;