UNPKG

@progress/kendo-charts

Version:

Kendo UI platform-independent Charts library

266 lines (207 loc) 6.79 kB
import { geometry as geom } from '@progress/kendo-drawing'; import Point from './point'; import { X, Y, TOP, BOTTOM, LEFT, RIGHT, CENTER } from '../common/constants'; import { getSpacing, isArray, rad } from '../common'; class Box { constructor(x1, y1, x2, y2) { this.x1 = x1 || 0; this.y1 = y1 || 0; this.x2 = x2 || 0; this.y2 = y2 || 0; } equals(box) { return this.x1 === box.x1 && this.x2 === box.x2 && this.y1 === box.y1 && this.y2 === box.y2; } width() { return this.x2 - this.x1; } height() { return this.y2 - this.y1; } translate(dx, dy) { this.x1 += dx; this.x2 += dx; this.y1 += dy; this.y2 += dy; return this; } move(x, y) { const height = this.height(); const width = this.width(); if (x !== undefined) { this.x1 = x; this.x2 = this.x1 + width; } if (y !== undefined) { this.y1 = y; this.y2 = this.y1 + height; } return this; } wrap(targetBox) { this.x1 = Math.min(this.x1, targetBox.x1); this.y1 = Math.min(this.y1, targetBox.y1); this.x2 = Math.max(this.x2, targetBox.x2); this.y2 = Math.max(this.y2, targetBox.y2); return this; } wrapLimit(targetBox, widthLimit, heightLimit) { this.x1 = Math.min(this.x1, Math.max(this.x1 - widthLimit, targetBox.x1)); this.y1 = Math.min(this.y1, Math.max(this.y1 - heightLimit, targetBox.y1)); this.x2 = Math.max(this.x2, Math.min(this.x2 + widthLimit, targetBox.x2)); this.y2 = Math.max(this.y2, Math.min(this.y2 + heightLimit, targetBox.y2)); return this; } wrapPoint(point) { const arrayPoint = isArray(point); const x = arrayPoint ? point[0] : point.x; const y = arrayPoint ? point[1] : point.y; this.wrap(new Box(x, y, x, y)); return this; } snapTo(targetBox, axis) { if (axis === X || !axis) { this.x1 = targetBox.x1; this.x2 = targetBox.x2; } if (axis === Y || !axis) { this.y1 = targetBox.y1; this.y2 = targetBox.y2; } return this; } alignTo(targetBox, anchor) { const height = this.height(); const width = this.width(); const axis = anchor === TOP || anchor === BOTTOM ? Y : X; const offset = axis === Y ? height : width; if (anchor === CENTER) { const targetCenter = targetBox.center(); const center = this.center(); this.x1 += targetCenter.x - center.x; this.y1 += targetCenter.y - center.y; } else if (anchor === TOP || anchor === LEFT) { this[axis + 1] = targetBox[axis + 1] - offset; } else { this[axis + 1] = targetBox[axis + 2]; } this.x2 = this.x1 + width; this.y2 = this.y1 + height; return this; } shrink(dw, dh) { this.x2 -= dw; this.y2 -= dh; return this; } expand(dw, dh) { this.shrink(-dw, -dh); return this; } pad(padding) { const spacing = getSpacing(padding); this.x1 -= spacing.left; this.x2 += spacing.right; this.y1 -= spacing.top; this.y2 += spacing.bottom; return this; } unpad(padding) { const spacing = getSpacing(padding); spacing.left = -spacing.left; spacing.top = -spacing.top; spacing.right = -spacing.right; spacing.bottom = -spacing.bottom; return this.pad(spacing); } clone() { return new Box(this.x1, this.y1, this.x2, this.y2); } center() { return new Point( this.x1 + this.width() / 2, this.y1 + this.height() / 2 ); } containsPoint(point) { return point.x >= this.x1 && point.x <= this.x2 && point.y >= this.y1 && point.y <= this.y2; } points() { return [ new Point(this.x1, this.y1), new Point(this.x2, this.y1), new Point(this.x2, this.y2), new Point(this.x1, this.y2) ]; } getHash() { return [ this.x1, this.y1, this.x2, this.y2 ].join(","); } overlaps(box) { return !(box.y2 < this.y1 || this.y2 < box.y1 || box.x2 < this.x1 || this.x2 < box.x1); } rotate(rotation) { let width = this.width(); let height = this.height(); const { x: cx, y: cy } = this.center(); const r1 = rotatePoint(0, 0, cx, cy, rotation); const r2 = rotatePoint(width, 0, cx, cy, rotation); const r3 = rotatePoint(width, height, cx, cy, rotation); const r4 = rotatePoint(0, height, cx, cy, rotation); width = Math.max(r1.x, r2.x, r3.x, r4.x) - Math.min(r1.x, r2.x, r3.x, r4.x); height = Math.max(r1.y, r2.y, r3.y, r4.y) - Math.min(r1.y, r2.y, r3.y, r4.y); this.x2 = this.x1 + width; this.y2 = this.y1 + height; return this; } toRect() { return new geom.Rect([ this.x1, this.y1 ], [ this.width(), this.height() ]); } hasSize() { return this.width() !== 0 && this.height() !== 0; } align(targetBox, axis, alignment) { if (axis === X) { this.alignX(targetBox, alignment); } else { this.alignY(targetBox, alignment); } return this; } alignX(targetBox, alignment) { const width = this.width(); if (alignment === LEFT) { this.x1 = targetBox.x1; this.x2 = this.x1 + width; } else if (alignment === RIGHT) { this.x2 = targetBox.x2; this.x1 = this.x2 - width; } else if (alignment === CENTER) { this.x1 = targetBox.x1 + (targetBox.width() - width) / 2; this.x2 = this.x1 + width; } } alignY(targetBox, alignment) { const height = this.height(); if (alignment === TOP) { this.y1 = targetBox.y1; this.y2 = this.y1 + height; } else if (alignment === BOTTOM) { this.y2 = targetBox.y2; this.y1 = this.y2 - height; } else if (alignment === CENTER) { this.y1 = targetBox.y1 + (targetBox.height() - height) / 2; this.y2 = this.y1 + height; } } } function rotatePoint(x, y, cx, cy, angle) { const theta = rad(angle); return new Point( cx + (x - cx) * Math.cos(theta) + (y - cy) * Math.sin(theta), cy - (x - cx) * Math.sin(theta) + (y - cy) * Math.cos(theta) ); } export default Box;