Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 842106e

Browse files
Improve current visualisation
Use a slider to adjust current speed Store current offsets in state, and calculate new offset from previous
1 parent 66e996e commit 842106e

File tree

20 files changed

+328
-78
lines changed

20 files changed

+328
-78
lines changed

‎public/styles.css‎

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,90 @@ body {
2929
button:active:hover {
3030
transform: translateY(1px);
3131
}
32+
33+
/* Slider */
34+
35+
input[type=range] {
36+
-webkit-appearance: none;
37+
width: 100%;
38+
margin: 10px 0;
39+
40+
background: transparent;
41+
border-color: transparent;
42+
color: transparent;
43+
}
44+
45+
input[type=range]::-webkit-slider-thumb {
46+
-webkit-appearance: none;
47+
}
48+
49+
input[type=range]:focus {
50+
outline: none;
51+
}
52+
53+
input[type=range]::-ms-track {
54+
width: 100%;
55+
cursor: pointer;
56+
background: transparent;
57+
border-color: transparent;
58+
color: transparent;
59+
}
60+
61+
input[type=range]::-webkit-slider-thumb {
62+
-webkit-appearance: none;
63+
border: 0px;
64+
height: 10px;
65+
width: 10px;
66+
border-radius: 50%;
67+
background: #7DF9FF;
68+
cursor: pointer;
69+
margin-top: -4px;
70+
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
71+
}
72+
73+
input[type=range]::-moz-range-thumb {
74+
border: 0px;
75+
height: 10px;
76+
width: 10px;
77+
border-radius: 50%;
78+
background: #7DF9FF;
79+
cursor: pointer;
80+
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
81+
}
82+
83+
input[type=range]::-ms-thumb {
84+
border: 0px;
85+
height: 10px;
86+
width: 10px;
87+
border-radius: 50%;
88+
background: #7DF9FF;
89+
cursor: pointer;
90+
box-shadow: 1px 1px 1px #000000, 0px 0px 1px #0d0d0d;
91+
}
92+
93+
input[type=range]::-webkit-slider-runnable-track {
94+
width: 100%;
95+
height: 2px;
96+
cursor: pointer;
97+
background: #555;
98+
border-radius: 1px;
99+
margin: 5px 0;
100+
}
101+
102+
input[type=range]::-moz-range-track {
103+
width: 100%;
104+
height: 2px;
105+
cursor: pointer;
106+
background: #555;
107+
border-radius: 1px;
108+
margin: 5px 0;
109+
}
110+
111+
input[type=range]::-ms-track {
112+
width: 100%;
113+
height: 2px;
114+
cursor: pointer;
115+
background: #555;
116+
border-radius: 1px;
117+
margin: 5px 0;
118+
}

‎src/redux/actions.js‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,3 +243,26 @@ export function changeComponentValue(id, value) {
243243
value
244244
};
245245
}
246+
247+
export const CHANGE_CURRENT_SPEED = 'CHANGE_CURRENT_SPEED';
248+
export function changeCurrentSpeed(speed) {
249+
return {
250+
type: CHANGE_CURRENT_SPEED,
251+
speed
252+
};
253+
}
254+
255+
export const UPDATE_CURRENT_OFFSETS = 'UPDATE_CURRENT_OFFSETS';
256+
export function updateCurrentOffsets(delta) {
257+
258+
return function(dispatch, getState) {
259+
const { currentSpeed, circuit } = getState();
260+
261+
dispatch({
262+
type: UPDATE_CURRENT_OFFSETS,
263+
delta,
264+
currentSpeed,
265+
componentStates: circuit.components
266+
});
267+
};
268+
}

‎src/redux/configureStore.js‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import rootReducer from './reducers';
66
import {
77
LOOP_BEGIN,
88
LOOP_UPDATE,
9+
UPDATE_CURRENT_OFFSETS,
910
ADDING_MOVED,
1011
MOVING_MOVED,
1112
MOUSE_MOVED,
@@ -18,6 +19,7 @@ const logger = createLogger({
1819
return __DEV__ && R.all(t => t !== action.type)([
1920
LOOP_BEGIN,
2021
LOOP_UPDATE,
22+
UPDATE_CURRENT_OFFSETS,
2123
ADDING_MOVED,
2224
MOVING_MOVED,
2325
MOUSE_MOVED,

‎src/redux/reducers.js‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import selected from './reducers/selectComponent';
88
import circuit from './reducers/mainLoop';
99
import showAddToaster from './reducers/toaster';
1010
import views from './reducers/views';
11+
import currentSpeed from './reducers/currentSpeed';
1112

1213
export default combineReducers({
1314
mode,
@@ -19,5 +20,6 @@ export default combineReducers({
1920

2021
// used to render canvas
2122
views,
22-
circuit
23+
circuit,
24+
currentSpeed
2325
});

‎src/redux/reducers/currentSpeed.js‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import {CHANGE_CURRENT_SPEED} from '../actions';
2+
3+
export default function currentSpeedReducer(speed = 50, action) {
4+
switch (action.type) {
5+
case CHANGE_CURRENT_SPEED:
6+
return action.speed;
7+
8+
default:
9+
return speed;
10+
}
11+
}

‎src/redux/reducers/mainLoop.js‎

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@ const INITIAL_STATE = {
5858

5959
staticEquation: null,
6060

61-
currentOffset: 0,
62-
6361
// TODO maxVoltage: 5,
6462
volts2RGB: createVolts2RGB(5),
6563

@@ -212,7 +210,6 @@ export default function mainLoopReducer(circuit = INITIAL_STATE, action) {
212210
volts2RGB,
213211
error: false,
214212
components: circuitState,
215-
currentOffset: circuit.currentOffset += action.delta,
216213
remainingDelta: timeToSimulate
217214
};
218215
}

‎src/redux/reducers/views.js‎

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,19 @@ import Components from '../../ui/diagram/components';
55
import DrawingUtils from '../../ui/utils/DrawingUtils.js';
66
import { snapToGrid } from '../../ui/diagram/Utils.js';
77
import { hoverFor } from '../../ui/diagram/boundingBox';
8+
import { CURRENT } from '../../ui/diagram/Constants';
89

910
import {
1011
ADDING_MOVED,
1112
MOVING_MOVED,
1213
DELETE_COMPONENT,
1314
CHANGE_COMPONENT_VALUE,
14-
SET_HOVERED_COMPONENT
15+
SET_HOVERED_COMPONENT,
16+
UPDATE_CURRENT_OFFSETS
1517
} from '../actions.js';
1618

19+
const STANDING_OFFSET = CURRENT.DOT_DISTANCE / 2;
20+
1721
const { diff } = DrawingUtils;
1822

1923
const moreThanOne = R.pipe(
@@ -71,6 +75,18 @@ function moveWholeComponent(views, action) {
7175
};
7276
}
7377

78+
/*
79+
* views = {
80+
* typeID - type of view e.g. Resistor
81+
* id - UID
82+
* value - e.g. 5Ω (TODO extend to support multi-value components)
83+
* dragPoints - real coordinates of the two drag points
84+
* connectors - coordinates of the connectors in the transformed canvas (used for rendering)
85+
* realConnectors - coordinates of the connectors in the real canvas
86+
*
87+
* currentOffsets - keeps track of current flow
88+
* }
89+
*/
7490
export default function viewsReducer(views = {}, action) {
7591
switch (action.type) {
7692
case ADDING_MOVED: {
@@ -96,11 +112,10 @@ export default function viewsReducer(views = {}, action) {
96112
typeID,
97113
id,
98114
value: Component.defaultValue,
99-
dragPoints, // real coordinates of the drag points
100-
101-
// TODO name these better
102-
connectors, // coordinates of the connectors in the transformed canvas - used for rendering
103-
realConnectors
115+
dragPoints,
116+
connectors,
117+
realConnectors,
118+
currentOffsets: R.repeat(STANDING_OFFSET, Component.numOfCurrentPaths)
104119
}
105120
};
106121
}
@@ -174,6 +189,39 @@ export default function viewsReducer(views = {}, action) {
174189
), views);
175190
}
176191

192+
case UPDATE_CURRENT_OFFSETS: {
193+
const {
194+
delta, // milliseconds
195+
currentSpeed,
196+
componentStates
197+
} = action;
198+
199+
// Shamelessly stolen from Paul Falstad. I really wish I knew where these numbers came from.
200+
const currentMultiplier = 1.7 * delta * Math.exp(currentSpeed / 3.5 - 14.2);
201+
202+
const updateOffsets = view => {
203+
const toOffset = ([current, prevOffset]) => {
204+
const extraOffset = (current * currentMultiplier) % (CURRENT.DOT_DISTANCE / 2);
205+
let offset = (prevOffset + extraOffset) % CURRENT.DOT_DISTANCE;
206+
if (offset < 0) {
207+
offset += CURRENT.DOT_DISTANCE;
208+
}
209+
return offset;
210+
};
211+
212+
const Type = Components[view.typeID];
213+
const componentState = componentStates[view.id];
214+
const currents = Type.getCurrents(view, componentState);
215+
const currentsAndOffsets = R.zip(currents, view.currentOffsets);
216+
217+
return {
218+
...view,
219+
currentOffsets: R.map(toOffset, currentsAndOffsets)
220+
};
221+
};
222+
return R.map(updateOffsets, views);
223+
}
224+
177225
default: return views;
178226
}
179227
}

‎src/ui/Updater.js‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@ function Updater(store) {
4040
}
4141
},
4242
circuitError: state.circuit.error,
43-
currentOffset: state.circuit.currentOffset,
4443
volts2RGB: state.circuit.volts2RGB
4544
}
4645
};

‎src/ui/diagram/components/Capacitor.js‎

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export default {
2020
typeID: BaseCapacitorModel.typeID,
2121

2222
numOfVoltages: 2,
23+
numOfCurrentPaths: 1,
2324
numOfConnectors: NUM_OF_CONNECTORS,
2425

2526
width: BOUNDING_BOX_WIDTH, // for label positioning
@@ -60,17 +61,21 @@ export default {
6061
ctx.stroke();
6162
},
6263

63-
renderCurrent: (props, state, renderBetween) => {
64-
const {
65-
connectors
66-
} = props;
67-
const [c1, c2] = connectors;
68-
64+
getCurrents: (props, state) => {
6965
const {
7066
currents = [0]
7167
} = state;
7268

73-
renderBetween(c1, {x: -CAPACITOR.GAP / 2, y: 0}, currents[0]);
74-
renderBetween({x: CAPACITOR.GAP / 2, y: 0}, c2, currents[0]);
69+
return currents;
70+
},
71+
72+
renderCurrent: (props, state, renderBetween) => {
73+
const {
74+
connectors: [c1, c2],
75+
currentOffsets: [offset]
76+
} = props;
77+
78+
renderBetween(c1, {x: -CAPACITOR.GAP / 2, y: 0}, offset);
79+
renderBetween({x: CAPACITOR.GAP / 2, y: 0}, c2, offset);
7580
}
7681
};

‎src/ui/diagram/components/CurrentSource.js‎

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default {
2323
typeID: BaseCurrentSourceModel.typeID,
2424

2525
numOfVoltages: 2,
26+
numOfCurrentPaths: 1,
2627
numOfConnectors: NUM_OF_CONNECTORS,
2728

2829
defaultValue: DEFAULT_CURRENT,
@@ -59,13 +60,20 @@ export default {
5960
ctx.stroke();
6061
},
6162

62-
renderCurrent: (props,state,renderBetween) => {
63+
getCurrents: (props) => {
6364
const {
64-
connectors,
6565
value: current = DEFAULT_CURRENT
6666
} = props;
67-
const [c1, c2] = connectors;
6867

69-
renderBetween(c1, c2, current);
68+
return [current];
69+
},
70+
71+
renderCurrent: (props, state, renderBetween) => {
72+
const {
73+
connectors: [c1, c2],
74+
currentOffsets: [offset]
75+
} = props;
76+
77+
renderBetween(c1, c2, offset);
7078
}
7179
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /