Merge pull request #435 from KgTong/feature-spin

Feature spin
This commit is contained in:
偏右 2015-10-31 00:33:06 +08:00
commit 9f6ce589d6
10 changed files with 299 additions and 18 deletions

View File

@ -0,0 +1,50 @@
# 基本用法
- order: 2
当有内容内嵌在Spin中时通过添加loading属性可以进入加载状态。
---
````jsx
import { Spin, Button } from 'antd';
let App = React.createClass({
getInitialState() {
return {
loading: false
};
},
enterLoading() {
this.setState({
loading: !this.state.loading
});
},
render() {
let childEl = (
<div className="inner-content">
<img src="https://t.alipayobjects.com/images/rmsweb/T1B9hfXcdvXXXXXXXX.svg" width="200px" height="200px" />
<div>我是一张图片</div>
</div>
);
let spinEl = this.state.loading ? (<Spin size="large"> { childEl } </Spin>) : childEl;
return (
<div>
{ spinEl }
<Button type="primary" onClick={this.enterLoading}>点击切换</Button>
</div>
);
}
});
ReactDOM.render(<App />, document.getElementById('components-spin-demo-full-page-load'));
````
<style>
.inner-content {
height: 300px;
padding-bottom: 60px;
padding-top: 60px;
text-align: center;
}
</style>

View File

@ -0,0 +1,30 @@
# 基本用法
- order: 0
作为页面元素使用。
---
````jsx
import { Spin } from 'antd';
ReactDOM.render(
<div>
<div className="example">
<Spin />
</div>
</div>, document.getElementById('components-spin-demo-page-element'));
````
<style>
.example {
text-align: center;
width: 100%;
background: rgba(0,0,0,0.05);
border-radius: 4px;
margin-bottom: 20px;
padding: 30px 50px;
margin: 20px 0;
}
</style>

70
components/spin/index.jsx Normal file
View File

@ -0,0 +1,70 @@
import React from 'react';
import { classSet } from 'rc-util';
import { isCssAnimationSupported } from 'css-animation';
const AntSpin = React.createClass({
getDefaultProps() {
return {
size: 'default'
};
},
propTypes: {
className: React.PropTypes.string,
size: React.PropTypes.oneOf(['small', 'default', 'large'])
},
isNestedPattern() {
return this.props.children ? true : false;
},
render() {
const prefix = 'ant-spin';
const nestedStatus = this.isNestedPattern();
const { className, size, ...others } = this.props;
const sizeCls = ({
'large': 'lg',
'small': 'sm'
})[size] || '';
let loadingClassName = classSet({
'ant-spin-nested-loading': nestedStatus
});
let spinClassName = classSet({
'ant-spin': true,
[className]: !!className
});
let spinEl;
if (!isCssAnimationSupported) {
// not support for animation, just use text instead
spinEl = <div className={ spinClassName }>加载中...</div>;
}else {
let spinWrapperClassName = classSet({
'ant-spin-wrapper': true,
[`${prefix}-${sizeCls}`]: sizeCls
});
spinEl = (<div className={ spinWrapperClassName }>
<div className={ spinClassName }>
<span className="ant-spin-dot ant-spin-dot-first" />
<span className="ant-spin-dot ant-spin-dot-second" />
<span className="ant-spin-dot ant-spin-dot-third" />
</div>
</div>);
}
let spinContainerEl = nestedStatus ?
<div className="ant-spin-container">
{ this.props.children }
</div> : null;
return (
<div {...this.props} className={ loadingClassName }>
{ spinEl }
{ spinContainerEl }
</div>
);
}
});
export default AntSpin;

19
components/spin/index.md Normal file
View File

@ -0,0 +1,19 @@
# Spin
- category: Components
- chinese: 加载动画
- type: 展示
---
用于页面和区块的loading状态。
## 何时使用
页面局部处于等待数据渲染时。
## API
| 参数 | 类型 | 默认值 |说明 |
|-----------|----------------|-------------|--------------|
| size | enum | default | spin组件中点的大小可选值为small default large

View File

@ -7,6 +7,7 @@ import FilterDropdown from './filterDropdown';
import Pagination from '../pagination';
import Icon from '../iconfont';
import objectAssign from 'object-assign';
import Spin from '../spin';
function noop() {
}
@ -569,9 +570,6 @@ let AntTable = React.createClass({
let columns = this.renderRowSelection();
let classString = this.props.className;
let expandIconAsCell = this.props.expandedRowRender && this.props.expandIconAsCell !== false;
if (this.state.loading && !this.isLocalDataSource()) {
classString += ' ant-table-loading';
}
if (this.props.size === 'small') {
classString += ' ant-table-small';
}
@ -591,7 +589,23 @@ let AntTable = React.createClass({
</div>;
emptyClass = ' ant-table-empty';
}
return <div className={'clearfix' + emptyClass}>
// spin holder
let spinEl;
let spinWrapperClass = '';
if (this.state.loading && !this.isLocalDataSource()) {
// if there is no pagination or no data, the height of spin should decrease by half of pagination
let paginationPatchClass = (this.hasPagination() && data && data.length !== 0)
? 'ant-table-with-pagination'
: 'ant-table-without-pagination';
let spinClass = `${paginationPatchClass} ant-table-spin-holder`;
spinEl = <div className={spinClass}>
<Spin />
</div>;
spinWrapperClass = ' ant-table-loading';
}
return <div className={'clearfix' + emptyClass + spinWrapperClass}>
<Table
{...this.props}
data={data}
@ -600,6 +614,7 @@ let AntTable = React.createClass({
expandIconAsCell={expandIconAsCell}
/>
{emptyText}
{spinEl}
{this.renderPagination()}
</div>;
}

View File

@ -53,6 +53,7 @@ const antd = {
Icon: require('./components/iconfont'),
Row: require('./components/layout').Row,
Col: require('./components/layout').Col,
Spin: require('./components/spin')
};
antd.version = require('./package.json').version;

View File

@ -34,3 +34,4 @@
@import "affix";
@import "badge";
@import "timeline";
@import "spin";

View File

@ -0,0 +1,88 @@
@import "../mixins/index";
@spin-prefix-cls: ant-spin;
// root of component
// ------------------------------
.@{spin-prefix-cls} {
color: @primary-color;
display: inline-block;
font-size: 1em;
text-align: center;
vertical-align: middle;
&-nested-loading {
position: relative;
}
&-wrapper {
font-size: @spin-dot-size;
}
&-nested-loading .ant-spin {
position: absolute;
top: 50%;
left: 50%;
margin-top: -0.75em;
margin-left: -2.5em;
z-index: 4;
}
&-nested-loading > &-container {
-webkit-filter: blur(10px); /* Chrome, Opera */
-moz-filter: blur(10px);
-ms-filter: blur(10px);
filter: blur(10px);
filter: progid:DXImageTransform.Microsoft.Blur(PixelRadius=10, MakeShadow=false); /* IE6~IE9 */
z-index: 19;
}
// dots
// ------------------------------
&-dot {
.animation(antSpinPulse 1s infinite ease-in-out);
.square(1em);
border-radius: 50%;
display: inline-block;
vertical-align: middle;
background-color: @primary-color;
}
&-dot-second {
.animation-delay(200ms);
margin-left: 1em;
}
&-dot-third {
.animation-delay(400ms);
margin-left: 1em;
}
// Sizes
// ------------------------------
// small
&-nested-loading > &-sm, &-not-nested-loading > &-sm {
font-size: @spin-dot-size-sm;
}
// large
&-nested-loading > &-lg, &-not-nested-loading > &-lg {
font-size: @spin-dot-size-lg;
}
}
// pulse
@keyframes antSpinPulse {
0%, 80%, 100% { opacity: 0; }
40% { opacity: 1; }
}
@media all and (-ms-high-contrast: none), (-ms-high-contrast: active) {
/* IE10+*/
.ant-spin-nested-loading > .ant-spin-container {
background: #fff;
opacity: 0.5;
}
}

View File

@ -82,23 +82,22 @@
&-loading {
position: relative;
.@{table-prefix-cls}-body {
opacity: 0.42;
background: #fff;
opacity: 0.5;
}
&:after {
position: absolute;
display: inline-block;
.animation(loadingCircle 1.5s infinite linear);
content: "\e610";
top: 50%;
left: 50%;
margin-top: -10px;
margin-left: -10px;
font-family: anticon;
width: 20px;
.@{table-prefix-cls}-spin-holder {
height: 20px;
line-height: 20px;
font-size: 20px;
color: @primary-color;
left: 50%;
top: 50%;
margin-left: -30px;
position: absolute;
}
.@{table-prefix-cls}-with-pagination {
margin-top: -20px;
}
.@{table-prefix-cls}-without-pagination {
margin-top: 10px;
}
}

View File

@ -138,3 +138,11 @@
@form-item-margin-bottom : 24px;
@overlay-shadow : 0 0 4px rgba(0, 0, 0, 0.17);
// Spin
// --------------------------------
@spin-dot-default : #999;
@spin-dot-size : 8px;
@spin-dot-size-sm : @spin-dot-size / 2;
@spin-dot-size-lg : @spin-dot-size * 2;