blob: 375554ecd55728e5f64e32c6241d1f6a4d64fc17 [file] [log] [blame]
/**
* DragToZoomBoxSk is a selection box applied on top of the google chart
* when a user ctrl click onto it. The user can drag the selection horizontally
* and vertically and this module will estimate the difference between the
* values based on the start and end cursor positions.
*/
import { css, html, LitElement } from 'lit';
import { customElement, property } from 'lit/decorators.js';
@customElement('drag-to-zoom-box-sk')
export class DragToZoomBox extends LitElement {
static styles = css`
:host {
display: none;
position: absolute; /* note: this interferes with calculating offsetY */
border-style: solid;
border-width: 1px 1px;
border-color: rgba(255, 99, 71, 0.4); /* almost orange red color */
background-color: rgba(255, 99, 68, 0.4); /* semi-transparent shade of orange hue */
--md-elevation-level: 1;
cursor: magnifying glass;
}
`;
protected render() {
return html`<md-elevation></md-elevation>`;
}
// mark the starting cursor location in the plot-google-chart
// start represents the selection range of either top, left, bottom or right
// we need to track the start coordinate because getBoundingClientRect
// is with respect to the viewport
@property()
startPosition = {
xOffset: 0,
yOffset: 0,
};
// store the chart boundary information in the plot-google-chart
@property()
private boundaryInfo = {
width: 0,
height: 0,
};
/**
* Initialize pass into helper variables to show the vertical or horizontal selection box.
* @param chartArea key positions of the google chart. Top and bottom are used to
* determine the max and min boundary horizontally. Left and right are determined the
* min and max boundary vertically.
* Height and width allow the selection to cleanly cover the chart.
* @param start the coordinate and y value of the chart where the cursor is
*/
initializeShow(
chartArea: { top: number; left: number; width: number; height: number },
start: { xOffset: number; yOffset: number }
) {
this.startPosition = start;
this.style.top = `${chartArea.top}px`;
this.style.left = `${chartArea.left}px`;
this.boundaryInfo.width = chartArea.width;
this.boundaryInfo.height = chartArea.height;
this.style.display = 'block';
}
/**
* Hide the module by switching the display to none
*/
hide() {
this.style.display = 'none';
this.style.height = `0px`;
this.style.width = `0px`;
}
/**
* Handle a drag event and update the selection area relative to the cursor start point
* @param update the updated cursor coordinate and boolean to distinguish if
* the direction is horizontal or vertical
*/
handleDrag(update: { offset: number; isHorizontal: boolean }) {
if (update.isHorizontal) {
const newLeft = Math.min(update.offset, this.startPosition.xOffset);
const width = Math.abs(update.offset - this.startPosition.xOffset);
this.style.left = `${newLeft}px`;
this.style.width = `${width}px`;
this.style.height = `${this.boundaryInfo.height}px`;
} else {
const newTop = Math.min(update.offset, this.startPosition.yOffset);
const height = Math.abs(update.offset - this.startPosition.yOffset);
this.style.top = `${newTop}px`;
this.style.height = `${height}px`;
this.style.width = `${this.boundaryInfo.width}px`;
}
}
}