Add crosshair component at hovertime
parent
803a93babc
commit
bc4288861d
|
@ -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
|
|
@ -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 &&
|
||||
<div>
|
||||
<Annotations
|
||||
dygraph={this.dygraph}
|
||||
annotationsRef={this.handleAnnotationsRef}
|
||||
staticLegendHeight={staticLegendHeight}
|
||||
/>}
|
||||
{this.dygraph &&
|
||||
/>
|
||||
<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
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
|
||||
// Components
|
||||
@import 'components/annotations';
|
||||
@import 'components/crosshairs';
|
||||
@import 'components/ceo-display-options';
|
||||
@import 'components/confirm-button';
|
||||
@import 'components/confirm-buttons';
|
||||
|
|
|
@ -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;
|
||||
}
|
Loading…
Reference in New Issue