| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204 |
- import {
- toPoint
- } from '../../util/Event';
- import {
- getMidPoint,
- pointsAligned
- } from '../../util/Geometry';
- import {
- append as svgAppend,
- attr as svgAttr,
- classes as svgClasses,
- create as svgCreate
- } from 'tiny-svg';
- import {
- rotate,
- translate
- } from '../../util/SvgTransformUtil';
- import {
- getApproxIntersection
- } from '../../util/LineIntersection';
- import { getDistancePointLine, perpendicularFoot } from './GeometricUtil';
- export var BENDPOINT_CLS = 'djs-bendpoint';
- export var SEGMENT_DRAGGER_CLS = 'djs-segment-dragger';
- export function toCanvasCoordinates(canvas, event) {
- var position = toPoint(event),
- clientRect = canvas._container.getBoundingClientRect(),
- offset;
- // canvas relative position
- offset = {
- x: clientRect.left,
- y: clientRect.top
- };
- // update actual event payload with canvas relative measures
- var viewbox = canvas.viewbox();
- return {
- x: viewbox.x + (position.x - offset.x) / viewbox.scale,
- y: viewbox.y + (position.y - offset.y) / viewbox.scale
- };
- }
- export function getConnectionIntersection(canvas, waypoints, event) {
- var localPosition = toCanvasCoordinates(canvas, event),
- intersection = getApproxIntersection(waypoints, localPosition);
- return intersection;
- }
- export function addBendpoint(parentGfx, cls) {
- var groupGfx = svgCreate('g');
- svgClasses(groupGfx).add(BENDPOINT_CLS);
- svgAppend(parentGfx, groupGfx);
- var visual = svgCreate('circle');
- svgAttr(visual, {
- cx: 0,
- cy: 0,
- r: 4
- });
- svgClasses(visual).add('djs-visual');
- svgAppend(groupGfx, visual);
- var hit = svgCreate('circle');
- svgAttr(hit, {
- cx: 0,
- cy: 0,
- r: 10
- });
- svgClasses(hit).add('djs-hit');
- svgAppend(groupGfx, hit);
- if (cls) {
- svgClasses(groupGfx).add(cls);
- }
- return groupGfx;
- }
- function createParallelDragger(parentGfx, segmentStart, segmentEnd, alignment) {
- var draggerGfx = svgCreate('g');
- svgAppend(parentGfx, draggerGfx);
- var width = 18,
- height = 6,
- padding = 11,
- hitWidth = calculateHitWidth(segmentStart, segmentEnd, alignment),
- hitHeight = height + padding;
- var visual = svgCreate('rect');
- svgAttr(visual, {
- x: -width / 2,
- y: -height / 2,
- width: width,
- height: height
- });
- svgClasses(visual).add('djs-visual');
- svgAppend(draggerGfx, visual);
- var hit = svgCreate('rect');
- svgAttr(hit, {
- x: -hitWidth / 2,
- y: -hitHeight / 2,
- width: hitWidth,
- height: hitHeight
- });
- svgClasses(hit).add('djs-hit');
- svgAppend(draggerGfx, hit);
- rotate(draggerGfx, alignment === 'v' ? 90 : 0, 0, 0);
- return draggerGfx;
- }
- export function addSegmentDragger(parentGfx, segmentStart, segmentEnd) {
- var groupGfx = svgCreate('g'),
- mid = getMidPoint(segmentStart, segmentEnd),
- alignment = pointsAligned(segmentStart, segmentEnd);
- svgAppend(parentGfx, groupGfx);
- createParallelDragger(groupGfx, segmentStart, segmentEnd, alignment);
- svgClasses(groupGfx).add(SEGMENT_DRAGGER_CLS);
- svgClasses(groupGfx).add(alignment === 'h' ? 'horizontal' : 'vertical');
- translate(groupGfx, mid.x, mid.y);
- return groupGfx;
- }
- /**
- * Calculates region for segment move which is 2/3 of the full segment length
- * @param {number} segmentLength
- *
- * @return {number}
- */
- export function calculateSegmentMoveRegion(segmentLength) {
- return Math.abs(Math.round(segmentLength * 2 / 3));
- }
- /**
- * Returns the point with the closest distance that is on the connection path.
- *
- * @param {Point} position
- * @param {djs.Base.Connection} connection
- * @returns {Point}
- */
- export function getClosestPointOnConnection(position, connection) {
- var segment = getClosestSegment(position, connection);
- return perpendicularFoot(position, segment);
- }
- // helper //////////
- function calculateHitWidth(segmentStart, segmentEnd, alignment) {
- var segmentLengthXAxis = segmentEnd.x - segmentStart.x,
- segmentLengthYAxis = segmentEnd.y - segmentStart.y;
- return alignment === 'h' ?
- calculateSegmentMoveRegion(segmentLengthXAxis) :
- calculateSegmentMoveRegion(segmentLengthYAxis);
- }
- function getClosestSegment(position, connection) {
- var waypoints = connection.waypoints;
- var minDistance = Infinity,
- segmentIndex;
- for (var i = 0; i < waypoints.length - 1; i++) {
- var start = waypoints[i],
- end = waypoints[i + 1],
- distance = getDistancePointLine(position, [ start, end ]);
- if (distance < minDistance) {
- minDistance = distance;
- segmentIndex = i;
- }
- }
- return [ waypoints[segmentIndex], waypoints[segmentIndex + 1] ];
- }
|