@logicflow/core
Version:
LogicFlow, help you quickly create flowcharts
257 lines (256 loc) • 13.5 kB
JavaScript
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
if (typeof b !== "function" && b !== null)
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { jsx as _jsx } from "preact/jsx-runtime";
import { Component } from 'preact/compat';
import { observer } from '../..';
import { EventType } from '../../constant';
import { StepDrag } from '../../util';
var CanvasOverlay = /** @class */ (function (_super) {
__extends(CanvasOverlay, _super);
function CanvasOverlay(props) {
var _this = _super.call(this) || this;
_this.stepScrollX = 0;
_this.stepScrollY = 0;
_this.pointers = new Map();
// get InjectedProps() {
// return this.props as InjectedProps;
// }
_this.onDragging = function (_a) {
var deltaX = _a.deltaX, deltaY = _a.deltaY;
if (_this.longPressTimer) {
clearTimeout(_this.longPressTimer);
_this.longPressTimer = undefined;
}
_this.setState({
isDragging: true,
});
var _b = _this.props.graphModel, transformModel = _b.transformModel, editConfigModel = _b.editConfigModel;
if (editConfigModel.stopMoveGraph === true) {
return;
}
transformModel.translate(deltaX, deltaY);
};
_this.onDragEnd = function () {
_this.setState({
isDragging: false,
});
};
_this.zoomHandler = function (ev) {
var _a = _this.props, _b = _a.graphModel, editConfigModel = _b.editConfigModel, transformModel = _b.transformModel, gridSize = _b.gridSize, graphModel = _a.graphModel;
var eX = ev.deltaX, eY = ev.deltaY;
var stopScrollGraph = editConfigModel.stopScrollGraph, stopZoomGraph = editConfigModel.stopZoomGraph;
// 如果没有禁止滚动移动画布, 并且当前触发的时候ctrl键、cmd键没有按住, 那么移动画布
if (!stopScrollGraph && !ev.ctrlKey && !ev.metaKey) {
ev.preventDefault();
_this.stepScrollX += eX;
_this.stepScrollY += eY;
if (Math.abs(_this.stepScrollX) >= gridSize) {
var remainderX = _this.stepScrollX % gridSize;
var moveDistance = _this.stepScrollX - remainderX;
transformModel.translate(-moveDistance * transformModel.SCALE_X, 0);
_this.stepScrollX = remainderX;
}
if (Math.abs(_this.stepScrollY) >= gridSize) {
var remainderY = _this.stepScrollY % gridSize;
var moveDistanceY = _this.stepScrollY - remainderY;
transformModel.translate(0, -moveDistanceY * transformModel.SCALE_Y);
_this.stepScrollY = remainderY;
}
return;
}
// 如果没有禁止缩放画布,那么进行缩放. 在禁止缩放画布后,按住 ctrl、cmd 键也不能缩放了。
if (!stopZoomGraph) {
ev.preventDefault();
var position = graphModel.getPointByClient({
x: ev.clientX,
y: ev.clientY,
});
var _c = position.canvasOverlayPosition, x = _c.x, y = _c.y;
transformModel.zoom(ev.deltaY < 0, [x, y]);
}
};
_this.clickHandler = function (ev) {
// 点击空白处取消节点选中状态, 不包括冒泡过来的事件。
var target = ev.target;
if (target.getAttribute('name') === 'canvas-overlay') {
var graphModel = _this.props.graphModel;
var selectElements = graphModel.selectElements;
if (selectElements.size > 0) {
graphModel.clearSelectElements();
}
// 如果是拖拽状态,不触发点击事件
if (_this.state.isDragging)
return;
graphModel.eventCenter.emit(EventType.BLANK_CLICK, { e: ev });
}
};
_this.handleContextMenu = function (ev) {
var target = ev.target;
if (target.getAttribute('name') === 'canvas-overlay') {
ev.preventDefault();
var graphModel = _this.props.graphModel;
var position = graphModel.getPointByClient({
x: ev.clientX,
y: ev.clientY,
});
// graphModel.setElementState(ElementState.SHOW_MENU, position.domOverlayPosition);
graphModel.eventCenter.emit(EventType.BLANK_CONTEXTMENU, {
e: ev,
position: position,
});
}
};
// 鼠标、触摸板 按下
_this.pointerDownHandler = function (ev) {
var _a = _this.props.graphModel, eventCenter = _a.eventCenter, editConfigModel = _a.editConfigModel, SCALE_X = _a.transformModel.SCALE_X, gridSize = _a.gridSize;
_this.pointers.set(ev.pointerId, { x: ev.clientX, y: ev.clientY });
if (_this.longPressTimer) {
clearTimeout(_this.longPressTimer);
}
if (ev.pointerType === 'touch') {
_this.longPressTimer = window.setTimeout(function () {
_this.handleContextMenu(ev);
}, 500);
}
// 检测双指触摸,初始化捏合缩放
if (_this.pointers.size === 2) {
var _b = _this.props.graphModel, transformModel = _b.transformModel, editConfigModel_1 = _b.editConfigModel;
// 记录两指当前位置用于计算初始距离
var pts = Array.from(_this.pointers.values());
var dx = pts[0].x - pts[1].x;
var dy = pts[0].y - pts[1].y;
var cx = (pts[0].x + pts[1].x) / 2;
var cy = (pts[0].y + pts[1].y) / 2;
// 记录捏合起始距离与当前缩放,后续按比例计算缩放
_this.pinchStartDistance = Math.hypot(dx, dy);
_this.pinchStartScale = transformModel.SCALE_X;
// 双指操作下取消画布拖拽,避免与捏合缩放冲突
_this.stepDrag.cancelDrag();
_this.pinchLastCenterX = cx;
_this.pinchLastCenterY = cy;
editConfigModel_1.updateEditConfig({ isPinching: true });
return;
}
var adjustEdge = editConfigModel.adjustEdge, adjustNodePosition = editConfigModel.adjustNodePosition, stopMoveGraph = editConfigModel.stopMoveGraph;
var target = ev.target;
var isFrozenElement = !adjustEdge && !adjustNodePosition;
if (target.getAttribute('name') === 'canvas-overlay' || isFrozenElement) {
if (stopMoveGraph !== true) {
_this.stepDrag.setStep(gridSize * SCALE_X);
_this.stepDrag.handleMouseDown(ev);
}
else {
eventCenter.emit(EventType.BLANK_MOUSEDOWN, { e: ev });
}
}
};
_this.pointerMoveHandler = function (ev) {
var _a;
// 记录当前指针位置(按 pointerId)
_this.pointers.set(ev.pointerId, { x: ev.clientX, y: ev.clientY });
// 当已记录初始捏合距离且存在两指时,执行捏合缩放
if (_this.pinchStartDistance && _this.pointers.size >= 2) {
var _b = _this.props, graphModel = _b.graphModel, _c = _b.graphModel, editConfigModel = _c.editConfigModel, transformModel = _c.transformModel;
if (editConfigModel.stopZoomGraph)
return;
// 取消触摸长按计时,避免捏合过程中误触发上下文菜单
if (_this.longPressTimer) {
clearTimeout(_this.longPressTimer);
}
// 计算两指间当前距离
var pts = Array.from(_this.pointers.values());
var dx = pts[0].x - pts[1].x;
var dy = pts[0].y - pts[1].y;
var dist = Math.hypot(dx, dy);
// 以初始缩放为基准,根据距离比例得到新的缩放比例
var scale = ((_a = _this.pinchStartScale) !== null && _a !== void 0 ? _a : transformModel.SCALE_X) *
(dist / _this.pinchStartDistance);
// 取两指中心作为缩放原点,并转换为画布坐标系
var cx = (pts[0].x + pts[1].x) / 2;
var cy = (pts[0].y + pts[1].y) / 2;
var pos = graphModel.getPointByClient({ x: cx, y: cy });
var _d = pos.canvasOverlayPosition, x = _d.x, y = _d.y;
transformModel.zoom(scale, [x, y]);
// 双指中心位移驱动画布平移,配合缩放实现捏合移动;
if (!editConfigModel.stopMoveGraph || editConfigModel.isPinching) {
var deltaX = _this.pinchLastCenterX === undefined ? 0 : cx - _this.pinchLastCenterX;
var deltaY = _this.pinchLastCenterY === undefined ? 0 : cy - _this.pinchLastCenterY;
transformModel.translate(deltaX, deltaY);
_this.pinchLastCenterX = cx;
_this.pinchLastCenterY = cy;
}
ev.preventDefault();
}
};
_this.pointerUpHandler = function (ev) {
_this.pointers.delete(ev.pointerId);
if (_this.longPressTimer) {
clearTimeout(_this.longPressTimer);
_this.longPressTimer = undefined;
}
// 双指松开或仅剩一指:结束捏合手势并清理临时状态
if (_this.pointers.size < 2) {
// 清空捏合距离与缩放起始值
_this.pinchStartDistance = undefined;
_this.pinchStartScale = undefined;
// 清空上一帧的双指中心
_this.pinchLastCenterX = undefined;
_this.pinchLastCenterY = undefined;
var editConfigModel = _this.props.graphModel.editConfigModel;
// 标记退出捏合,框选等交互可恢复
editConfigModel.updateEditConfig({ isPinching: false });
// 为了处理画布移动的时候,编辑和菜单仍然存在的问题。
_this.clickHandler(ev);
}
};
var _a = props.graphModel, gridSize = _a.gridSize, eventCenter = _a.eventCenter;
_this.stepDrag = new StepDrag({
onDragging: _this.onDragging,
onDragEnd: _this.onDragEnd,
step: gridSize,
eventType: 'BLANK',
isStopPropagation: false,
eventCenter: eventCenter,
model: undefined,
});
// 当 ctrl、cmd 键被按住的时候,可以放大缩小。
_this.state = {
isDragging: false,
};
return _this;
}
CanvasOverlay.prototype.render = function () {
var transformModel = this.props.graphModel.transformModel;
var transform = transformModel.getTransformStyle().transform;
var children = this.props.children;
var isDragging = this.state.isDragging;
return (_jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "100%", height: "100%", name: "canvas-overlay", onWheel: this.zoomHandler, onPointerDown: this.pointerDownHandler, onPointerMove: this.pointerMoveHandler, onPointerUp: this.pointerUpHandler, onPointerCancel: this.pointerUpHandler, onContextMenu: this.handleContextMenu, style: { touchAction: 'none', WebkitUserSelect: 'none' }, className: isDragging
? 'lf-canvas-overlay lf-dragging'
: 'lf-canvas-overlay lf-drag-able', children: _jsx("g", { transform: transform, children: children }) }));
};
CanvasOverlay = __decorate([
observer
], CanvasOverlay);
return CanvasOverlay;
}(Component));
export { CanvasOverlay };
export default CanvasOverlay;