diff --git a/client/app/scripts/charts/edge-container.js b/client/app/scripts/charts/edge-container.js index 369365f5b..981e8b0c4 100644 --- a/client/app/scripts/charts/edge-container.js +++ b/client/app/scripts/charts/edge-container.js @@ -2,7 +2,7 @@ import React from 'react'; import { Motion, spring } from 'react-motion'; import { Map as makeMap } from 'immutable'; import { line, curveBasis } from 'd3-shape'; -import { each, omit, times, constant } from 'lodash'; +import { each, times, constant } from 'lodash'; import { NODES_SPRING_ANIMATION_CONFIG } from '../constants/animation'; import { NODE_BASE_SIZE, EDGE_WAYPOINTS_CAP } from '../constants/styles'; @@ -70,8 +70,7 @@ export default class EdgeContainer extends React.PureComponent { } render() { - const { isAnimated, waypoints } = this.props; - const forwardedProps = omit(this.props, 'isAnimated', 'waypoints', 'scale'); + const { isAnimated, waypoints, scale, ...forwardedProps } = this.props; if (!isAnimated) { return transformedEdge(forwardedProps, waypoints.toJS(), this.state.thickness); diff --git a/client/app/scripts/charts/edge.js b/client/app/scripts/charts/edge.js index 7d31aae8a..276f2aa09 100644 --- a/client/app/scripts/charts/edge.js +++ b/client/app/scripts/charts/edge.js @@ -14,9 +14,9 @@ class Edge extends React.Component { } render() { - const { id, path, highlighted, blurred, focused, thickness, source, target } = this.props; + const { id, path, highlighted, focused, thickness, source, target } = this.props; const shouldRenderMarker = (focused || highlighted) && (source !== target); - const className = classNames('edge', { highlighted, blurred }); + const className = classNames('edge', { highlighted }); return ( ( +const transformedNode = (otherProps, { x, y, k }) => ( // NOTE: Controlling blurring and transform from here seems to re-render // faster than adding a CSS class and controlling it from there. - + ); export default class NodeContainer extends React.PureComponent { render() { - const { dx, dy, isAnimated, scale, blurred, contrastMode } = this.props; - const nodeBlurOpacity = contrastMode ? 0.6 : 0.25; - const forwardedProps = omit(this.props, 'dx', 'dy', 'isAnimated', 'scale', 'blurred'); - const opacity = blurred ? nodeBlurOpacity : 1; + const { dx, dy, isAnimated, scale, ...forwardedProps } = this.props; if (!isAnimated) { // Show static node for optimized rendering - return transformedNode(forwardedProps, { x: dx, y: dy, k: scale, opacity }); + return transformedNode(forwardedProps, { x: dx, y: dy, k: scale }); } return ( @@ -33,7 +29,6 @@ export default class NodeContainer extends React.PureComponent { x: spring(dx, NODES_SPRING_ANIMATION_CONFIG), y: spring(dy, NODES_SPRING_ANIMATION_CONFIG), k: spring(scale, NODES_SPRING_ANIMATION_CONFIG), - opacity: spring(opacity, NODES_SPRING_ANIMATION_CONFIG), }}> {interpolated => transformedNode(forwardedProps, interpolated)} diff --git a/client/app/scripts/charts/nodes-chart-elements.js b/client/app/scripts/charts/nodes-chart-elements.js index c1479ff83..0c4e62280 100644 --- a/client/app/scripts/charts/nodes-chart-elements.js +++ b/client/app/scripts/charts/nodes-chart-elements.js @@ -1,6 +1,7 @@ import React from 'react'; +import classNames from 'classnames'; import { connect } from 'react-redux'; -import { Map as makeMap, List as makeList } from 'immutable'; +import { fromJS, Map as makeMap, List as makeList } from 'immutable'; import NodeContainer from './node-container'; import EdgeContainer from './edge-container'; @@ -152,7 +153,6 @@ class NodesChartElements extends React.Component { matches={node.get('matches')} networks={node.get('networks')} metric={node.get('metric')} - blurred={node.get('blurred')} focused={node.get('focused')} highlighted={node.get('highlighted')} shape={node.get('shape')} @@ -183,14 +183,30 @@ class NodesChartElements extends React.Component { waypoints={edge.get('points')} highlighted={edge.get('highlighted')} focused={edge.get('focused')} - blurred={edge.get('blurred')} scale={edge.get('scale')} isAnimated={isAnimated} /> ); } + renderOverlay(element) { + // NOTE: This piece of code is a bit hacky - as we can't set the absolute coords for the + // SVG element, we set the zoom level high enough that we're sure it covers the screen. + const className = classNames('nodes-chart-overlay', { active: element.get('isActive') }); + const scale = (this.props.selectedScale || 1) * 100000; + return ( + + ); + } + renderElement(element) { + if (element.get('isOverlay')) { + return this.renderOverlay(element); + } // This heuristics is not ideal but it works. return element.get('points') ? this.renderEdge(element) : this.renderNode(element); } @@ -220,6 +236,7 @@ class NodesChartElements extends React.Component { const orderedElements = makeList([ edges.get(BLURRED_EDGES_LAYER, makeList()), nodes.get(BLURRED_NODES_LAYER, makeList()), + fromJS([{ isOverlay: true, isActive: !!nodes.get(BLURRED_NODES_LAYER) }]), edges.get(NORMAL_EDGES_LAYER, makeList()), nodes.get(NORMAL_NODES_LAYER, makeList()), edges.get(HIGHLIGHTED_EDGES_LAYER, makeList()), diff --git a/client/app/scripts/constants/animation.js b/client/app/scripts/constants/animation.js index 895b5f5f4..edc3a2ad0 100644 --- a/client/app/scripts/constants/animation.js +++ b/client/app/scripts/constants/animation.js @@ -1,3 +1,3 @@ -export const NODES_SPRING_ANIMATION_CONFIG = { stiffness: 80, damping: 20, precision: 0.1 }; +export const NODES_SPRING_ANIMATION_CONFIG = { stiffness: 200, damping: 25, precision: 1 }; export const NODES_SPRING_FAST_ANIMATION_CONFIG = { stiffness: 800, damping: 50, precision: 1 }; diff --git a/client/app/scripts/selectors/topology.js b/client/app/scripts/selectors/topology.js index 6c9465ff3..c4d06655a 100644 --- a/client/app/scripts/selectors/topology.js +++ b/client/app/scripts/selectors/topology.js @@ -46,7 +46,7 @@ export const graphExceedsComplexityThreshSelector = createSelector( state => state.getIn(['currentTopology', 'stats', 'node_count']) || 0, state => state.getIn(['currentTopology', 'stats', 'edge_count']) || 0, ], - (nodeCount, edgeCount) => (nodeCount + (2 * edgeCount)) > 1000 + (nodeCount, edgeCount) => (nodeCount + (2 * edgeCount)) > 500 ); // Options for current topology, sub-topologies share options with parent diff --git a/client/app/styles/_base.scss b/client/app/styles/_base.scss index adda36df4..14c72b03c 100644 --- a/client/app/styles/_base.scss +++ b/client/app/styles/_base.scss @@ -411,6 +411,15 @@ } +.nodes-chart-overlay { + pointer-events: none; + opacity: 0; + + &.active { + opacity: $node-elements-in-background-opacity; + } +} + .nodes-chart, .nodes-resources { &-error, &-loading { @@ -438,7 +447,8 @@ li { padding-top: 5px; } } - &-loading &-error-icon-container { + // Make watermarks blink only if actually shown (otherwise the FF performance decreses weirdly). + &-loading:not(.hide) &-error-icon-container { @extend .blinkable; } @@ -468,7 +478,6 @@ } .nodes-chart-elements .node { - transition: opacity .2s $base-ease; text-align: center; .node-label { @@ -562,12 +571,6 @@ } .edge { - transition: opacity .5s $base-ease; - - &.blurred { - opacity: $edge-opacity-blurred; - } - .link { fill: none; stroke: $edge-color; @@ -628,7 +631,6 @@ fill: none; stroke-opacity: 1; stroke-width: $node-border-stroke-width; - transition: stroke-opacity 0.333s $base-ease, fill 0.333s $base-ease; } &.metrics .border { diff --git a/client/app/styles/_contrast-overrides.scss b/client/app/styles/_contrast-overrides.scss index 310f79166..94339a0f7 100644 --- a/client/app/styles/_contrast-overrides.scss +++ b/client/app/styles/_contrast-overrides.scss @@ -12,6 +12,8 @@ $text-darker-color: darken($text-color, 20%); $white: white; $edge-color: black; +$node-elements-in-background-opacity: 0.4; + $node-highlight-shadow-opacity: 0.4; $node-highlight-stroke-opacity: 0.5; $node-highlight-stroke-width: 0.16; diff --git a/client/app/styles/_variables.scss b/client/app/styles/_variables.scss index ac30c5d25..07701f135 100644 --- a/client/app/styles/_variables.scss +++ b/client/app/styles/_variables.scss @@ -31,6 +31,8 @@ $border-radius: 4px; $terminal-header-height: 44px; +$node-elements-in-background-opacity: 0.7; + $node-highlight-shadow-opacity: 0.5; $node-highlight-stroke-opacity: 0.4; $node-highlight-stroke-width: 0.04;