diff --git a/client/app/scripts/charts/edge.js b/client/app/scripts/charts/edge.js index c7bb9f4ccb..97797195f4 100644 --- a/client/app/scripts/charts/edge.js +++ b/client/app/scripts/charts/edge.js @@ -1,5 +1,7 @@ +const _ = require('lodash'); const d3 = require('d3'); const React = require('react'); +const Spring = require('react-motion').Spring; const AppActions = require('../actions/app-actions'); @@ -8,19 +10,81 @@ const line = d3.svg.line() .x(function(d) { return d.x; }) .y(function(d) { return d.y; }); +const animConfig = [80, 20]; // stiffness, bounce + +const flattenPoints = function(points) { + const flattened = {}; + points.forEach(function(point, i) { + flattened['x' + i] = {val: point.x, config: animConfig}; + flattened['y' + i] = {val: point.y, config: animConfig}; + }); + return flattened; +}; + +const extractPoints = function(points) { + const extracted = []; + _.each(points, function(value, key) { + const axis = key[0]; + const index = key.slice(1); + if (!extracted[index]) { + extracted[index] = {}; + } + extracted[index][axis] = value.val; + }); + return extracted; +}; + const Edge = React.createClass({ + getInitialState: function() { + return { + points: [] + }; + }, + + componentWillMount: function() { + this.ensureSameLength(this.props.points); + }, + + componentWillReceiveProps: function(nextProps) { + this.ensureSameLength(nextProps.points); + }, + render: function() { const className = this.props.highlighted ? 'edge highlighted' : 'edge'; + const points = flattenPoints(this.props.points); + const props = this.props; + const handleMouseEnter = this.handleMouseEnter; + const handleMouseLeave = this.handleMouseLeave; return ( - - - - + + {function(interpolated) { + const path = line(extractPoints(interpolated)); + return ( + + + + + ); + }} + ); }, + ensureSameLength: function(points) { + // Spring needs constant list length, hoping that dagre will insert never more than 10 + const length = 10; + let missing = length - points.length; + + while (missing) { + points.unshift(points[0]); + missing = length - points.length; + } + + return points; + }, + handleMouseEnter: function(ev) { AppActions.enterEdge(ev.currentTarget.id); }, diff --git a/client/app/scripts/charts/node.js b/client/app/scripts/charts/node.js index e47691470c..eff188b02d 100644 --- a/client/app/scripts/charts/node.js +++ b/client/app/scripts/charts/node.js @@ -1,46 +1,16 @@ const React = require('react'); -const tweenState = require('react-tween-state'); +const Spring = require('react-motion').Spring; const AppActions = require('../actions/app-actions'); const NodeColorMixin = require('../mixins/node-color-mixin'); const Node = React.createClass({ mixins: [ - NodeColorMixin, - tweenState.Mixin + NodeColorMixin ], - getInitialState: function() { - return { - x: 0, - y: 0 - }; - }, - - componentWillMount: function() { - // initial node position when rendered the first time - this.setState({ - x: this.props.dx, - y: this.props.dy - }); - }, - - componentWillReceiveProps: function(nextProps) { - // animate node transition to next position - this.tweenState('x', { - easing: tweenState.easingTypes.easeInOutQuad, - duration: 500, - endValue: nextProps.dx - }); - this.tweenState('y', { - easing: tweenState.easingTypes.easeInOutQuad, - duration: 500, - endValue: nextProps.dy - }); - }, - render: function() { - const transform = 'translate(' + this.getTweeningValue('x') + ',' + this.getTweeningValue('y') + ')'; + const props = this.props; const scale = this.props.scale; const textOffsetX = 0; const textOffsetY = scale(0.5) + 18; @@ -50,6 +20,8 @@ const Node = React.createClass({ const onMouseEnter = this.handleMouseEnter; const onMouseLeave = this.handleMouseLeave; const classNames = ['node']; + const ellipsis = this.ellipsis; + const animConfig = [80, 20]; // stiffness, bounce if (this.props.highlighted) { classNames.push('highlighted'); @@ -60,19 +32,26 @@ const Node = React.createClass({ } return ( - - {this.props.highlighted && } - - - - - {this.ellipsis(this.props.label, 14)} - - - {this.ellipsis(this.props.subLabel, 12)} - - + + {function(interpolated) { + const transform = 'translate(' + interpolated.x.val + ',' + interpolated.y.val + ')'; + return ( + + {props.highlighted && } + + + + + {ellipsis(props.label, 14)} + + + {ellipsis(props.subLabel, 12)} + + + ); + }} + ); }, diff --git a/client/package.json b/client/package.json index c14726dc49..0d38001c60 100644 --- a/client/package.json +++ b/client/package.json @@ -20,6 +20,7 @@ "object-assign": "^2.0.0", "page": "^1.6.3", "react": "^0.13.3", + "react-motion": "^0.2.7", "react-tap-event-plugin": "^0.1.7", "react-tween-state": "0.0.5", "reqwest": "~1.1.5",