diff --git a/site/docs/en-US/anchor-smooth.md b/site/docs/en-US/anchor-smooth.md new file mode 100644 index 000000000..842eca806 --- /dev/null +++ b/site/docs/en-US/anchor-smooth.md @@ -0,0 +1,86 @@ +## AnchorSmooth + +A label slide to anchor point. + +### Basic usage + +Similar to the use of a tag, the attribute targetId is used to indicate the anchor that you want to reach. + +::: demo The AnchorSmooth component provides `targetId` attributes to point to ID elements that exist in the page and must have values. If the child element does not exist, `targetId` is used as the child element. +```js +render() { + return ( +
+
Here is the anchor#anchor0
+
+ + + Slide to anchor#anchor1 + +
+
+ ) +} +``` +::: + +### callback + +The attribute `onFinish` can bind a callback function and execute the callback function after reaching the anchor point. + +::: demo In the AnchorSmooth component, you can set the `onFinish` callback function that completes the sliding, and then call the `onFinish` function when it reaches the anchor. +```js +render() { + return ( +
+
+ Here is the anchor#anchor1 +
+ console.log("Arrive at anchor2")}> + Go to the anchor with ID anchor2 and execute the callback function + +
+ ) +} +``` +::: + +### set title + +The` title` property tells the user the anchor to go when the mouse moves in. + +::: demo Use the `title` attribute to describe an anchor. +```js +render() { + return ( +
+
+ Here is the anchor#anchor2 +
+ console.log("Arrive at anchor0")}> + To the anchor with ID anchor0, containing title + +
+ ) +} +``` +::: + +### Attributes + +| Attribute | Description | Type | Accepted Values | Default | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| **targetId** | Anchor target **REQUIRED** | string | — | — | +| title | title | string | — | — | + +### Events + +| Event Name | Description | Parameters | +|---------- |-------- |---------- | +| onFinish | fires when anchor is arrived | — | + diff --git a/site/docs/en-US/go-top.md b/site/docs/en-US/go-top.md new file mode 100644 index 000000000..ccc7b5b02 --- /dev/null +++ b/site/docs/en-US/go-top.md @@ -0,0 +1,120 @@ +## GoTop + +In a long page, you can go back to the top of the page by clicking on the button from the bottom to the top. + +### Basic usage + +Usually the top-back button appears in the lower right corner of the page, so it is recommended to modify the `right`, `bottom` attributes for positioning; if there are special needs, you can also modify the `left`, `top` attributes. + +::: demo In the GoTop component, you can modify the `right` and `bottom` attributes with the default values of right: 50px and bottom: 50px. +```js +render() { + return ( +
+

Basic usage: The first button in the lower right corner

+ +
+ ) +} +``` +::: + +### Property `showheight` + +Usually the top button will not appear when the rolling distance is 0. We can define the height of the scrollbar when the button appears by the attribute `showheight`, with the default value of 300, per unit px. If the scroll distance is greater than 300, the display button will fade in; if the scroll distance is less than 300, the hidden button will fade out. + +::: demo In the GoTop component, you can modify the showheight property to specify the scroll distance of the scrollbar, default value: 300; type: number. + +```js +render() { + return ( +
+

+ A button appears when the scroll distance is 200 px: + the second button in the lower right corner +

+ +
+ ) +} +``` + +::: + +### With icon + +By default, the `el-icon-caret-top` in elementUI can be used to replace the default icon by setting sub-elements. + +::: demo By setting the` children` attribute to display GoTop's icon, you can more effectively show the user your display intentions. +```js +render() { + return ( +
+

With icon:The third button in the lower right corner

+ + + +
+ ) +} +``` +::: + +### Sliding time and callback function + +Customize the time used to complete the sliding, attribute: `time`, default value: 300, unit: Ms. + +::: demo In the GoTop component, you can set the `time` needed to complete the sliding and call an `onFinish` callback function when you reach the anchor. + +```js +render() { + return ( +
+

+ Custom sliding time and callback function: + The fourth button in the lower right corner +

+ console.log("go to top")}/> +
+ ) +} +``` + +::: + +### Set title + +The` title` property tells the user the anchor to go when the mouse moves in. + +::: demo Use the `title` attribute to describe an anchor. + +```js +render() { + return ( +
+

Title: the fifth button in the lower right corner

+ +
+ ) +} +``` + +::: + +### Attributes +| Attribute | Description | Type | Accepted Values | Default | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| showheight | Scrollbar Scroll Distance Threshold, Unit PX | number | — | 300 | +| time | The time required to reach the top, unit MS | number | — | 300 | +| title | title | string | — | — | +| right | Distance to the rightof the page | string | — | 50px | +| bottom | Distance to the bottom of the page | string | — | 50px | +| top | Distance to the top of the page | string | — | — | +| left | Distance to the left of the page | string | — | — | + +### Events + +| Event Name | Description | Parameters | +| ---------- | ---------------------------- | ---------- | +| onFinish | fires when anchor is arrived | — | \ No newline at end of file diff --git a/site/docs/zh-CN/anchor-smooth.md b/site/docs/zh-CN/anchor-smooth.md new file mode 100644 index 000000000..c4494b998 --- /dev/null +++ b/site/docs/zh-CN/anchor-smooth.md @@ -0,0 +1,85 @@ +## AnchorSmooth 滑向锚点 + +用于a标签滑向锚点。 + +### 基本用法 + +和a标签用法类似,使用属性`targetId`表明想到达的锚点。 + +::: demo AnchorSmooth 组件提供`targetId`属性指向页面中**存在id元素**,必须值。若子元素不存在,则使用`targetId`当作子元素。 +```js +render() { + return ( +
+
这里是锚点#anchor0
+
+ + + 滑动到锚点anchor1 + +
+
+ ) +} +``` +::: + +### 回调函数 + +属性`onFinish`可在绑定一个回调函数,在到达锚点后执行回调函数。 + +::: demo 在 AnchorSmooth 组件中,你可以设置完成滑动完成的回调函数`onFinish`,到达锚点之后会调用`onFinish`函数。 +```js +render() { + return ( +
+
+ 这里是锚点#anchor1 +
+ console.log("Arrive at anchor2")}> + 到id为anchor2的锚点,并执行回调函数 + +
+ ) +} +``` +::: + +### 设置标题 + +`title`属性,鼠标移入时告诉用户即将去的锚点。 + +::: demo 使用`title`属性来描述一个锚点。 +```js +render() { + return ( +
+
+ 这里是锚点#anchor2 +
+ console.log("Arrive at anchor0")}> + 到id为anchor0的锚点,包含title + +
+ ) +} +``` +::: + +### Attributes + +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| **targetId** | 锚点目标,页面中需要有对应id,**必选参数** | string | — | — | +| title | 辅助性文字 | string | — | — | + +### Events + +| 事件名称 | 说明 | 回调参数 | +|---------- |-------- |---------- | +| onFinish | 锚点到达时的回调函数 | — | diff --git a/site/docs/zh-CN/go-top.md b/site/docs/zh-CN/go-top.md new file mode 100644 index 000000000..22e2d94ae --- /dev/null +++ b/site/docs/zh-CN/go-top.md @@ -0,0 +1,114 @@ +## GoTop 回顶部 + +长页面中从底部回到顶部的按钮,点击可以回到页面顶部。 + +### 基本用法 + +通常回顶部按钮出现在页面的右下角,因此建议修改`right`,`bottom`属性进行定位;若有特殊需求,也可以修改`left` ,`top`属性。 + +::: demo 在 GoTop组件中,你可以修改`right`,`bottom`属性,默认值为right:50px;bottom:50px;。 +```js +render() { + return ( +
+

基本用法:右下角按钮第一个

+ +
+ ) +} +``` +::: + +### 出现时机 + +一般回顶部按钮,不会在滚动距离为0时出现。我们可以通过属性`showheight` 来定义按钮出现时滚动条的高度,默认值为300,单位px。滚动距离大于300,会淡入显示按钮;小于300,会淡出隐藏按钮。 + +::: demo 在 GoTop组件中,你可以修改`showheight`属性,指定滚动条的滚动距离,默认值:300;类型:number。 + +```js +render() { + return ( +
+

在滚动距离为200px时出现按钮:右下角按钮第二个

+ +
+ ) +} +``` + +::: + +### 替换 icon + +GoTop 组件中,默认使用elementUI中的el-icon-caret-top,可以通过设置子元素的方式,替换默认icon图标。 + +::: demo 通过设置`children`属性来显示 GoTop 的 icon,这能更有效地向用户展示你的显示意图。 +```js +render() { + return ( +
+

替换 icon:右下角按钮第三个

+ + + +
+ ) +} +``` +::: + +### 滑动时间和回调函数 + +自定义完成滑动所用的时间,属性:` time`,默认值: 300,单位: ms。 + +::: demo 在 GoTop 组件中,你可以设置完成滑动所用的时间`time`,到达锚点之后会调用一个的`onFinish`的回调函数。`time`属性决定完成滑动所用的时间,接受`number`,默认为300。 + +```js +render() { + return ( +
+

自定义滑动时间和回调函数:右下角按钮第四个

+ console.log("go to top")}/> +
+ ) +} +``` + +::: + +### title + +包含标题,鼠标移入时告诉用户即将去的锚点。 + +::: demo 使用`title`属性来描述一个锚点。 + +```js +render() { + return ( +
+

title:右下角按钮第五个

+ +
+ ) +} +``` + +::: + +### Attributes +| 参数 | 说明 | 类型 | 可选值 | 默认值 | +|---------- |-------------- |---------- |-------------------------------- |-------- | +| showheight | 滚动条滚动距离阈值,单位px | number | — | 300 | +| time | 到达描点所需要的时间,单位ms | number | — | 300 | +| title | title | string | — | — | +| right | 到页面右边的距离 | string | — | 50px | +| bottom | 到页面底端的距离 | string | — | 50px | +| top | 到页面顶端的距离 | string | — | — | +| left | 到页面左边的距离 | string | — | — | + +### Events + +| 事件名称 | 说明 | 回调参数 | +| -------- | -------------------------- | -------- | +| onFinish | 滚动条到达顶部时的回调函数 | — | \ No newline at end of file diff --git a/site/locales/en-US.js b/site/locales/en-US.js index 37bfc3dd0..9bfa7a186 100644 --- a/site/locales/en-US.js +++ b/site/locales/en-US.js @@ -45,7 +45,9 @@ module.exports = { 'popover': 'Popover', 'card': 'Card', 'carousel': 'Carousel', - 'collapse': 'Collapse' + 'collapse': 'Collapse', + 'anchor-smooth':'AnchorSmooth', + 'go-top':'GoTop' }, misc: { 'guide': 'Guide', diff --git a/site/locales/zh-CN.js b/site/locales/zh-CN.js index 4bc9b2b32..4feac10dc 100644 --- a/site/locales/zh-CN.js +++ b/site/locales/zh-CN.js @@ -45,7 +45,9 @@ module.exports = { 'popover': 'Popover 弹出框', 'card': 'Card 卡片', 'carousel': 'Carousel 走马灯', - 'collapse': 'Collapse 折叠面板' + 'collapse': 'Collapse 折叠面板', + 'anchor-smooth':'AnchorSmooth 滑向锚点', + 'go-top':'GoTop 回顶部' }, misc: { 'guide': '指南', diff --git a/site/pages/anchor-smooth/index.jsx b/site/pages/anchor-smooth/index.jsx new file mode 100644 index 000000000..5794c1b1f --- /dev/null +++ b/site/pages/anchor-smooth/index.jsx @@ -0,0 +1,9 @@ +import Markdown from '../../../libs/markdown'; + +import './style.scss'; + +export default class AnchorSmooth extends Markdown { + document(locale) { + return require(`../../docs/${locale}/anchor-smooth.md`); + } +} diff --git a/site/pages/anchor-smooth/style.scss b/site/pages/anchor-smooth/style.scss new file mode 100644 index 000000000..9a9c0b820 --- /dev/null +++ b/site/pages/anchor-smooth/style.scss @@ -0,0 +1,13 @@ +.demo-anchorsmooth{ + + .anchor-point{ + color: #20a0ff; + height: 50px; + line-height: 50px; + } + + .anchor-group a{ + margin-right: 100px; + } + +} diff --git a/site/pages/go-top/index.jsx b/site/pages/go-top/index.jsx new file mode 100644 index 000000000..8e0c27a03 --- /dev/null +++ b/site/pages/go-top/index.jsx @@ -0,0 +1,9 @@ +import Markdown from '../../../libs/markdown'; + +import './style.scss'; + +export default class GoTop extends Markdown { + document(locale) { + return require(`../../docs/${locale}/go-top.md`); + } +} diff --git a/site/pages/go-top/style.scss b/site/pages/go-top/style.scss new file mode 100644 index 000000000..ea3b29b46 --- /dev/null +++ b/site/pages/go-top/style.scss @@ -0,0 +1,5 @@ +.demo-gotop { + h3{ + color: #20a0ff; + } +} diff --git a/site/pages/index.jsx b/site/pages/index.jsx index 5bfb46530..7768dc7b6 100644 --- a/site/pages/index.jsx +++ b/site/pages/index.jsx @@ -58,7 +58,9 @@ export default { 'popover': require('./popover'), 'card': require('./card'), 'carousel': require('./carousel'), - 'collapse': require('./collapse') + 'collapse': require('./collapse'), + 'anchor-smooth':require('./anchor-smooth'), + 'go-top':require('./go-top') } } } diff --git a/site/pages/input/custom-item.jsx b/site/pages/input/custom-item.jsx index 436752e58..b2967a42b 100644 --- a/site/pages/input/custom-item.jsx +++ b/site/pages/input/custom-item.jsx @@ -16,4 +16,4 @@ CustomItem.propTypes = { item: PropTypes.object }; -module.exports = CustomItem; +export default CustomItem; diff --git a/src/anchor/AnchorSmooth.jsx b/src/anchor/AnchorSmooth.jsx new file mode 100644 index 000000000..32c482627 --- /dev/null +++ b/src/anchor/AnchorSmooth.jsx @@ -0,0 +1,93 @@ +/* @flow */ + +import React from 'react'; +import {Component, PropTypes} from '../../libs'; + +export function getScrollTop() { + let html = document.documentElement || {scrollTop : 0}; + let body = document.body || {scrollTop : 0}; + return window.pageYOffset || + html ? html.scrollTop : + body ? body.scrollTop : 0; +} + +function goTarget(targetTop, time = 300, callback) { + let interval = 10; + time = Math.max(time, 100); + let initTop = getScrollTop(); + let total = Math.ceil(time / interval); + let speed = (targetTop - initTop) / total; + + if (speed === 0) { + return; + } + + let count = 1; + let timer = setInterval(goMove, interval); + + function goMove() { + if (count >= total) { + window.scrollTo(0, targetTop); + clearInterval(timer); + callback && callback(); + return; + } + window.scrollTo(0, speed * count + initTop); + count++; + } + +} + +export default class AnchorSmooth extends Component { + + onClick(e: SyntheticEvent): void{ + e.preventDefault(); + let targetDom = document.getElementById(this.props.targetId); + if (targetDom && targetDom.scrollIntoView) { + targetDom.scrollIntoView({ + behavior: 'smooth', + block: 'start', + inline: 'nearest' + }); + this.props.onFinish && this.props.onFinish(); + } else { + let targetTop = targetDom ? targetDom.offsetTop : 0; + goTarget(targetTop, this.props.time, this.props.onFinish); + } + } + + + // shouldComponentUpdate(nextProps) { + // const propsKeys = Object.keys(this.props); + // const nextPropsKeys = Object.keys(nextProps); + // + // if (propsKeys.length !== nextPropsKeys.length) { + // return true; + // } + // for (const key of propsKeys) { + // if (this.props[key] !== nextProps[key]) { + // return true; + // } + // } + // return false; + // } + + render() { + const {targetId, children, ...other} = this.props; + return ( + {children || targetId} + ) + } +} + +AnchorSmooth.propTypes = { + targetId: PropTypes.string, + time: PropTypes.number, + onFinish: PropTypes.func +}; + +AnchorSmooth.defaultProps = { + time: 300 +}; + diff --git a/src/anchor/GoTop.jsx b/src/anchor/GoTop.jsx new file mode 100644 index 000000000..4bf6d5f84 --- /dev/null +++ b/src/anchor/GoTop.jsx @@ -0,0 +1,65 @@ +/* @flow */ + +import React from 'react'; +import {Component, PropTypes} from '../../libs'; +import AnchorSmooth, {getScrollTop} from './AnchorSmooth'; +// import './style.css'; + +export default class GoTop extends Component { + + constructor() { + super(...arguments); + this.state = {show: false}; + this.$showAnchor = this.showAnchor.bind(this); + } + + showAnchor() { + let scrollY = getScrollTop(); + let show = scrollY >= this.props.showheight; + if (this.state.show !== show) { + this.setState({ + show + }); + } + } + + componentDidMount() { + this.$showAnchor(); + window.addEventListener("scroll", this.$showAnchor) + } + + componentWillUnmount() { + window.removeEventListener("scroll", this.$showAnchor); + } + + render() { + const {children, bottom, right, top, left, ...other} = this.props; + return ( +
+ + {children || } + +
+ ) + } +} + +GoTop.propTypes = { + showheight: PropTypes.number, + bottom: PropTypes.string, + top: PropTypes.string, + left: PropTypes.string, + right: PropTypes.string +}; + +GoTop.defaultProps = { + showheight: 300 +}; diff --git a/src/anchor/index.js b/src/anchor/index.js new file mode 100644 index 000000000..44ce0f1fa --- /dev/null +++ b/src/anchor/index.js @@ -0,0 +1,4 @@ +import AnchorSmooth from './AnchorSmooth'; +import GoTop from './GoTop'; + +export {AnchorSmooth,GoTop}; \ No newline at end of file diff --git a/src/anchor/style.css b/src/anchor/style.css new file mode 100644 index 000000000..d10558340 --- /dev/null +++ b/src/anchor/style.css @@ -0,0 +1,28 @@ +.el-anchor__top-wrapper { + position: fixed; + bottom: 50px; + right: 50px; + z-index: 99; + transition: opacity 0.2s linear 0s, visibility 0s linear 0.2s; +} + +.el-anchor__top { + border-radius: 50%; + width: 50px; + height: 50px; + background-color: #58b7ff; + display: block; + text-align: center; + line-height: 50px; + opacity: 0.4; + transition: opacity 0.3s linear 0s; +} + +.el-anchor__top:hover { + opacity: 1; +} + +.el-anchor__top i { + color: #ffffff; + font-size: 22px; +} \ No newline at end of file diff --git a/src/index.js b/src/index.js index fdbac9308..a1b0a46f5 100644 --- a/src/index.js +++ b/src/index.js @@ -1,6 +1,7 @@ export { default as i18n } from './locale'; export { default as Alert } from './alert'; +export { AnchorSmooth, GoTop} from './anchor'; export { default as Button } from './button'; export { default as Card } from './card'; export { default as Layout } from './layout';