UNPKG

@antv/x6

Version:

JavaScript diagramming library that uses SVG and HTML for rendering.

410 lines 16.9 kB
"use strict"; 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) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.PathDrawer = void 0; var util_1 = require("../../util"); var geometry_1 = require("../../geometry"); var view_1 = require("../../view"); // need: <meta http-equiv="x-ua-compatible" content="IE=Edge" /> var PathDrawer = /** @class */ (function (_super) { __extends(PathDrawer, _super); function PathDrawer(options) { var _this = _super.call(this) || this; _this.MOVEMENT_DETECTION_THRESHOLD = 150; _this.options = util_1.ObjectExt.merge({}, PathDrawer.defaultOptions, options); _this.action = 'awaiting-input'; _this.render(); _this.startListening(); return _this; } Object.defineProperty(PathDrawer.prototype, "vel", { get: function () { return util_1.Vector.create(this.container); }, enumerable: false, configurable: true }); PathDrawer.prototype.render = function () { var options = this.options; this.container = util_1.Dom.createSvgElement('g'); util_1.Dom.addClass(this.container, this.prefixClassName('path-drawer')); this.pathTemplate = util_1.Dom.createSvgElement('path'); util_1.Dom.attr(this.pathTemplate, options.pathAttributes); this.startPointElement = util_1.Vector.create(options.startPointMarkup).addClass('start-point').node; this.controlElement = util_1.Dom.createSvgElement('path'); util_1.Dom.addClass(this.controlElement, 'control-path'); util_1.Vector.create('rect', { x: 0, y: 0, width: '100%', height: '100%', fill: 'transparent', stroke: 'none', }).appendTo(this.container); this.options.target.appendChild(this.container); return this; }; PathDrawer.prototype.onRemove = function () { this.remove(this.pathElement); this.clear(); this.stopListening(); }; PathDrawer.prototype.startListening = function () { this.delegateEvents({ mousedown: 'onMouseDown', touchstart: 'onMouseDown', dblclick: 'onDoubleClick', contextmenu: 'onContextMenu', 'mousedown .start-point': 'onStartPointMouseDown', 'touchstart .start-point': 'onStartPointMouseDown', }); }; PathDrawer.prototype.stopListening = function () { this.undelegateEvents(); }; PathDrawer.prototype.clear = function () { var path = this.pathElement; if (path && path.pathSegList.numberOfItems <= 1) { this.remove(path); } this.startPointElement.remove(); this.controlElement.remove(); this.undelegateDocumentEvents(); this.action = 'awaiting-input'; this.emit('clear'); }; PathDrawer.prototype.createPath = function (x, y) { this.pathElement = this.pathTemplate.cloneNode(true); this.addMoveSegment(x, y); util_1.Dom.translate(this.startPointElement, x, y, { absolute: true, }); this.vel.before(this.pathElement); this.vel.append(this.startPointElement); this.emit('path:create', { path: this.pathElement }); }; PathDrawer.prototype.closePath = function () { var path = this.pathElement; var first = this.getPathSeg(path, 0); var last = this.getPathSeg(path, -1); if (last.pathSegType === SVGPathSeg.PATHSEG_LINETO_ABS) { path.pathSegList.replaceItem(path.createSVGPathSegClosePath(), path.pathSegList.numberOfItems - 1); } else { last.x = first.x; last.y = first.y; path.pathSegList.appendItem(path.createSVGPathSegClosePath()); } this.finishPath('path:close'); }; PathDrawer.prototype.finishPath = function (name) { var path = this.pathElement; if (path && 0 < this.numberOfVisibleSegments()) { this.emit('path:finish', { path: path }); this.trigger(name, { path: path }); } else { this.emit('path:abort', { path: path }); } this.clear(); }; PathDrawer.prototype.numberOfVisibleSegments = function () { var path = this.pathElement; var remaining = path.pathSegList.numberOfItems; remaining = remaining - 1; var last = this.getPathSeg(path, -1); if (last.pathSegType === SVGPathSeg.PATHSEG_CLOSEPATH) { remaining = remaining - 1; } return remaining; }; PathDrawer.prototype.addMoveSegment = function (x, y) { var path = this.pathElement; var seg = path.createSVGPathSegMovetoAbs(x, y); path.pathSegList.appendItem(seg); this.emit('path:segment:add', { path: path }); this.emit('path:move-segment:add', { path: path }); }; PathDrawer.prototype.addLineSegment = function (x, y) { var path = this.pathElement; var seg = path.createSVGPathSegLinetoAbs(x, y); path.pathSegList.appendItem(seg); this.emit('path:segment:add', { path: path }); this.emit('path:line-segment:add', { path: path }); }; PathDrawer.prototype.addCurveSegment = function (x, y, x1, y1, x2, y2) { var path = this.pathElement; var seg = path.createSVGPathSegCurvetoCubicAbs(x, y, x1, y1, x2 || x, y2 || y); path.pathSegList.appendItem(seg); this.emit('path:segment:add', { path: path }); this.emit('path:curve-segment:add', { path: path }); }; PathDrawer.prototype.adjustLastSegment = function (x, y, x1, y1, x2, y2) { var path = this.pathElement; var snapRadius = this.options.snapRadius; if (snapRadius && x != null && y != null) { var snaped = this.snapLastSegmentCoordinates(x, y, snapRadius); x = snaped.x; // tslint:disable-line y = snaped.y; // tslint:disable-line } var seg = this.getPathSeg(path, -1); if (x != null) { seg.x = x; } if (y != null) { seg.y = y; } if (x1 != null) { seg.x1 = x1; } if (y1 != null) { seg.y1 = y1; } if (x2 != null) { seg.x2 = x2; } if (y2 != null) { seg.y2 = y2; } this.emit('path:edit', { path: path }); this.emit('path:last-segment:adjust', { path: path }); }; PathDrawer.prototype.snapLastSegmentCoordinates = function (x, y, snapRadius) { var path = this.pathElement; var xSnaped = false; var ySnaped = false; var targetX = x; var targetY = y; for (var i = path.pathSegList.numberOfItems - 2; 0 <= i && (!xSnaped || !ySnaped); i -= 1) { var seg = this.getPathSeg(path, i); if (!xSnaped && Math.abs(seg.x - x) < snapRadius) { targetX = seg.x; xSnaped = true; } if (!ySnaped && Math.abs(seg.y - y) < snapRadius) { targetY = seg.y; ySnaped = true; } } return new geometry_1.Point(targetX, targetY); }; PathDrawer.prototype.removeLastSegment = function () { var path = this.pathElement; path.pathSegList.removeItem(path.pathSegList.numberOfItems - 1); this.emit('path:edit', { path: path }); this.emit('path:last-segment:remove', { path: path }); }; PathDrawer.prototype.findControlPoint = function (x, y) { var path = this.pathElement; var seg = this.getPathSeg(path, -1); return new geometry_1.Point(x, y).reflection(seg); }; PathDrawer.prototype.replaceLastSegmentWithCurve = function () { var path = this.pathElement; var last = this.getPathSeg(path, -1); var prev = this.getPathSeg(path, -2); var seg = path.createSVGPathSegCurvetoCubicAbs(last.x, last.y, prev.x, prev.y, last.x, last.y); path.pathSegList.replaceItem(seg, path.pathSegList.numberOfItems - 1); this.emit('path:edit', { path: path }); this.emit('path:last-segment:replace-with-curve', { path: path }); }; PathDrawer.prototype.adjustControlPath = function (x1, y1, x2, y2) { var controlPathElement = this.controlElement; controlPathElement.pathSegList.initialize(controlPathElement.createSVGPathSegMovetoAbs(x1, y1)); controlPathElement.pathSegList.appendItem(controlPathElement.createSVGPathSegLinetoAbs(x2, y2)); this.vel.append(controlPathElement); var path = this.pathElement; this.emit('path:interact', { path: path }); this.emit('path:control:adjust', { path: path }); }; PathDrawer.prototype.removeControlPath = function () { var path = this.pathElement; var svgControl = this.controlElement; svgControl.pathSegList.clear(); this.vel.append(svgControl); this.emit('path:interact', { path: path }); this.emit('path:control:remove', { path: path }); }; PathDrawer.prototype.getPathSeg = function (path, index) { var i = index < 0 ? path.pathSegList.numberOfItems + index : index; return path.pathSegList.getItem(i); }; PathDrawer.prototype.onMouseDown = function (evt) { var e = this.normalizeEvent(evt); e.stopPropagation(); if (this.isLeftMouseDown(e) && this.isSamePositionEvent(e) && this.container.parentNode) { var local = this.vel.toLocalPoint(e.clientX, e.clientY); switch (this.action) { case 'awaiting-input': this.createPath(local.x, local.y); this.action = 'path-created'; this.delegateDocumentEvents(PathDrawer.documentEvents); break; case 'adjusting-line-end': this.action = 'awaiting-line-end'; break; case 'adjusting-curve-end': this.action = 'awaiting-curve-control-2'; } this.timeStamp = e.timeStamp; } }; PathDrawer.prototype.onMouseMove = function (evt) { var e = this.normalizeEvent(evt); e.stopPropagation(); if ('awaiting-input' !== this.action) { var local = this.vel.toLocalPoint(e.clientX, e.clientY); var timeStamp = this.timeStamp; if (timeStamp) { if (e.timeStamp - timeStamp < this.MOVEMENT_DETECTION_THRESHOLD) { switch (this.action) { case 'path-created': { var translate = util_1.Dom.translate(this.startPointElement); this.adjustControlPath(translate.tx, translate.ty, local.x, local.y); break; } case 'awaiting-line-end': case 'adjusting-curve-control-1': { this.adjustLastSegment(local.x, local.y); break; } case 'awaiting-curve-control-2': { this.adjustLastSegment(local.x, local.y, null, null, local.x, local.y); } } } else { switch (this.action) { case 'path-created': this.action = 'adjusting-curve-control-1'; break; case 'awaiting-line-end': this.replaceLastSegmentWithCurve(); this.action = 'adjusting-curve-control-2'; break; case 'awaiting-curve-control-2': this.action = 'adjusting-curve-control-2'; break; case 'adjusting-curve-control-1': { var translate = util_1.Dom.translate(this.startPointElement); this.adjustControlPath(translate.tx, translate.ty, local.x, local.y); break; } case 'adjusting-curve-control-2': { var controlPoint = this.findControlPoint(local.x, local.y); this.adjustLastSegment(null, null, null, null, controlPoint.x, controlPoint.y); this.adjustControlPath(controlPoint.x, controlPoint.y, local.x, local.y); } } } } else { switch (this.action) { case 'adjusting-line-end': this.adjustLastSegment(local.x, local.y); break; case 'adjusting-curve-end': this.adjustLastSegment(local.x, local.y, null, null, local.x, local.y); } } } }; PathDrawer.prototype.onPointerUp = function (evt) { this.timeStamp = null; var e = this.normalizeEvent(evt); e.stopPropagation(); if (this.isLeftMouseDown(e) && this.isSamePositionEvent(e)) { var local = this.vel.toLocalPoint(e.clientX, e.clientY); switch (this.action) { case 'path-created': case 'awaiting-line-end': this.addLineSegment(local.x, local.y); this.action = 'adjusting-line-end'; break; case 'awaiting-curve-control-2': this.removeControlPath(); this.addLineSegment(local.x, local.y); this.action = 'adjusting-line-end'; break; case 'adjusting-curve-control-1': case 'adjusting-curve-control-2': this.addCurveSegment(local.x, local.y, local.x, local.y); this.action = 'adjusting-curve-end'; } } }; PathDrawer.prototype.onStartPointMouseDown = function (evt) { var e = this.normalizeEvent(evt); e.stopPropagation(); if (this.isLeftMouseDown(e) && this.isSamePositionEvent(e)) { this.closePath(); } }; PathDrawer.prototype.onDoubleClick = function (evt) { var e = this.normalizeEvent(evt); e.preventDefault(); e.stopPropagation(); if (this.isLeftMouseDown(e)) { if (this.pathElement && 0 < this.numberOfVisibleSegments()) { this.removeLastSegment(); this.finishPath('path:stop'); } } }; PathDrawer.prototype.onContextMenu = function (evt) { var e = this.normalizeEvent(evt); e.preventDefault(); e.stopPropagation(); if (this.isSamePositionEvent(e)) { if (this.pathElement && 0 < this.numberOfVisibleSegments()) { this.removeLastSegment(); this.finishPath('path:stop'); } } }; PathDrawer.prototype.isLeftMouseDown = function (e) { return (e.which || 0) <= 1; }; PathDrawer.prototype.isSamePositionEvent = function (e) { var originalEvent = e.originalEvent; return originalEvent == null || originalEvent.detail <= 1; }; return PathDrawer; }(view_1.View)); exports.PathDrawer = PathDrawer; (function (PathDrawer) { PathDrawer.defaultOptions = { pathAttributes: { class: null, fill: '#ffffff', stroke: '#000000', 'stroke-width': 1, 'pointer-events': 'none', }, startPointMarkup: '<circle r="5"/>', snapRadius: 0, }; PathDrawer.documentEvents = { mousemove: 'onMouseMove', touchmove: 'onMouseMove', mouseup: 'onMouseUp', touchend: 'onMouseUp', touchcancel: 'onMouseUp', }; })(PathDrawer = exports.PathDrawer || (exports.PathDrawer = {})); exports.PathDrawer = PathDrawer; //# sourceMappingURL=drawer.js.map