Add crosshair component at hovertime

pull/10616/head
Deniz Kusefoglu 2018-03-07 14:16:54 -08:00
parent 803a93babc
commit bc4288861d
4 changed files with 189 additions and 17 deletions

View File

@ -0,0 +1,41 @@
import React, {PropTypes, Component} from 'react'
import {DYGRAPH_CONTAINER_XLABEL_MARGIN} from 'shared/constants'
class Crosshair extends Component {
render() {
const {
dygraph,
staticLegendHeight,
hoverTime,
handleCrosshairRef,
} = this.props
const crosshairleft = Math.round(
Math.max(-1000, dygraph.toDomXCoord(hoverTime)) || -1000 + 1
)
const crosshairHeight = `calc(100% - ${staticLegendHeight +
DYGRAPH_CONTAINER_XLABEL_MARGIN}px)`
return (
<div className="new-crosshair" ref={el => handleCrosshairRef(el)}>
<div
className="new-crosshair--crosshair"
style={{
left: crosshairleft + 1,
height: crosshairHeight,
zIndex: 1999,
}}
/>
</div>
)
}
}
const {func, number, shape, string} = PropTypes
Crosshair.propTypes = {
dygraph: shape({}),
staticLegendHeight: number,
hoverTime: string,
handleCrosshairRef: func,
}
export default Crosshair

View File

@ -9,6 +9,7 @@ import Dygraphs from 'src/external/dygraph'
import DygraphLegend from 'src/shared/components/DygraphLegend'
import StaticLegend from 'src/shared/components/StaticLegend'
import Annotations from 'src/shared/components/Annotations'
import Crosshair from 'src/shared/components/Crosshair'
import getRange, {getStackedRange} from 'shared/parsing/getRangeForDygraph'
import {DISPLAY_OPTIONS} from 'src/dashboards/constants'
@ -196,10 +197,26 @@ class Dygraph extends Component {
onZoom(this.formatTimeRange(lower), this.formatTimeRange(upper))
}
highlightCallback = (e, x) => {
clampWithinGraphTimerange = timestamp => {
const [xRangeStart] = this.dygraph.xAxisRange()
return Math.max(xRangeStart, timestamp)
}
eventToTimestamp = ({pageX: pxBetweenMouseAndPage}) => {
const {
left: pxBetweenGraphAndPage,
} = this.crosshairRef.getBoundingClientRect()
const graphXCoordinate = pxBetweenMouseAndPage - pxBetweenGraphAndPage
const timestamp = this.dygraph.toDataXCoord(graphXCoordinate)
const clamped = this.clampWithinGraphTimerange(timestamp)
return `${clamped}`
}
highlightCallback = e => {
const {onSetHoverTime} = this.props
const newTime = this.eventToTimestamp(e)
if (onSetHoverTime) {
onSetHoverTime(x.toString())
onSetHoverTime(newTime)
}
}
@ -311,6 +328,7 @@ class Dygraph extends Component {
}
handleAnnotationsRef = ref => (this.annotationsRef = ref)
handleCrosshairRef = ref => (this.crosshairRef = ref)
handleReceiveStaticLegendHeight = staticLegendHeight => {
this.setState({staticLegendHeight})
@ -318,8 +336,7 @@ class Dygraph extends Component {
render() {
const {isHidden, staticLegendHeight} = this.state
const {staticLegend, children} = this.props
const {staticLegend, children, hoverTime} = this.props
const nestedGraph = (children && children.length && children[0]) || children
let dygraphStyle = {...this.props.containerStyle, zIndex: '2'}
if (staticLegend) {
@ -331,22 +348,28 @@ class Dygraph extends Component {
height: `calc(100% - ${staticLegendHeight + cellVerticalPadding}px)`,
}
}
return (
<div className="dygraph-child" onMouseLeave={this.deselectCrosshair}>
{this.dygraph &&
<Annotations
dygraph={this.dygraph}
annotationsRef={this.handleAnnotationsRef}
staticLegendHeight={staticLegendHeight}
/>}
{this.dygraph &&
<DygraphLegend
isHidden={isHidden}
dygraph={this.dygraph}
onHide={this.handleHideLegend}
onShow={this.handleShowLegend}
/>}
<div>
<Annotations
dygraph={this.dygraph}
annotationsRef={this.handleAnnotationsRef}
staticLegendHeight={staticLegendHeight}
/>
<DygraphLegend
isHidden={isHidden}
dygraph={this.dygraph}
onHide={this.handleHideLegend}
onShow={this.handleShowLegend}
/>
<Crosshair
dygraph={this.dygraph}
staticLegendHeight={staticLegendHeight}
hoverTime={hoverTime}
handleCrosshairRef={this.handleCrosshairRef}
/>
</div>}
<div
ref={r => {
this.graphRef = r

View File

@ -33,6 +33,7 @@
// Components
@import 'components/annotations';
@import 'components/crosshairs';
@import 'components/ceo-display-options';
@import 'components/confirm-button';
@import 'components/confirm-buttons';

View File

@ -0,0 +1,107 @@
$crosshair-color: $g20-white;
$crosshair-color__drag: $c-hydrogen;
$window0: rgba($crosshair-color, 0);
$window15: rgba($crosshair-color, 0.15);
$window35: rgba($crosshair-color, 0.35);
$active-window0: rgba($crosshair-color__drag, 0);
$active-window15: rgba($crosshair-color__drag, 0.15);
$active-window35: rgba($crosshair-color__drag, 0.35);
$timestamp-font-size: 14px;
$timestamp-font-weight: 600;
.crosshair {
position: absolute;
top: 8px;
z-index: 3;
background-color: $crosshair-color;
height: calc(100% - 36px);
width: 2px;
transform: translateX(
-1px
); // translate should always be half with width to horizontally center the crosshair pos
transition: background-color 0.25s ease;
visibility: visible;
&.dragging {
background-color: $crosshair-color__drag;
z-index: 4;
}
}
.crosshair-window {
position: absolute;
top: 8px;
background: linear-gradient(to bottom, $window15 0%, $window0 100%);
border-top: 2px dotted $window35;
z-index: 1;
&.active {
background: linear-gradient(
to bottom,
$active-window15 0%,
$active-window0 100%
);
border-top: 2px dotted $active-window35;
}
}
/*
New crosshairs
------------------------------------------------------------------------------
*/
.new-crosshair {
position: absolute;
z-index: 0;
top: 8px;
width: calc(100% - 32px);
height: calc(100% - 16px);
cursor: pointer;
opacity: 1;
}
.new-crosshair--crosshair {
opacity: 1;
position: absolute;
top: 0;
height: calc(100% - 20px);
width: 0.5px;
transform: translateX(-1px);
background: linear-gradient(to bottom, $c-dreamsicle 0%, $c-dreamsicle 100%);
transition: opacity 0.4s ease;
z-index: 5;
cursor: pointer;
}
.new-crosshair-tooltip {
display: flex;
flex-direction: column;
align-items: center;
background: linear-gradient(to bottom, $c-pool 0%, $c-ocean 100%);
border-radius: 4px;
padding: 6px 12px;
position: absolute;
bottom: calc(100% + 8px);
left: 50%;
transform: translateX(-50%);
z-index: 10;
}
.new-crosshair-helper {
white-space: nowrap;
font-size: 13px;
line-height: 13px;
font-weight: 600;
color: $c-neutrino;
margin-bottom: 4px;
}
.new-crosshair-timestamp {
white-space: nowrap;
font-size: $timestamp-font-size;
line-height: $timestamp-font-size;
font-weight: $timestamp-font-weight;
color: $g20-white;
}