@antv/f6
Version:
A Mobile Graph Visualization Framework in JavaScript
420 lines • 12.4 kB
JavaScript
import { __assign } from "tslib";
/*
* @Author: moyee
* @LastEditors: moyee
* @Description: 拖动 Combo
*/
import { each } from '@antv/util';
import Util from '../util';
import Global from '../global';
var calculationItemsBBox = Util.calculationItemsBBox;
/**
* 遍历拖动的 Combo 下的所有 Combo
* @param data 拖动的 Combo
* @param fn
*/
var traverseCombo = function traverseCombo(data, fn) {
if (fn(data) === false) {
return;
}
if (data) {
var combos = data.get('combos');
if (combos.length === 0) {
return false;
}
each(combos, function (child) {
traverseCombo(child, fn);
});
}
};
export default {
getDefaultCfg: function getDefaultCfg() {
return {
enableDelegate: false,
delegateStyle: {},
// 拖动节点过程中是否只改变 Combo 的大小,而不改变其结构
onlyChangeComboSize: false,
// 拖动过程中目标 combo 状态样式
activeState: '',
selectedState: 'selected'
};
},
getEvents: function getEvents() {
return {
'combo:dragstart': 'onDragStart',
'combo:drag': 'onDrag',
'combo:dragend': 'onDragEnd',
'combo:drop': 'onDrop',
'node:drop': 'onNodeDrop',
'combo:dragenter': 'onDragEnter',
'combo:dragleave': 'onDragLeave'
};
},
validationCombo: function validationCombo(evt) {
var item = evt.item;
if (!item || item.destroyed) {
return false;
}
if (!this.shouldUpdate(this, evt)) {
return false;
}
var type = item.getType();
if (type !== 'combo') {
return false;
}
return true;
},
onDragStart: function onDragStart(evt) {
var _this = this;
var graph = this.graph;
var item = evt.item;
if (!this.validationCombo(evt)) return;
this.targets = [];
// 获取所有选中的 Combo
var combos = graph.findAllByState('combo', this.selectedState);
var currentCombo = item.get('id');
var dragCombos = combos.filter(function (combo) {
var comboId = combo.get('id');
return currentCombo === comboId;
});
if (dragCombos.length === 0) {
this.targets.push(item);
} else {
this.targets = combos;
}
if (this.activeState) {
this.targets.map(function (combo) {
var model = combo.getModel();
if (model.parentId) {
var parentCombo = graph.findById(model.parentId);
if (parentCombo) {
graph.setItemState(parentCombo, _this.activeState, true);
}
}
});
}
this.point = {};
this.originPoint = {};
this.origin = {
x: evt.x,
y: evt.y
};
this.currentItemChildCombos = [];
traverseCombo(item, function (param) {
if (param.destroyed) {
return false;
}
var model = param.getModel();
_this.currentItemChildCombos.push(model.id);
return true;
});
},
onDrag: function onDrag(evt) {
var _this = this;
if (!this.origin) {
return;
}
if (!this.validationCombo(evt)) return;
if (this.enableDelegate) {
this.updateDelegate(evt);
} else {
if (this.activeState) {
var graph_1 = this.graph;
var item = evt.item;
var model_1 = item.getModel();
// 拖动过程中实时计算距离
var combos = graph_1.getCombos();
var sourceBBox = item.getBBox();
var centerX_1 = sourceBBox.centerX,
centerY_1 = sourceBBox.centerY,
width_1 = sourceBBox.width;
// 参与计算的 Combo,需要排除掉:
// 1、拖动 combo 自己
// 2、拖动 combo 的 parent
// 3、拖动 Combo 的 children
var calcCombos = combos.filter(function (combo) {
var cmodel = combo.getModel();
// 被拖动的是最外层的 Combo,无 parent,排除自身和子元素
if (!model_1.parentId) {
return cmodel.id !== model_1.id && !_this.currentItemChildCombos.includes(cmodel.id);
}
return cmodel.id !== model_1.id && !_this.currentItemChildCombos.includes(cmodel.id);
});
calcCombos.map(function (combo) {
var _a = combo.getBBox(),
cx = _a.centerX,
cy = _a.centerY,
w = _a.width;
// 拖动的 combo 和要进入的 combo 之间的距离
var disX = centerX_1 - cx;
var disY = centerY_1 - cy;
// 圆心距离
var distance = 2 * Math.sqrt(disX * disX + disY * disY);
if (width_1 + w - distance > 0.8 * width_1) {
graph_1.setItemState(combo, _this.activeState, true);
} else {
graph_1.setItemState(combo, _this.activeState, false);
}
});
}
each(this.targets, function (item) {
_this.updateCombo(item, evt);
});
}
},
updatePositions: function updatePositions(evt) {
var _this = this;
// 当启用 delegate 时,拖动结束时需要更新 combo
if (this.enableDelegate) {
each(this.targets, function (item) {
_this.updateCombo(item, evt);
});
}
},
onDrop: function onDrop(evt) {
var _this = this;
// 被放下的目标 combo
var item = evt.item;
if (!item || !this.targets || item.destroyed) {
return;
}
this.updatePositions(evt);
var graph = this.graph;
var targetModel = item.getModel();
this.targets.map(function (combo) {
var model = combo.getModel();
if (model.parentId !== targetModel.id) {
if (_this.activeState) {
graph.setItemState(item, _this.activeState, false);
}
// 将 Combo 放置到某个 Combo 上面时,只有当 onlyChangeComboSize 为 false 时候才更新 Combo 结构
if (!_this.onlyChangeComboSize) {
graph.updateComboTree(combo, targetModel.id);
} else {
graph.updateCombo(combo);
}
} else {
graph.updateCombo(item);
}
});
this.end(item, evt);
// 如果已经拖放下了,则不需要再通过距离判断了
this.endComparison = true;
},
onNodeDrop: function onNodeDrop(evt) {
var _this = this;
if (!this.targets || this.targets.length === 0) return;
this.updatePositions(evt);
var graph = this.graph;
var item = evt.item;
var comboId = item.getModel().comboId;
var droppedCombo;
// 如果被放置的的节点有 comboId,且这个 comboId 与正在被拖拽的 combo 的父 id 不相同,则更新父亲为 comboId
if (comboId) {
if (this.activeState) {
var combo = graph.findById(comboId);
graph.setItemState(combo, this.activeState, false);
}
this.targets.map(function (combo) {
if (!_this.onlyChangeComboSize) {
if (comboId !== combo.getID()) {
droppedCombo = graph.findById(comboId);
if (comboId !== combo.getModel().parentId) graph.updateComboTree(combo, comboId);
}
} else {
graph.updateCombo(combo);
}
});
} else {
// 如果被放置的节点没有 comboId,且正在被拖拽的 combo 有父 id,则更新父亲为 undefined
this.targets.map(function (combo) {
if (!_this.onlyChangeComboSize) {
var model = combo.getModel();
if (model.comboId) {
graph.updateComboTree(combo);
}
} else {
graph.updateCombo(combo);
}
});
}
// 如果已经拖放下了,则不需要再通过距离判断了
this.endComparison = true;
this.end(droppedCombo, evt);
},
onDragEnter: function onDragEnter(evt) {
if (!this.origin) {
return;
}
if (!this.validationCombo(evt)) return;
var item = evt.item;
var graph = this.graph;
if (this.activeState) {
graph.setItemState(item, this.activeState, true);
}
},
onDragLeave: function onDragLeave(evt) {
if (!this.origin) {
return;
}
if (!this.validationCombo(evt)) return;
var item = evt.item;
var graph = this.graph;
if (this.activeState) {
graph.setItemState(item, this.activeState, false);
}
},
onDragEnd: function onDragEnd(evt) {
if (!this.targets || this.targets.length === 0) return;
var item = evt.item;
this.updatePositions(evt);
var parentCombo = this.getParentCombo(item.getModel().parentId);
var graph = this.graph;
if (parentCombo && this.activeState) {
graph.setItemState(parentCombo, this.activeState, false);
}
this.end(undefined, evt);
},
end: function end(comboDropedOn, evt) {
var _this = this;
if (!this.origin) return;
var graph = this.graph;
// 删除delegate shape
if (this.delegateShape) {
var delegateGroup = graph.get('delegateGroup');
delegateGroup.clear();
this.delegateShape = null;
}
if (comboDropedOn && this.activeState) {
graph.setItemState(comboDropedOn, this.activeState, false);
}
// 若没有被放置的 combo,则是被放置在画布上
if (!comboDropedOn) {
this.targets.map(function (combo) {
// 将 Combo 放置到某个 Combo 上面时,只有当 onlyChangeComboSize 为 false 时候才更新 Combo 结构
if (!_this.onlyChangeComboSize) {
graph.updateComboTree(combo);
} else {
graph.updateCombo(combo);
}
});
}
this.point = [];
this.origin = null;
this.originPoint = null;
this.targets.length = 0;
},
/**
* 遍历 comboTree,分别更新 node 和 combo
* @param data
* @param fn
*/
traverse: function traverse(data, fn) {
var _this = this;
if (fn(data) === false) {
return;
}
if (data) {
var combos = data.get('combos');
each(combos, function (child) {
_this.traverse(child, fn);
});
var nodes = data.get('nodes');
each(nodes, function (child) {
_this.traverse(child, fn);
});
}
},
updateCombo: function updateCombo(item, evt) {
var _this = this;
this.traverse(item, function (param) {
if (param.destroyed) {
return false;
}
_this.updateSignleItem(param, evt);
return true;
});
},
/**
*
* @param item 当前正在拖动的元素
* @param evt
*/
updateSignleItem: function updateSignleItem(item, evt) {
var origin = this.origin;
var graph = this.graph;
var model = item.getModel();
var itemId = item.get('id');
if (!this.point[itemId]) {
this.point[itemId] = {
x: model.x,
y: model.y
};
}
var x = evt.x - origin.x + this.point[itemId].x;
var y = evt.y - origin.y + this.point[itemId].y;
graph.updateItem(item, {
x: x,
y: y
});
},
/**
* 根据 ID 获取父 Combo
* @param parentId 父 Combo ID
*/
getParentCombo: function getParentCombo(parentId) {
var graph = this.graph;
if (!parentId) {
return undefined;
}
var parentCombo = graph.findById(parentId);
if (!parentCombo) {
return undefined;
}
return parentCombo;
},
updateDelegate: function updateDelegate(evt) {
var graph = this.graph;
// 当没有 delegate shape 时创建
if (!this.delegateShape) {
var delegateGroup = graph.get('delegateGroup');
var bbox = null;
if (this.targets.length > 1) {
bbox = calculationItemsBBox(this.targets);
} else {
bbox = this.targets[0].getBBox();
}
var x = bbox.x,
y = bbox.y,
width = bbox.width,
height = bbox.height,
minX = bbox.minX,
minY = bbox.minY;
this.originPoint = {
x: x,
y: y,
width: width,
height: height,
minX: minX,
minY: minY
};
var attrs = __assign(__assign({}, Global.delegateStyle), this.delegateStyle);
this.delegateShape = delegateGroup.addShape('rect', {
attrs: __assign({
width: bbox.width,
height: bbox.height,
x: bbox.x,
y: bbox.y
}, attrs),
name: 'combo-delegate-shape'
});
} else {
var clientX = evt.x - this.origin.x + this.originPoint.minX;
var clientY = evt.y - this.origin.y + this.originPoint.minY;
this.delegateShape.attr({
x: clientX,
y: clientY
});
}
}
};