Skip to content

Commit b34fa3c

Browse files
make active color follow button, make snap to nearest position
1 parent 526ec34 commit b34fa3c

File tree

3 files changed

+166
-68
lines changed

3 files changed

+166
-68
lines changed

demo/compiled.js

Lines changed: 131 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -20857,6 +20857,8 @@
2085720857

2085820858
var _react2 = _interopRequireDefault(_react);
2085920859

20860+
var _styles = __webpack_require__(173);
20861+
2086020862
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
2086120863

2086220864
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
@@ -20865,31 +20867,6 @@
2086520867

2086620868
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
2086720869

20868-
var grey = '#CCC';
20869-
var offBackground = {
20870-
top: 0,
20871-
boxShadow: 'inset 0 0 0px 1px ' + grey,
20872-
height: 0.6,
20873-
width: 1
20874-
};
20875-
20876-
var onBackground = {
20877-
top: 0,
20878-
height: 0.6
20879-
};
20880-
20881-
var buttonStyle = {
20882-
height: 0.6,
20883-
width: 0.6,
20884-
top: 0
20885-
};
20886-
20887-
var commonStyles = {
20888-
position: 'absolute',
20889-
borderRadius: 0.3,
20890-
transition: '0.1s ease-in-out'
20891-
};
20892-
2089320870
var OnOff = function (_React$Component) {
2089420871
_inherits(OnOff, _React$Component);
2089520872

@@ -20898,63 +20875,116 @@
2089820875

2089920876
var _this = _possibleConstructorReturn(this, (OnOff.__proto__ || Object.getPrototypeOf(OnOff)).call(this, props));
2090020877

20878+
var active = !!props.initialValue;
2090120879
_this.state = {
20902-
on: !!props.initialValue, // false if not set
20880+
on: active, // false if not set
2090320881
width: props.with || 100,
20882+
activeColorWidth: active ? 1 : 0.6,
20883+
buttonPosition: active ? 0.4 : 0,
2090420884
buttonColor: props.buttonColor || '#FFFFFF',
2090520885
passiveColor: props.passiveColor || '#FFFFFF',
2090620886
activeColor: props.activeColor || '#13BF11'
2090720887
};
20888+
2090820889
_this.handleChange = _this.handleChange.bind(_this);
2090920890
_this.onChange = props.onChange || function () {};
20891+
_this.onPointerDown = _this.onPointerDown.bind(_this);
20892+
_this.onDrag = _this.onDrag.bind(_this);
20893+
_this.onDragEnd = _this.onDragEnd.bind(_this);
2091020894
return _this;
2091120895
}
2091220896

2091320897
_createClass(OnOff, [{
2091420898
key: 'handleChange',
20915-
value: function handleChange() {
20899+
value: function handleChange(state) {
2091620900
var _this2 = this;
2091720901

20918-
this.setState({ on: !this.state.on }, function () {
20902+
var val = typeof state == 'boolean' ? state : !this.state.on;
20903+
this.setState({
20904+
on: val,
20905+
buttonPosition: val ? 0.4 : 0,
20906+
activeColorWidth: val ? 1 : 0.6
20907+
}, function () {
2091920908
return _this2.onChange(_this2.state.on);
2092020909
} // callback to parent Component
2092120910
);
2092220911
}
2092320912
}, {
20924-
key: 'setStyles',
20925-
value: function setStyles(obj) {
20926-
var styles = _extends({}, obj, commonStyles);
20927-
for (var key in styles) {
20928-
if (typeof styles[key] == 'number') styles[key] = this.state.width * styles[key] + 'px';
20929-
}
20930-
return styles;
20913+
key: 'getPointerCoords',
20914+
value: function getPointerCoords(e) {
20915+
return {
20916+
x: e.pageX || e.touches[0].pageX,
20917+
y: e.pageY || e.touches[0].pageY
20918+
};
20919+
}
20920+
}, {
20921+
key: 'onPointerDown',
20922+
value: function onPointerDown(e) {
20923+
this.touchDown = this.getPointerCoords(e.nativeEvent).x - parseInt(e.target.style.left, 10);
20924+
window.addEventListener('ontouchend' in window ? 'touchend' : 'mouseup', this.onDragEnd);
20925+
if ('onmouseout' in window) e.target.addEventListener('mouseout', this.onDragEnd);
20926+
}
20927+
}, {
20928+
key: 'onDrag',
20929+
value: function onDrag(e) {
20930+
e.preventDefault();
20931+
if (!this.touchDown) return;else this.dragged = true;
20932+
20933+
var positionNow = this.getPointerCoords(e.nativeEvent).x;
20934+
var diff = (positionNow - this.touchDown) / this.state.width;
20935+
// o.4 and 0.6 are related to proportions where 1 is the width
20936+
var max = 0.4;
20937+
if (diff < 0) diff = 0;else if (diff > max) diff = max;
20938+
var pos = 0.6 + diff;
20939+
20940+
this.setState({
20941+
buttonPosition: diff,
20942+
activeColorWidth: pos
20943+
});
20944+
}
20945+
}, {
20946+
key: 'onDragEnd',
20947+
value: function onDragEnd(e) {
20948+
window.removeEventListener('ontouchend' in window ? 'touchend' : 'mouseup', this.onDragEnd);
20949+
if ('onmouseout' in window) e.target.removeEventListener('mouseout', this.onDragEnd);
20950+
var newState = this.dragged ? this.state.buttonPosition > 0.2 : !this.state.on;
20951+
this.handleChange(newState);
20952+
this.touchDown = this.dragged = null;
2093120953
}
2093220954
}, {
2093320955
key: 'render',
2093420956
value: function render() {
2093520957
var on = this.state.on;
2093620958

20937-
var active = this.setStyles(_extends({}, onBackground, {
20938-
width: on ? 1 : 0.6,
20959+
var active = (0, _styles.setStyles)(_extends({}, _styles.onBackground, {
20960+
width: this.state.activeColorWidth,
2093920961
background: this.state.activeColor
20940-
}));
20941-
var passive = this.setStyles(_extends({}, offBackground, {
20942-
width: on ? 0.6 : 1,
20943-
left: on ? 0.4 : 0,
20962+
}), this.state.width);
20963+
20964+
var passive = (0, _styles.setStyles)(_extends({}, _styles.offBackground, {
2094420965
background: this.state.passiveColor
20945-
}));
20946-
var button = this.setStyles(_extends({}, buttonStyle, {
20947-
background: this.state.buttonColor,
20948-
left: on ? 0.4 : 0,
20949-
boxShadow: 'inset 0 0 0 1px ' + (on ? this.state.activeColor : grey) + ', 0 2px 4px ' + grey
20950-
}));
20966+
}), this.state.width);
20967+
20968+
var button = (0, _styles.setStyles)(_extends({}, _styles.buttonStyle, {
20969+
left: this.state.buttonPosition,
20970+
boxShadow: 'inset 0 0 0 1px ' + (on ? this.state.activeColor : _styles.grey) + ', 0 2px 4px ' + _styles.grey,
20971+
background: this.state.buttonColor
20972+
}), this.state.width);
2095120973

2095220974
return _react2.default.createElement(
2095320975
'div',
20954-
{ onClick: this.handleChange, style: { position: 'relative', height: 0.6 * this.state.width } },
20955-
_react2.default.createElement('div', { style: active }),
20976+
{
20977+
/*onClick={this.handleChange}*/
20978+
style: { position: 'relative', height: 0.6 * this.state.width }
20979+
},
2095620980
_react2.default.createElement('div', { style: passive }),
20957-
_react2.default.createElement('div', { style: button })
20981+
_react2.default.createElement('div', { style: active }),
20982+
_react2.default.createElement('div', {
20983+
onMouseMove: this.onDrag,
20984+
onTouchMove: this.onDrag,
20985+
onTouchStart: this.onPointerDown,
20986+
onMouseDown: this.onPointerDown,
20987+
style: button })
2095820988
);
2095920989
}
2096020990
}]);
@@ -21569,5 +21599,56 @@
2156921599
module.exports = onlyChild;
2157021600
/* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(3)))
2157121601

21602+
/***/ },
21603+
/* 173 */
21604+
/***/ function(module, exports) {
21605+
21606+
'use strict';
21607+
21608+
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; };
21609+
21610+
var grey = '#CCC';
21611+
21612+
var offBackground = {
21613+
top: 0,
21614+
boxShadow: 'inset 0 0 0px 1px ' + grey,
21615+
height: 0.6,
21616+
left: 0,
21617+
width: 1
21618+
};
21619+
21620+
var onBackground = {
21621+
top: 0,
21622+
height: 0.6
21623+
};
21624+
21625+
var buttonStyle = {
21626+
height: 0.6,
21627+
width: 0.6,
21628+
top: 0
21629+
};
21630+
21631+
var commonStyles = {
21632+
position: 'absolute',
21633+
borderRadius: 0.3,
21634+
transition: '0.1s ease-in-out'
21635+
};
21636+
21637+
var setStyles = function setStyles(obj, width) {
21638+
var styles = _extends({}, obj, commonStyles);
21639+
for (var key in styles) {
21640+
if (typeof styles[key] == 'number') styles[key] = width * styles[key] + 'px';
21641+
}
21642+
return styles;
21643+
};
21644+
21645+
module.exports = {
21646+
grey: grey,
21647+
offBackground: offBackground,
21648+
onBackground: onBackground,
21649+
buttonStyle: buttonStyle,
21650+
setStyles: setStyles
21651+
};
21652+
2157221653
/***/ }
2157321654
/******/ ]);

index.js

Lines changed: 33 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import {grey, offBackground, onBackground, buttonStyle, setStyles} from './style
55
export default class OnOff extends React.Component {
66
constructor(props) {
77
super(props);
8+
const active = !!props.initialValue;
89
this.state = {
9-
on: !!props.initialValue, // false if not set
10+
on: active, // false if not set
1011
width: props.with || 100,
12+
activeColorWidth: active ? 1 : 0.6,
13+
buttonPosition: active ? 0.4 : 0,
1114
buttonColor: props.buttonColor || '#FFFFFF',
1215
passiveColor: props.passiveColor || '#FFFFFF',
1316
activeColor: props.activeColor || '#13BF11'
@@ -20,9 +23,13 @@ export default class OnOff extends React.Component {
2023
this.onDragEnd = this.onDragEnd.bind(this);
2124
}
2225

23-
handleChange() {
24-
this.setState(
25-
{on: !this.state.on},
26+
handleChange(state) {
27+
const val = typeof state == 'boolean' ? state : !this.state.on;
28+
this.setState({
29+
on: val,
30+
buttonPosition: val ? 0.4 : 0,
31+
activeColorWidth: val ? 1 : 0.6
32+
},
2633
() => this.onChange(this.state.on) // callback to parent Component
2734
);
2835
}
@@ -36,56 +43,65 @@ export default class OnOff extends React.Component {
3643

3744
onPointerDown(e){
3845
this.touchDown = this.getPointerCoords(e.nativeEvent).x - parseInt(e.target.style.left, 10);
39-
window.addEventListener('ontouchend' in global ? 'touchend' : 'mouseup', this.onDragEnd);
46+
window.addEventListener('ontouchend' in window ? 'touchend' : 'mouseup', this.onDragEnd);
47+
if ('onmouseout' in window) e.target.addEventListener('mouseout', this.onDragEnd);
4048
}
4149

4250
onDrag(e){
43-
if (!this.touchDown) return;
4451
e.preventDefault();
52+
if (!this.touchDown) return;
53+
else this.dragged = true;
54+
4555
const positionNow = this.getPointerCoords(e.nativeEvent).x;
46-
let diff = positionNow - this.touchDown;
47-
const max = 0.6 * this.state.width;
56+
let diff = (positionNow - this.touchDown) / this.state.width;
57+
// o.4 and 0.6 are related to proportions where 1 is the width
58+
const max = 0.4;
4859
if (diff < 0) diff = 0;
4960
else if (diff > max) diff = max;
61+
const pos = 0.6 + diff;
5062

51-
e.target.style.left = diff + 'px';
63+
this.setState({
64+
buttonPosition: diff,
65+
activeColorWidth: pos
66+
});
5267
}
5368

5469
onDragEnd(e){
55-
window.removeEventListener('ontouchend' in global ? 'touchend' : 'mouseup', this.onDragEnd);
56-
this.touchDown = null;
70+
window.removeEventListener('ontouchend' in window ? 'touchend' : 'mouseup', this.onDragEnd);
71+
if ('onmouseout' in window) e.target.removeEventListener('mouseout', this.onDragEnd);
72+
const newState = this.dragged ? this.state.buttonPosition > 0.2 : !this.state.on;
73+
this.handleChange(newState);
74+
this.touchDown = this.dragged = null;
5775
}
5876

5977
render() {
6078
const on = this.state.on;
6179

6280
const active = setStyles({
6381
...onBackground,
64-
width: on ? 1 : 0.6,
82+
width: this.state.activeColorWidth,
6583
background: this.state.activeColor
6684
}, this.state.width);
6785

6886
const passive = setStyles({
6987
...offBackground,
70-
left: on ? 0.4 : 0,
71-
width: on ? 0.6 : 1,
7288
background: this.state.passiveColor
7389
}, this.state.width);
7490

7591
const button = setStyles({
7692
...buttonStyle,
77-
left: on ? 0.4 : 0,
93+
left: this.state.buttonPosition,
7894
boxShadow: `inset 0 0 0 1px ${on ? this.state.activeColor : grey}, 0 2px 4px ${grey}`,
7995
background: this.state.buttonColor
8096
}, this.state.width);
8197

8298
return (
8399
<div
84-
onClick={this.handleChange}
100+
/*onClick={this.handleChange}*/
85101
style={{position: 'relative', height: 0.6 * this.state.width}}
86102
>
87-
<div style={active}/>
88103
<div style={passive}/>
104+
<div style={active}/>
89105
<div
90106
onMouseMove={this.onDrag}
91107
onTouchMove={this.onDrag}

styles.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ const offBackground = {
55
top: 0,
66
boxShadow: `inset 0 0 0px 1px ${grey}`,
77
height: 0.6,
8-
width: 1
8+
left: 0,
9+
width: 1,
910
}
1011

1112
const onBackground = {

0 commit comments

Comments
 (0)