Skip to content

Commit 5f8bebe

Browse files
authored
Merge pull request #19 from react-component/0.12.0
bump 0.12.0-beta.0
2 parents d8ad64d + 184bde0 commit 5f8bebe

File tree

9 files changed

+260
-21
lines changed

9 files changed

+260
-21
lines changed

assets/switch.less

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
.switch {
2+
height: 400px;
3+
background: #CCC;
4+
& ul {
5+
display: block;
6+
width: 100%;
7+
overflow: hidden;
8+
& li {
9+
list-style: none;
10+
height: 100px;
11+
width: 100px;
12+
float: left;
13+
background: #000;
14+
&:nth-child(2n) {
15+
background: #ff6600;
16+
}
17+
}
18+
}
19+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
placeholder

examples/switch-enterForcedRePlay.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* eslint-disable no-console,react/no-multi-comp */
2+
import QueueAnim from 'rc-queue-anim';
3+
import React from 'react';
4+
import ReactDom from 'react-dom';
5+
import '../assets/switch.less';
6+
7+
class Demo extends React.Component {
8+
constructor() {
9+
super(...arguments);
10+
this.childrenKey = [
11+
{ key: 1 },
12+
{ key: 2 },
13+
{ key: 3 },
14+
{ key: 4 },
15+
{ key: 5 },
16+
{ key: 6 },
17+
];
18+
this.state = {
19+
childrenKey: this.childrenKey,
20+
};
21+
}
22+
23+
onEnter = () => {
24+
this.setState({
25+
childrenKey: null,
26+
});
27+
};
28+
29+
onLeave = () => {
30+
this.setState({
31+
childrenKey: this.childrenKey,
32+
});
33+
};
34+
35+
getChildren = () => {
36+
return (this.state.childrenKey || []).map(item => {
37+
return (<li key={item.key} />);
38+
});
39+
};
40+
41+
render() {
42+
const childrenToRender = this.getChildren();
43+
return (<div className="switch" onMouseEnter={this.onEnter} onMouseLeave={this.onLeave}>
44+
<h2>鼠标经过当前区域,再移出区域查看</h2>
45+
<QueueAnim component="ul" leaveReverse delay={[0, 300]} type="scale" enterForcedRePlay>
46+
{childrenToRender}
47+
</QueueAnim>
48+
<QueueAnim component="ul" leaveReverse delay={150} type="scale" enterForcedRePlay>
49+
{childrenToRender}
50+
</QueueAnim>
51+
<QueueAnim component="ul" leaveReverse delay={[300, 0]} type="scale" enterForcedRePlay>
52+
{childrenToRender}
53+
</QueueAnim>
54+
</div>);
55+
}
56+
}
57+
58+
ReactDom.render(<Demo />, document.getElementById('__react-content'));

examples/switch.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
placeholder

examples/switch.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/* eslint-disable no-console,react/no-multi-comp */
2+
import QueueAnim from 'rc-queue-anim';
3+
import React from 'react';
4+
import ReactDom from 'react-dom';
5+
import '../assets/switch.less';
6+
7+
class Demo extends React.Component {
8+
constructor() {
9+
super(...arguments);
10+
this.childrenKey = [
11+
{ key: 1 },
12+
{ key: 2 },
13+
{ key: 3 },
14+
{ key: 4 },
15+
{ key: 5 },
16+
{ key: 6 },
17+
];
18+
this.state = {
19+
childrenKey: this.childrenKey,
20+
};
21+
}
22+
23+
onEnter = () => {
24+
this.setState({
25+
childrenKey: null,
26+
});
27+
};
28+
29+
onLeave = () => {
30+
this.setState({
31+
childrenKey: this.childrenKey,
32+
});
33+
};
34+
35+
getChildren = () => {
36+
return (this.state.childrenKey || []).map(item => {
37+
return (<li key={item.key} />);
38+
});
39+
};
40+
41+
render() {
42+
const childrenToRender = this.getChildren();
43+
return (<div className="switch" onMouseEnter={this.onEnter} onMouseLeave={this.onLeave}>
44+
<h2>鼠标经过当前区域,再移出区域查看</h2>
45+
<QueueAnim component="ul" leaveReverse delay={[0, 300]} type="scale">
46+
{childrenToRender}
47+
</QueueAnim>
48+
<QueueAnim component="ul" leaveReverse delay={150} type="scale">
49+
{childrenToRender}
50+
</QueueAnim>
51+
<QueueAnim component="ul" leaveReverse delay={[300, 0]} type="scale">
52+
{childrenToRender}
53+
</QueueAnim>
54+
</div>);
55+
}
56+
}
57+
58+
ReactDom.render(<Demo />, document.getElementById('__react-content'));

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "rc-queue-anim",
3-
"version": "0.11.12",
3+
"version": "0.12.0-beta.0",
44
"description": "Queue animation component for react",
55
"keywords": [
66
"react",

src/QueueAnim.jsx

Lines changed: 72 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,8 @@ import {
9595
mergeChildren,
9696
transformArguments,
9797
getChildrenFromProps,
98+
assignChild,
99+
checkStyleName,
98100
} from './utils';
99101
import AnimTypes from './animTypes';
100102
const BackEase = {
@@ -105,6 +107,9 @@ const BackEase = {
105107

106108
const placeholderKeyPrefix = 'ant-queue-anim-placeholder-';
107109

110+
const noop = () => {
111+
};
112+
108113
class QueueAnim extends React.Component {
109114
constructor() {
110115
super(...arguments);
@@ -150,12 +155,27 @@ class QueueAnim extends React.Component {
150155
nextChildren
151156
);
152157

158+
const childrenShow = this.state.childrenShow;
159+
if (nextProps.enterForcedRePlay) {
160+
// 在出场没结束时,childrenShow 里的值将不会清除。再触发进场时, childrenShow 里的值是保留着的, 设置了 enterForcedRePlay 将重新播放进场。
161+
newChildren.forEach(item => {
162+
if (this.keysToLeave.indexOf(item.key) >= 0) {
163+
const node = findDOMNode(this.refs[item.key]);
164+
// 因为进场是用的间隔性进入,这里不做 stop 处理将会在这间隔里继续出场的动画。。
165+
velocity(node, 'stop');
166+
delete childrenShow[item.key];
167+
}
168+
});
169+
}
170+
171+
153172
this.keysToEnter = [];
154173
this.keysToLeave = [];
155174
this.keysAnimating = [];
156175

157176
// need render to avoid update
158177
this.setState({
178+
childrenShow,
159179
children: newChildren,
160180
});
161181

@@ -237,6 +257,47 @@ class QueueAnim extends React.Component {
237257
});
238258
}
239259

260+
getInitAnimType = (node, velocityConfig) => {
261+
/*
262+
* enterForcedRePlay 为 false 时:
263+
* 强行结束后,获取当前 dom 里是否有 data 里的 key 值,
264+
* 如果有,出场开始启动为 dom 里的值
265+
* 而不是 animTypes 里的初始值,如果是初始值将会跳动。
266+
*/
267+
const data = { ...assignChild(velocityConfig) };
268+
const transformsBase = velocity && velocity.prototype.constructor &&
269+
velocity.prototype.constructor.CSS.Lists.transformsBase || [];
270+
const setPropertyValue = velocity && velocity.prototype.constructor &&
271+
velocity.prototype.constructor.CSS.setPropertyValue || noop;
272+
const getUnitType = velocity && velocity.prototype.constructor &&
273+
velocity.prototype.constructor.CSS.Values.getUnitType || noop;
274+
const nodeStyle = node.style;
275+
Object.keys(data).forEach(dataKey => {
276+
let cssName = dataKey;
277+
if (transformsBase.indexOf(dataKey) >= 0) {
278+
cssName = 'transform';
279+
const transformString = nodeStyle[checkStyleName(cssName)];
280+
if (transformString && transformString !== 'none') {
281+
if (transformString.match(dataKey)) {
282+
const rep = new RegExp(`^.*${dataKey}\\(([^\\)]+?)\\).*`, 'i');
283+
const transformData = transformString.replace(rep, '$1');
284+
data[dataKey][1] = parseFloat(transformData);
285+
return;
286+
}
287+
} else {
288+
data[dataKey][1] = 0;
289+
}
290+
} else if (nodeStyle[dataKey] && parseFloat(nodeStyle[dataKey])) {
291+
data[dataKey][1] = parseFloat(nodeStyle[dataKey]);
292+
} else {
293+
data[dataKey][1] = 0;
294+
}
295+
// 先把初始值设进 style 里。免得跳动;把下面的设置放到这里。
296+
setPropertyValue(node, cssName, `${data[dataKey][1]}${getUnitType(dataKey)}`);
297+
});
298+
return data;
299+
};
300+
240301
performEnter(key, i) {
241302
const interval = transformArguments(this.props.interval, key, i)[0];
242303
const delay = transformArguments(this.props.delay, key, i)[0];
@@ -261,9 +322,13 @@ class QueueAnim extends React.Component {
261322
return;
262323
}
263324
const duration = transformArguments(this.props.duration, key, i)[0];
264-
node.style.visibility = 'hidden';
265325
velocity(node, 'stop');
266-
velocity(node, this.getVelocityEnterConfig(key, i), {
326+
const data = this.props.enterForcedRePlay ? this.getVelocityEnterConfig(key, i) :
327+
this.getInitAnimType(node, this.getVelocityEnterConfig(key, i));
328+
if (this.props.enterForcedRePlay) {
329+
node.style.visibility = 'hidden';
330+
}
331+
velocity(node, data, {
267332
duration,
268333
easing: this.getVelocityEasing(key, i)[0],
269334
visibility: 'visible',
@@ -284,7 +349,8 @@ class QueueAnim extends React.Component {
284349
const duration = transformArguments(this.props.duration, key, i)[1];
285350
const order = this.props.leaveReverse ? (this.keysToLeave.length - i - 1) : i;
286351
velocity(node, 'stop');
287-
velocity(node, this.getVelocityLeaveConfig(key, i), {
352+
const data = this.getInitAnimType(node, this.getVelocityLeaveConfig(key, i));
353+
velocity(node, data, {
288354
delay: interval * order + delay,
289355
duration,
290356
easing: this.getVelocityEasing(key, i)[1],
@@ -369,6 +435,7 @@ class QueueAnim extends React.Component {
369435
'ease',
370436
'leaveReverse',
371437
'animatingClassName',
438+
'enterForcedRePlay',
372439
].forEach(key => delete tagProps[key]);
373440
return createElement(this.props.component, { ...tagProps }, childrenToRender);
374441
}
@@ -391,6 +458,7 @@ QueueAnim.propTypes = {
391458
animConfig: funcOrObjectOrArray,
392459
ease: funcOrStringOrArray,
393460
leaveReverse: React.PropTypes.bool,
461+
enterForcedRePlay: React.PropTypes.bool,
394462
animatingClassName: React.PropTypes.array,
395463
};
396464

@@ -403,6 +471,7 @@ QueueAnim.defaultProps = {
403471
animConfig: null,
404472
ease: 'easeOutQuart',
405473
leaveReverse: false,
474+
enterForcedRePlay: false,
406475
animatingClassName: ['queue-anim-entering', 'queue-anim-leaving'],
407476
};
408477

src/utils.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,3 +83,28 @@ export function transformArguments(arg, key, i) {
8383
export function getChildrenFromProps(props) {
8484
return props && props.children;
8585
}
86+
87+
export function assignChild(data) {
88+
const obj = {};
89+
Object.keys(data).forEach(key => {
90+
if (Array.isArray(data[key])) {
91+
obj[key] = [].concat(data[key]);
92+
return;
93+
} else if (typeof data[key] === 'object') {
94+
obj[key] = { ...data[key] };
95+
return;
96+
}
97+
obj[key] = data[key];
98+
return;
99+
});
100+
return obj;
101+
}
102+
103+
export function checkStyleName(p) {
104+
const a = ['O', 'Moz', 'ms', 'Ms', 'Webkit'];
105+
if (p !== 'filter' && p in document.body.style) {
106+
return p;
107+
}
108+
const _p = p.charAt(0).toUpperCase() + p.substr(1);
109+
return `${(a.filter((key) => `${key}${_p}` in document.body.style)[0] || '')}${_p}`;
110+
}

0 commit comments

Comments
 (0)