UNPKG

@progress/kendo-angular-gantt

Version:
196 lines (195 loc) 6.93 kB
/**----------------------------------------------------------------------------------------- * Copyright © 2025 Progress Software Corporation. All rights reserved. * Licensed under commercial license. See LICENSE.md in the project root for more information *-------------------------------------------------------------------------------------------*/ import { DependencyType } from '../models/dependency-type.enum'; /** * @hidden * * Gets the offset (top and left values) relative to a target element. */ export const getOffsetRelativeToParent = (element, targetParent) => { const offset = { top: 0, left: 0 }; if (!targetParent.contains(element)) { return offset; } let offsetParent = element; while (offsetParent && offsetParent !== targetParent) { offset.top += offsetParent.offsetTop; offset.left += offsetParent.offsetLeft; offsetParent = offsetParent.offsetParent; } return offset; }; /** * @hidden */ export const getElementRect = (element, relativeContainer) => { const { top, left } = getOffsetRelativeToParent(element, relativeContainer); return { top: top + element.offsetHeight / 2, left: left, right: left + element.offsetWidth }; }; /** * @hidden */ export const dependencyCoordinates = (from, to, rowHeight, type, minDistanceBeforeTurn, arrowSize) => { const points = []; const minTurnHeight = Math.floor(rowHeight / 2); const drawingDown = from.top < to.top; let top, left; // FF and SS are composed of 4 connected polyline points (not counting the arrow) /* [[[]]]- -[[[]]] | | [[[]]]- -[[[]]] */ if (type === DependencyType.FF || type === DependencyType.SS) { // polyline start from first task const dir = type === DependencyType.SS ? 'left' : 'right'; top = from.top; left = from[dir]; points.push({ top, left }); // first turn point left = Math[dir === 'left' ? 'min' : 'max'](from[dir], to[dir]); left = dir === 'left' ? left - minDistanceBeforeTurn : left + minDistanceBeforeTurn; points.push({ top, left }); // second turn point top = to.top; points.push({ top, left }); // second task reached left = dir === 'left' ? to[dir] - arrowSize : to[dir] + arrowSize; points.push({ top, left }); // arrow pointing to the second task points.push(...getArrow(top, left, dir !== 'left', arrowSize)); } else { // FS and SF are composed of 4 or 6 connected polyline points (not counting the arrow), depending on the position of the tasks /* [[[]]]- [[[]]]- | | -[[[]]] ----- | -[[[]]] */ const startDir = type === DependencyType.SF ? 'left' : 'right'; const endDir = type === DependencyType.SF ? 'right' : 'left'; const additionalTurn = type === DependencyType.SF ? from[startDir] - minDistanceBeforeTurn * 2 < to[endDir] : from[startDir] + minDistanceBeforeTurn * 2 > to[endDir]; // polyline start from first task top = from.top; left = from[startDir]; points.push({ top, left }); // first turn point left = startDir === 'left' ? left - minDistanceBeforeTurn : left + minDistanceBeforeTurn; points.push({ top, left }); // if second task start is before the first task end in FS // if second task end is after the first task start in SF if (additionalTurn) { // additional turn start top = drawingDown ? top + minTurnHeight : top - minTurnHeight; points.push({ top, left }); // additional turn end left = startDir === 'left' ? to[endDir] + minDistanceBeforeTurn : to[endDir] - minDistanceBeforeTurn; points.push({ top, left }); } // second task level reached top = to.top; points.push({ top, left }); // second task element reached left = endDir === 'left' ? to[endDir] - arrowSize : to[endDir] + arrowSize; points.push({ top, left }); // arrow pointing to the second task points.push(...getArrow(top, left, endDir !== 'left', arrowSize)); } return points; }; const getArrow = (top, left, isArrowWest, arrowSize) => { const points = isArrowWest ? getArrowWest(top, left, arrowSize) : getArrowEast(top, left, arrowSize); return points; }; const getArrowWest = (top, left, arrowSize) => { const points = []; points.push({ top: top - arrowSize / 2, left }); points.push({ top, left: left - arrowSize + 1 }); points.push({ top: top + arrowSize / 2, left }); points.push({ top, left }); return points; }; const getArrowEast = (top, left, arrowSize) => { const points = []; points.push({ top: top + arrowSize / 2, left }); points.push({ top, left: left + arrowSize - 1 }); points.push({ top: top - arrowSize / 2, left }); points.push({ top, left }); return points; }; /** * @hidden * * Translates the provided client `left` and `top` coords to coords relative to the provided container. * https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems#standard_cssom_coordinate_systems */ export const clientToOffsetCoords = (clientLeft, clientTop, offsetContainer) => { // client (viewport) coordinates of the target container // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#value const offsetContainerClientRect = offsetContainer.getBoundingClientRect(); return { left: clientLeft - offsetContainerClientRect.left + offsetContainer.scrollLeft, top: clientTop - offsetContainerClientRect.top + offsetContainer.scrollTop }; }; /** * @hidden * * Retrieves the `left` and `top` values of the center of the provided element. * The retrieved values are relative to the current viewport (client values). * https://developer.mozilla.org/en-US/docs/Web/CSS/CSSOM_View/Coordinate_systems#standard_cssom_coordinate_systems */ export const getElementClientCenterCoords = (element) => { // client (viewport) coordinates of the targeted element // https://developer.mozilla.org/en-US/docs/Web/API/Element/getBoundingClientRect#value const { left, top, width, height } = element.getBoundingClientRect(); return { left: left + (width / 2), top: top + (height / 2) }; };