Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Addition of wheel event and scroll buttons #71

Open
wants to merge 21 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
cb1ad1a
Fix empty ref scroll
Jul 17, 2019
ac8fb11
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
20e14b1
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
be4f1d2
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
0b62ffa
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
d2f6c00
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
4c10fbc
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
0f42ea6
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
6667c7f
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
834ce2d
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
8682e7b
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
6a80ab9
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
da7cc45
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
7ff0ef8
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
6998fa0
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
6bfd0fa
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 5, 2023
65d001c
[feature] Support for wheel event (mvieracanive)
maiavierasedicii Jan 6, 2023
7b317c5
[feature] Support for click event (mvieracanive)
maiavierasedicii Jan 6, 2023
abf2aaf
[feature] Support for click event (mvieracanive)
maiavierasedicii Jan 6, 2023
30ffa2d
[feature] Support for click event (mvieracanive)
maiavierasedicii Jan 6, 2023
23c4a3c
[feature] Support for click event (mvieracanive)
maiavierasedicii Jan 6, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 16 additions & 3 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
test
examples
.nyc_output
test/
examples/
.nyc_output/
coverage/
stories/
storybook-static/
lib/*.js
.github
.storybook/
.babelrc
.eslintrc
.eslintignore
.gitignore
.travis.yml
postcss.config.js
rollup.config.js
webpack.config.js
31 changes: 24 additions & 7 deletions lib/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@ type Props = {
showHeader: boolean,
showFooter: boolean,
showCaption: boolean,
showScrollButtons: boolean,
dateConfig: Object | Array<string>,
headerFormat: string,
confirmText: string,
cancelText: string,
onChange: Function,
onSelect: Function,
onCancel: Function,
themeClass?: String,
}

type State = {
Expand Down Expand Up @@ -165,7 +167,21 @@ class DatePicker extends Component<void, Props, State> {
* @return {Object} JSX对象
*/
render() {
const { min, max, theme, dateConfig, confirmText, cancelText, headerFormat, showHeader, showFooter, customHeader, showCaption } = this.props;
const {
min,
max,
theme,
dateConfig,
confirmText,
cancelText,
headerFormat,
showHeader,
showFooter,
customHeader,
showCaption,
showScrollButtons
} = this.props;

const value = this.state.value;
const themeClassName =
['default', 'dark', 'ios', 'android', 'android-dark'].indexOf(theme) === -1 ?
Expand All @@ -175,7 +191,7 @@ class DatePicker extends Component<void, Props, State> {

return (
<div
className={`datepicker ${themeClassName}`}>
className={`datepicker ${themeClassName} ${this.props.themeClass ? this.props.themeClass : ''}`}>
{showHeader && (
<div className="datepicker-header">
{customHeader || convertDate(value, headerFormat)}
Expand All @@ -198,16 +214,17 @@ class DatePicker extends Component<void, Props, State> {
step={item.step}
type={item.type}
format={item.format}
onSelect={this.handleDateSelect} />
onSelect={this.handleDateSelect}
showScrollButtons={showScrollButtons} />
))}
</div>
{showFooter && <div className="datepicker-navbar">
<a
className="datepicker-navbar-btn"
onClick={this.handleFinishBtnClick}>{confirmText}</a>
{showFooter && <div className='datepicker-navbar'>
<a
className="datepicker-navbar-btn"
onClick={this.props.onCancel}>{cancelText}</a>
<a
className='datepicker-navbar-btn'
onClick={this.handleFinishBtnClick}>{confirmText}</a>
</div>}
</div>
);
Expand Down
110 changes: 102 additions & 8 deletions lib/DatePickerItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ const DATE_HEIGHT = 40; // 每个日期的高度
const DATE_LENGTH = 10; // 日期的个数
const MIDDLE_INDEX = Math.floor(DATE_LENGTH / 2); // 日期数组中间值的索引
const MIDDLE_Y = - DATE_HEIGHT * MIDDLE_INDEX; // translateY值
const WHEEL_DELTA_Y = DATE_HEIGHT;
const WHEEL_STOP = 200;
const CLICK_OFFSET = 111;

const isUndefined = val => typeof val === 'undefined';
const isFunction = val => Object.prototype.toString.apply(val) === '[object Function]';
Expand All @@ -21,6 +24,7 @@ type Props = {
max: Object,
format: string | Array<*>,
step: number,
showScrollButtons: boolean,
onSelect: Function,
}

Expand All @@ -41,6 +45,11 @@ class DatePickerItem extends Component<void, Props, State> {
this.translateY = 0; // 容器偏移的距离
this.currentIndex = MIDDLE_INDEX; // 滑动中当前日期的索引
this.moveDateCount = 0; // 一次滑动移动了多少个时间
this._moveToTimer = null;
this.wheelMoveTimer = null;
this.wheelMoveStarted = false;
this.wheelYOffset = 0;
this.clickOffset = 0;

this.state = {
translateY: MIDDLE_Y,
Expand All @@ -52,6 +61,8 @@ class DatePickerItem extends Component<void, Props, State> {
this.handleContentMouseDown = this.handleContentMouseDown.bind(this);
this.handleContentMouseMove = this.handleContentMouseMove.bind(this);
this.handleContentMouseUp = this.handleContentMouseUp.bind(this);
this.handleContentWheelMove = this.handleContentWheelMove.bind(this);
this.handleContentClick = this.handleContentClick.bind(this);
}

componentWillMount() {
Expand All @@ -64,6 +75,7 @@ class DatePickerItem extends Component<void, Props, State> {
viewport.addEventListener('touchmove', this.handleContentTouch, false);
viewport.addEventListener('touchend', this.handleContentTouch, false);
viewport.addEventListener('mousedown', this.handleContentMouseDown, false);
viewport.addEventListener('wheel', this.handleContentWheelMove, false);
}

componentWillReceiveProps(nextProps) {
Expand Down Expand Up @@ -97,6 +109,9 @@ class DatePickerItem extends Component<void, Props, State> {
viewport.removeEventListener('touchmove', this.handleContentTouch, false);
viewport.removeEventListener('touchend', this.handleContentTouch, false);
viewport.removeEventListener('mousedown', this.handleContentMouseDown, false);
viewport.removeEventListener('wheel', this.handleContentWheelMove, false);

clearTimeout(this._moveToTimer);
}

_iniDates(date) {
Expand Down Expand Up @@ -160,26 +175,25 @@ class DatePickerItem extends Component<void, Props, State> {
this._updateDates(-1);
}

this._moveTo(this.refs.scroll, this.currentIndex);
this._moveTo(this.currentIndex);
}

/**
* 添加滑动动画
* @param {DOM} obj DOM对象
* @param {number} angle 角度
* @return {undefined}
*/
_moveTo(obj, currentIndex) {
_moveTo(currentIndex) {
this.animating = true;

addPrefixCss(obj, { transition: 'transform .2s ease-out' });
addPrefixCss(this.refs.scroll, { transition: 'transform .2s ease-out' });

this.setState({
translateY: -currentIndex * DATE_HEIGHT,
});

// NOTE: There is no transitionend, setTimeout is used instead.
setTimeout(() => {
this._moveToTimer = setTimeout(() => {
this.animating = false;
this.props.onSelect(this.state.dates[MIDDLE_INDEX]);
this._clearTransition(this.refs.scroll);
Expand All @@ -193,18 +207,30 @@ class DatePickerItem extends Component<void, Props, State> {
event.targetTouches[0].pageY :
event.pageY;

if (event.type === 'click') {
this.touchY = event.pageY + this.clickOffset;
}

this.translateY = this.state.translateY;
this.moveDateCount = 0;
}


handleMove(event) {
const touchY =
let touchY =
(!isUndefined(event.targetTouches) &&
!isUndefined(event.targetTouches[0])) ?
event.targetTouches[0].pageY :
event.pageY;

if (event.type === 'wheel') {
touchY = event.pageY + this.wheelYOffset;
}

if (event.type === 'click') {
touchY = event.pageY + this.clickOffset + (Math.sign(this.clickOffset) * -1 * WHEEL_DELTA_Y);
}

const dir = touchY - this.touchY;
const translateY = this.translateY + dir;
const direction = dir > 0 ? -1 : 1;
Expand All @@ -227,7 +253,16 @@ class DatePickerItem extends Component<void, Props, State> {
}

handleEnd(event) {
const touchY = event.pageY || event.changedTouches[0].pageY;
let touchY = event.pageY || (event.changedTouches && event.changedTouches[0].pageY);

if (event.type === 'wheel') {
touchY = event.pageY + this.wheelYOffset;
}

if (event.type === 'click') {
touchY = event.pageY + this.clickOffset + (Math.sign(this.clickOffset) * -1 * WHEEL_DELTA_Y);
}

const dir = touchY - this.touchY;
const direction = dir > 0 ? -1 : 1;
this._moveToNext(direction);
Expand Down Expand Up @@ -255,8 +290,53 @@ class DatePickerItem extends Component<void, Props, State> {
* @param {Object} event 事件对象
* @return {undefined}
*/
handleContentClick(event, direction) {
if (this.animating) return;
this.clickOffset = CLICK_OFFSET * direction;

this.handleStart(event);
this.handleMove(event);
this.handleEnd(event);
}

handleContentWheelMove(event) {
this.wheelYOffset += WHEEL_DELTA_Y * Math.sign(event.deltaY);

if (this.animating) return;

if (!this.wheelMoveStarted) {
this.handleStart(event);
this.wheelMoveStarted = true;
}

if (this.wheelMoveTimer) {
window.clearTimeout(this.wheelMoveTimer)
}

this.wheelMoveTimer = window.setTimeout(
() => this.handleContenWheelStop.bind(this)(event),
WHEEL_STOP
)

if (this.wheelMoveStarted) {
this.handleMove(event);
}
}

handleContenWheelStop(event) {
this.wheelYOffset -= WHEEL_DELTA_Y * Math.sign(event.deltaY)

if (this.wheelMoveStarted) {
this.wheelMoveStarted = false;
this.wheelYOffset = 0;

this.handleEnd(event);
}
}

handleContentMouseDown(event) {
if (this.animating) return;

this.handleStart(event);
document.addEventListener('mousemove', this.handleContentMouseMove);
document.addEventListener('mouseup', this.handleContentMouseUp);
Expand Down Expand Up @@ -308,10 +388,17 @@ class DatePickerItem extends Component<void, Props, State> {

return (
<div className="datepicker-col-1">
{this.props.showScrollButtons && (<div className="datepicker-scroll-btn">
<div
className="datepicker-scroll-btn-icon"
onClick = { (e) => this.handleContentClick(e, 1) } >
</div>
</div>)}
<div
ref={viewport => this.viewport = viewport} // eslint-disable-line
className="datepicker-viewport">
<div className="datepicker-wheel">
<div className='datepicker-wheel'>
<ul
ref="scroll"
className="datepicker-scroll"
Expand All @@ -320,6 +407,13 @@ class DatePickerItem extends Component<void, Props, State> {
</ul>
</div>
</div>
{this.props.showScrollButtons && (<div className="datepicker-scroll-btn">
<div
className="datepicker-scroll-btn-icon"
onClick = { (e) => this.handleContentClick(e, -1) } >
</div>
</div>)}
</div>
);
}
Expand Down
33 changes: 31 additions & 2 deletions lib/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@
}

.datepicker {
position: absolute;
position: relative;
left: 0;
bottom: 0;
width: 100%;
width: 300px;
z-index: 1;
font-size: 16px;
text-align: center;
Expand Down Expand Up @@ -83,6 +83,35 @@
font-size: 1.2em;
}

.datepicker-scroll-btn {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
margin: 0 .25em;
cursor: pointer;
}

.datepicker-scroll-btn-icon {
border-radius: 100%;
display: flex;
font-size: 12px;
color: darkgray;
align-items: center;
justify-content: center;
transition: background-color 1s;
height: 20px;
width: 20px;
}

.datepicker-scroll-btn-icon:active {
background: rgba(0,0,0,0.4);
}

.datepicker-scroll-btn-icon:hover {
color: rgb(17, 17, 17);
}

.datepicker-content {
display: flex;
padding: .5em .25em;
Expand Down
Loading