Skip to content

Commit 43c959a

Browse files
authored
Merge pull request #54 from magjac/user-configuration-of-transitions
User configuration of transitions
2 parents 2d691a7 + 3fc02b7 commit 43c959a

File tree

5 files changed

+194
-13
lines changed

5 files changed

+194
-13
lines changed

package-lock.json

Lines changed: 11 additions & 11 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
"dependencies": {
2727
"@material-ui/core": "^1.5.0",
2828
"@material-ui/icons": "^1.1.0",
29-
"d3-graphviz": "^2.5.1",
29+
"d3-graphviz": "^2.6.0",
3030
"d3-scale-chromatic": "^1.3.0",
3131
"d3-selection": "^1.3.0",
3232
"d3-transition": "^1.1.1",

src/Graph.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,9 @@ class Graph extends React.Component {
131131
.height(height)
132132
.engine(engine)
133133
.fit(fit)
134+
.tweenPaths(this.props.tweenPaths)
135+
.tweenShapes(this.props.tweenShapes)
136+
.tweenPrecision(this.props.tweenPrecision)
134137
.dot(this.props.dotSrc, this.handleDotLayoutReady.bind(this))
135138
.render(this.handleRenderGraphReady.bind(this));
136139
}
@@ -150,7 +153,7 @@ class Graph extends React.Component {
150153
this.renderGraphReady = true;
151154
this.setZoomScale(1, true);
152155
this.graphviz
153-
.transition(() => d3_transition().duration(1000));
156+
.transition(() => d3_transition().duration(this.props.transitionDuration * 1000));
154157
this.props.onInitialized();
155158
}
156159
if (this.pendingUpdate) {

src/SettingsDialog.js

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@ import DialogContentText from '@material-ui/core/DialogContentText';
99
import DialogTitle from '@material-ui/core/DialogTitle';
1010
import FormGroup from '@material-ui/core/FormGroup';
1111
import FormControlLabel from '@material-ui/core/FormControlLabel';
12+
import FormLabel from '@material-ui/core/FormLabel';
13+
import RadioGroup from '@material-ui/core/RadioGroup';
14+
import Radio from '@material-ui/core/Radio';
1215
import Switch from '@material-ui/core/Switch';
1316
import Input from '@material-ui/core/Input';
1417
import InputAdornment from '@material-ui/core/InputAdornment';
@@ -44,6 +47,23 @@ const styles = theme => ({
4447
display: 'flex',
4548
justifyContent: 'space-between',
4649
},
50+
transitionDuration: {
51+
width: '7.6em',
52+
},
53+
group: {
54+
marginTop: theme.spacing.unit * 1,
55+
marginLeft: theme.spacing.unit * 0,
56+
},
57+
tweenPrecisionAbsoluteInput: {
58+
marginTop: theme.spacing.unit * 1,
59+
marginLeft: theme.spacing.unit * 1.5,
60+
width: '6.9em',
61+
},
62+
tweenPrecisionRelativeInput: {
63+
marginTop: theme.spacing.unit * 1,
64+
marginLeft: theme.spacing.unit * 1.5,
65+
width: '4.8em',
66+
},
4767
holdOffInput: {
4868
width: '7.6em',
4969
},
@@ -69,6 +89,34 @@ class SettingsDialog extends React.Component {
6989
this.props.onFitGraphSwitchChange(event.target.checked);
7090
};
7191

92+
handleTransitionDurationChange = (event) => {
93+
this.props.onTransitionDurationChange(event.target.value);
94+
};
95+
96+
handleTweenPathsSwitchChange = (event) => {
97+
this.props.onTweenPathsSwitchChange(event.target.checked);
98+
};
99+
100+
handleTweenShapesSwitchChange = (event) => {
101+
this.props.onTweenShapesSwitchChange(event.target.checked);
102+
};
103+
104+
handleTweenPrecisionChange = (event) => {
105+
let tweenPrecision = event.target.value;
106+
if (event.target.value === 'absolute' || tweenPrecision > 1) {
107+
tweenPrecision = Math.max(Math.ceil(tweenPrecision), 1);
108+
}
109+
this.props.onTweenPrecisionChange(tweenPrecision.toString() + (this.props.tweenPrecision.includes('%') ? '%': ''));
110+
};
111+
112+
handleTweenPrecisionIsRelativeRadioChange = (event) => {
113+
let tweenPrecision = +this.props.tweenPrecision.split('%')[0];
114+
if (event.target.value === 'absolute' || tweenPrecision > 1) {
115+
tweenPrecision = Math.max(Math.ceil(tweenPrecision), 1);
116+
}
117+
this.props.onTweenPrecisionChange(tweenPrecision.toString() + (event.target.value === 'relative' ? '%': ''));
118+
};
119+
72120
handleHoldOffChange = (event) => {
73121
this.props.onHoldOffChange(event.target.value);
74122
};
@@ -83,6 +131,13 @@ class SettingsDialog extends React.Component {
83131

84132
render() {
85133
const { classes } = this.props;
134+
const tweenPrecisionIsRelative = this.props.tweenPrecision.includes('%');
135+
const tweenPrecision = +this.props.tweenPrecision.split('%')[0];
136+
const tweenPrecisionType = tweenPrecisionIsRelative ? 'relative' : 'absolute';
137+
const tweenPrecisionUnit = tweenPrecisionIsRelative ? '%' : 'points';
138+
const enableTweenPrecisionSetting = this.props.tweenPaths || this.props.tweenShapes;
139+
const tweenPrecisionStep = (tweenPrecisionIsRelative && tweenPrecision <= 1) ? 0.1 : 1;
140+
const tweenPrecisionInputClass = tweenPrecisionIsRelative ? classes.tweenPrecisionRelativeInput : classes.tweenPrecisionAbsoluteInput;
86141
return (
87142
<div>
88143
<Dialog
@@ -140,6 +195,89 @@ class SettingsDialog extends React.Component {
140195
label="Fit graph to available area"
141196
/>
142197
</FormGroup>
198+
<FormControl
199+
className={classes.formControl}
200+
aria-describedby="transition-duration-helper-text"
201+
>
202+
<InputLabel shrink={true}>Transition duration</InputLabel>
203+
<Input
204+
className={classes.transitionDuration}
205+
id="transition-duration"
206+
type="number"
207+
value={this.props.transitionDuration}
208+
onChange={this.handleTransitionDurationChange}
209+
endAdornment={<InputAdornment position="end"> seconds</InputAdornment>}
210+
inputProps={{
211+
'aria-label': 'transitionDuration',
212+
min: 0.1,
213+
max: 99,
214+
step: 0.1,
215+
}}
216+
/>
217+
</FormControl>
218+
<FormGroup row>
219+
<FormControlLabel
220+
className={classes.formControlLabel}
221+
control={
222+
<Switch
223+
checked={this.props.tweenPaths}
224+
onChange={this.handleTweenPathsSwitchChange}
225+
/>
226+
}
227+
label="Enable path tweening during transitions"
228+
/>
229+
</FormGroup>
230+
<FormGroup row>
231+
<FormControlLabel
232+
className={classes.formControlLabel}
233+
control={
234+
<Switch
235+
checked={this.props.tweenShapes}
236+
onChange={this.handleTweenShapesSwitchChange}
237+
/>
238+
}
239+
label="Enable shape tweening during transitions"
240+
/>
241+
</FormGroup>
242+
<FormControl component="fieldset" className={classes.formControl}>
243+
<FormLabel component="legend">Tweening precision</FormLabel>
244+
<RadioGroup
245+
name="tweenPrecision"
246+
className={classes.group}
247+
value={tweenPrecisionType}
248+
onChange={this.handleTweenPrecisionIsRelativeRadioChange}
249+
>
250+
<FormControlLabel
251+
className={classes.formControlLabel}
252+
value="absolute"
253+
disabled={!enableTweenPrecisionSetting}
254+
control={<Radio />}
255+
label="Absolute"
256+
/>
257+
<FormControlLabel
258+
className={classes.formControlLabel}
259+
value="relative"
260+
disabled={!enableTweenPrecisionSetting}
261+
control={<Radio />}
262+
label="Relative"
263+
/>
264+
</RadioGroup>
265+
<Input
266+
className={tweenPrecisionInputClass}
267+
id="tween-precision"
268+
type="number"
269+
value={tweenPrecision}
270+
disabled={!enableTweenPrecisionSetting}
271+
onChange={this.handleTweenPrecisionChange}
272+
endAdornment={<InputAdornment position="end"> {tweenPrecisionUnit} </InputAdornment>}
273+
inputProps={{
274+
'aria-label': 'tweenPrecision',
275+
min: tweenPrecisionStep,
276+
max: tweenPrecisionIsRelative ? 100 : 999,
277+
step: tweenPrecisionStep,
278+
}}
279+
/>
280+
</FormControl>
143281
</DialogContent>
144282
<DialogTitle id="form-dialog-title">Text Editor</DialogTitle>
145283
<DialogContent classes={{root: classes.root}}>

src/pages/index.js

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ class Index extends React.Component {
5454
mouseOperationsDialogIsOpen: false,
5555
aboutDialogIsOpen: false,
5656
fitGraph : localStorage.getItem('fitGraph') === 'true',
57+
transitionDuration: localStorage.getItem('transitionDuration') || 1,
58+
tweenPaths : localStorage.getItem('tweenPaths') !== 'false',
59+
tweenShapes : localStorage.getItem('tweenShapes') !== 'false',
60+
tweenPrecision : localStorage.getItem('tweenPrecision') || '1%',
5761
engine : localStorage.getItem('engine') || 'dot',
5862
defaultNodeAttributes: JSON.parse(localStorage.getItem('defaultNodeAttributes')) || {},
5963
defaultEdgeAttributes: JSON.parse(localStorage.getItem('defaultEdgeAttributes')) || {},
@@ -180,6 +184,30 @@ class Index extends React.Component {
180184
});
181185
}
182186

187+
handleTransitionDurationChange = (transitionDuration) => {
188+
this.setPersistentState({
189+
transitionDuration: transitionDuration,
190+
});
191+
}
192+
193+
handleTweenPathsSwitchChange = (tweenPaths) => {
194+
this.setPersistentState({
195+
tweenPaths: tweenPaths,
196+
});
197+
}
198+
199+
handleTweenShapesSwitchChange = (tweenShapes) => {
200+
this.setPersistentState({
201+
tweenShapes: tweenShapes,
202+
});
203+
}
204+
205+
handleTweenPrecisionChange = (tweenPrecision) => {
206+
this.setPersistentState({
207+
tweenPrecision: tweenPrecision,
208+
});
209+
}
210+
183211
handleHoldOffChange = (holdOff) => {
184212
this.setPersistentState({
185213
holdOff: holdOff,
@@ -399,8 +427,16 @@ class Index extends React.Component {
399427
open={this.state.settingsDialogIsOpen}
400428
engine={this.state.engine}
401429
fitGraph={this.state.fitGraph}
430+
transitionDuration={this.state.transitionDuration}
431+
tweenPaths={this.state.tweenPaths}
432+
tweenShapes={this.state.tweenShapes}
433+
tweenPrecision={this.state.tweenPrecision}
402434
onEngineSelectChange={this.handleEngineSelectChange}
403435
onFitGraphSwitchChange={this.handleFitGraphSwitchChange}
436+
onTransitionDurationChange={this.handleTransitionDurationChange}
437+
onTweenPathsSwitchChange={this.handleTweenPathsSwitchChange}
438+
onTweenShapesSwitchChange={this.handleTweenShapesSwitchChange}
439+
onTweenPrecisionChange={this.handleTweenPrecisionChange}
404440
holdOff={this.state.holdOff}
405441
onHoldOffChange={this.handleHoldOffChange}
406442
fontSize={this.state.fontSize}
@@ -472,6 +508,10 @@ class Index extends React.Component {
472508
dotSrc={this.state.dotSrc}
473509
engine={this.state.engine}
474510
fit={this.state.fitGraph}
511+
transitionDuration={this.state.transitionDuration}
512+
tweenPaths={this.state.tweenPaths}
513+
tweenShapes={this.state.tweenShapes}
514+
tweenPrecision={this.state.tweenPrecision}
475515
defaultNodeAttributes={this.state.defaultNodeAttributes}
476516
defaultEdgeAttributes={this.state.defaultEdgeAttributes}
477517
onTextChange={this.handleTextChange}

0 commit comments

Comments
 (0)