Added a semitransparent layer over the background nodes.

This commit is contained in:
Filip Barl
2017-08-04 11:59:27 +02:00
parent 656fbac4e6
commit 038bbbd5ce
8 changed files with 63 additions and 39 deletions

View File

@@ -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 (
<g

View File

@@ -6,24 +6,22 @@ import { NODES_SPRING_ANIMATION_CONFIG } from '../constants/animation';
import Node from './node';
const transformedNode = (otherProps, { x, y, k, opacity }) => (
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.
<g transform={`translate(${x},${y}) scale(${k})`} style={{opacity}}>
<g transform={`translate(${x},${y}) scale(${k})`}>
<Node {...otherProps} />
</g>
);
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 } = this.props;
const forwardedProps = omit(this.props, 'dx', 'dy', 'isAnimated', 'scale');
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 +31,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)}
</Motion>

View File

@@ -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,7 +183,6 @@ 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}
/>
@@ -191,6 +190,16 @@ class NodesChartElements extends React.Component {
}
renderElement(element) {
if (element.get('overlay')) {
const className = classNames('nodes-overlay', { active: element.get('active') });
return (
<rect
className={className}
x={-1} y={-1} width={2} height={2}
transform="scale(1000000)"fill="#fff"
/>
);
}
// This heuristics is not ideal but it works.
return element.get('points') ? this.renderEdge(element) : this.renderNode(element);
}
@@ -213,6 +222,11 @@ class NodesChartElements extends React.Component {
.map(this.edgeScaleDecorator)
.groupBy(this.edgeDisplayLayer);
// const orderedElements = makeList([
// edges,
// nodes,
// ]).flatten(true);
// NOTE: The elements need to be arranged into a single array outside
// of DOM structure for React rendering engine to do smart rearrangements
// without unnecessary re-rendering of the elements themselves. So e.g.
@@ -220,6 +234,7 @@ class NodesChartElements extends React.Component {
const orderedElements = makeList([
edges.get(BLURRED_EDGES_LAYER, makeList()),
nodes.get(BLURRED_NODES_LAYER, makeList()),
fromJS([{ overlay: true, active: !!nodes.get(BLURRED_NODES_LAYER) }]),
edges.get(NORMAL_EDGES_LAYER, makeList()),
nodes.get(NORMAL_NODES_LAYER, makeList()),
edges.get(HIGHLIGHTED_EDGES_LAYER, makeList()),
@@ -242,7 +257,7 @@ function mapStateToProps(state) {
hasSelectedNode: hasSelectedNodeFn(state),
layoutNodes: layoutNodesSelector(state),
layoutEdges: layoutEdgesSelector(state),
isAnimated: !graphExceedsComplexityThreshSelector(state),
isAnimated: false && !graphExceedsComplexityThreshSelector(state),
highlightedNodeIds: highlightedNodeIdsSelector(state),
highlightedEdgeIds: highlightedEdgeIdsSelector(state),
selectedNetworkNodesIds: selectedNetworkNodesIdsSelector(state),

View File

@@ -151,6 +151,7 @@ class NodeDetails extends React.Component {
}
renderDetails() {
console.log('render details');
const { details, nodeControlStatus, nodeMatches = makeMap() } = this.props;
const showControls = details.controls && details.controls.length > 0;
const nodeColor = getNodeColorDark(details.rank, details.label, details.pseudo);

View File

@@ -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 };

View File

@@ -27,15 +27,18 @@
}
.colorable {
transition: background-color .3s $base-ease;
transition: none;
// transition: background-color .3s $base-ease;
}
.palable {
transition: all .2s $base-ease;
transition: none;
// transition: all .2s $base-ease;
}
.hideable {
transition: opacity .5s $base-ease;
transition: none;
// transition: opacity .5s $base-ease;
}
.blinkable {
@@ -259,7 +262,7 @@
margin-bottom: 15px;
z-index: 2001;
transition: all .15s $base-ease;
// transition: all .15s $base-ease;
overflow: hidden;
height: 0;
@@ -411,6 +414,16 @@
}
.nodes-overlay {
// transition: opacity 2.5s $base-ease;
pointer-events: none;
opacity: 0;
&.active {
opacity: $node-elements-in-background-opacity;
}
}
.nodes-chart, .nodes-resources {
&-error, &-loading {
@@ -439,7 +452,7 @@
}
&-loading &-error-icon-container {
@extend .blinkable;
// @extend .blinkable;
}
&-loading {
@@ -468,7 +481,7 @@
}
.nodes-chart-elements .node {
transition: opacity .2s $base-ease;
// transition: opacity .2s $base-ease;
text-align: center;
.node-label {
@@ -562,12 +575,6 @@
}
.edge {
transition: opacity .5s $base-ease;
&.blurred {
opacity: $edge-opacity-blurred;
}
.link {
fill: none;
stroke: $edge-color;
@@ -628,7 +635,7 @@
fill: none;
stroke-opacity: 1;
stroke-width: $node-border-stroke-width;
transition: stroke-opacity 0.333s $base-ease, fill 0.333s $base-ease;
// transition: stroke-opacity 0.333s $base-ease, fill 0.333s $base-ease;
}
&.metrics .border {
@@ -700,7 +707,7 @@
right: $details-window-padding-left;
top: 100px;
bottom: 48px;
transition: transform 0.33333s cubic-bezier(0,0,0.21,1), margin-top .15s $base-ease;
// transition: transform 0.33333s cubic-bezier(0,0,0.21,1), margin-top .15s $base-ease;
}
}
@@ -848,7 +855,7 @@
color: $white;
&-icon {
@extend .blinkable;
// @extend .blinkable;
margin-right: 0.5em;
}
}
@@ -1237,7 +1244,7 @@
left: 10px;
bottom: 10px;
right: 0;
transition: transform 0.5s cubic-bezier(0.230, 1.000, 0.320, 1.000);
// transition: transform 0.5s cubic-bezier(0.230, 1.000, 0.320, 1.000);
@extend .shadow-2;
}
@@ -1397,7 +1404,7 @@
}
.error {
animation: blinking 2.0s 60 $base-ease; // blink for 2 minutes
// animation: blinking 2.0s 60 $base-ease; // blink for 2 minutes
color: $text-secondary-color;
}
@@ -1421,7 +1428,7 @@
}
&.status-loading {
animation: blinking 2.0s 150 $base-ease; // keep blinking for 5 minutes
// animation: blinking 2.0s 150 $base-ease; // keep blinking for 5 minutes
text-transform: none;
color: $text-color;
}
@@ -1530,7 +1537,7 @@
}
&-info {
@extend .blinkable;
// @extend .blinkable;
display: block;
margin-top: 5px;
text-align: right;
@@ -1618,7 +1625,7 @@
display: inline-block;
position: relative;
width: 10em;
transition: width 0.3s 0s $base-ease;
// transition: width 0.3s 0s $base-ease;
&-wrapper {
flex: 0 1 20%;
@@ -1638,7 +1645,7 @@
color: $text-tertiary-color;
top: 0;
opacity: 0;
transition: transform 0.3s 0s $base-ease, opacity 0.3s 0s $base-ease;
// transition: transform 0.3s 0s $base-ease, opacity 0.3s 0s $base-ease;
text-align: left;
}
@@ -1665,7 +1672,7 @@
&-hint {
font-size: 0.8rem;
text-transform: uppercase;
transition: opacity 0.3s 0.5s $base-ease;
// transition: opacity 0.3s 0.5s $base-ease;
opacity: 1;
}
}
@@ -1703,7 +1710,7 @@
&-focused &-label-hint,
&-pinned &-label-hint,
&-filled &-label-hint {
transition: opacity 0.1s 0s $base-ease;
// transition: opacity 0.1s 0s $base-ease;
opacity: 0;
}
@@ -1712,7 +1719,7 @@
&-pinned &-hint {
opacity: 1;
transform: translate3d(0, 2.75em, 0);
transition: transform 0.3s 0.3s $base-ease, opacity 0.3s 0.3s $base-ease;
// transition: transform 0.3s 0.3s $base-ease, opacity 0.3s 0.3s $base-ease;
}
&-focused &-input-field,

View File

@@ -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;

View File

@@ -31,6 +31,8 @@ $border-radius: 4px;
$terminal-header-height: 44px;
$node-elements-in-background-opacity: 0.75;
$node-highlight-shadow-opacity: 0.5;
$node-highlight-stroke-opacity: 0.4;
$node-highlight-stroke-width: 0.04;