diff --git a/demo/documentation/components/affix/enUS/basic.md b/demo/documentation/components/affix/enUS/basic.md index fdc08617f..c86028080 100644 --- a/demo/documentation/components/affix/enUS/basic.md +++ b/demo/documentation/components/affix/enUS/basic.md @@ -3,10 +3,16 @@
- Top 50px + + + Top 50px + + + Bottom 60px + + -
``` @@ -17,7 +23,6 @@ background-color: rgba(128, 128, 128, .3); border-radius: 6px; overflow: auto; - position: relative; } .padding { diff --git a/demo/documentation/components/affix/enUS/index.md b/demo/documentation/components/affix/enUS/index.md index 439a90a95..dc66cb1f3 100644 --- a/demo/documentation/components/affix/enUS/index.md +++ b/demo/documentation/components/affix/enUS/index.md @@ -1,4 +1,5 @@ # Affix ```demo basic +position ``` \ No newline at end of file diff --git a/demo/documentation/components/affix/enUS/position.md b/demo/documentation/components/affix/enUS/position.md new file mode 100644 index 000000000..fc78dffa8 --- /dev/null +++ b/demo/documentation/components/affix/enUS/position.md @@ -0,0 +1,43 @@ +# Position +Affix can be `absolute` or `fix` positioned. You may need some css tricks to make it works as following. By default position is set to `fix`, because in most cases scrolled element is `#document`. +```html +
+
+
+
+ + + Top 50px + + + Bottom 60px + + +
+
+
+``` +```css +.absolute-anchor-container { + width: 100%; + height: 200px; + position: relative; +} + +.container { + height: 200px; + background-color: rgba(128, 128, 128, .3); + border-radius: 6px; + overflow: auto; +} + +.padding { + height: 150px; + width: 100%; + background-color: rgba(128, 128, 128, .15); +} + +.content { + height: 600px; +} +``` \ No newline at end of file diff --git a/demo/loaders/convertMd2Doc.js b/demo/loaders/convertMd2Doc.js index be96146c5..a63674fb1 100644 --- a/demo/loaders/convertMd2Doc.js +++ b/demo/loaders/convertMd2Doc.js @@ -68,7 +68,7 @@ function parseDemosAsAnchor (demosLiteral) { .map(demoName => demoName.trim()) .filter(demoName => demoName.length) const linkTags = demoNames.map(demoName => ``) - return `${linkTags.join('\n')}` + return `${linkTags.join('\n')}` } function generateScript (demosLiteral, components = []) { diff --git a/packages/common/Affix/src/main.vue b/packages/common/Affix/src/main.vue index 7559acaef..9f4141b0f 100644 --- a/packages/common/Affix/src/main.vue +++ b/packages/common/Affix/src/main.vue @@ -2,7 +2,8 @@
@@ -27,6 +28,10 @@ export default { bottom: { type: Number, default: null + }, + position: { + type: String, + default: 'fix' } }, data () { @@ -34,25 +39,27 @@ export default { container: null, stickToTop: false, stickToBottom: false, - memorizedTop: null, - affixTop: null + bottomAffixedTriggerScrollTop: null, + topAffixedTriggerScrollTop: null } }, computed: { + affixed () { + return this.stickToBottom || this.stickToTop + }, style () { const style = {} - if (this.affixed && this.affixTop !== null) { - style.top = `${this.affixTop}px` + if (this.stickToTop && this.top !== null) { + style.top = `${this.top}px` + } + if (this.stickToBottom && this.bottom !== null) { + style.bottom = `${this.bottom}px` } return style - }, - affixed () { - return this.stickToTop || this.stickToBottom } }, mounted () { this.init() - this.memorizeTop() }, beforeDestroy () { if (this.container) { @@ -71,35 +78,36 @@ export default { this.handleScroll() } }, - memorizeTop () { - const { - top - } = this.$el.getBoundingClientRect() - const containerScrollTop = this.container.scrollTop - const delta = containerScrollTop - this.top - this.memorizedTop = top + delta - }, handleScroll (e) { const containerEl = this.container.nodeName === '#document' ? this.container.documentElement : this.container - let scrollTop = containerEl.scrollTop - let scrollBottom = containerEl.scrollBottom - const originalAffixed = this.affixed - if (this.top !== null && scrollTop >= this.top) { + if (this.affixed) { + if (containerEl.scrollTop <= this.topAffixedTriggerScrollTop) { + this.stickToTop = false + this.topAffixedTriggerScrollTop = null + } + if (containerEl.scrollTop >= this.bottomAffixedTriggerScrollTop) { + this.stickToBottom = false + this.bottomAffixedTriggerScrollTop = null + } + return + } + const containerRect = containerEl.getBoundingClientRect() + const affixRect = this.$el.getBoundingClientRect() + const pxToTop = affixRect.top - containerRect.top + const pxToBottom = containerRect.bottom - affixRect.bottom + if (this.top !== null && pxToTop <= this.top) { this.stickToTop = true + this.topAffixedTriggerScrollTop = containerEl.scrollTop - (this.top - pxToTop) } else { this.stickToTop = false + this.topAffixedTriggerScrollTop = null } - if (this.bottom !== null && scrollBottom >= this.bottom) { + if (this.bottom !== null && pxToBottom <= this.bottom) { this.stickToBottom = true + this.bottomAffixedTriggerScrollTop = containerEl.scrollTop + this.bottom - pxToBottom } else { this.stickToBottom = false - } - if (!originalAffixed && this.affixed) { - // console.log(e, this.$el.getBoundingClientRect().top) - this.affixTop = this.memorizedTop - // debugger - } else { - this.memorizeTop() + this.bottomAffixedTriggerScrollTop = null } } } diff --git a/packages/common/Anchor/index.js b/packages/common/Anchor/index.js index 554a12786..108dca50f 100644 --- a/packages/common/Anchor/index.js +++ b/packages/common/Anchor/index.js @@ -1,5 +1,5 @@ /* istanbul ignore file */ -import Anchor from './src/main.vue' +import Anchor from './src/AnchorAdapter.vue' import AnchorLink from './src/Link.vue' Anchor.install = function (Vue) { diff --git a/packages/common/Anchor/src/main.vue b/packages/common/Anchor/src/AnchorAdapter.vue similarity index 77% rename from packages/common/Anchor/src/main.vue rename to packages/common/Anchor/src/AnchorAdapter.vue index f6fcb12cd..8522a9c1f 100644 --- a/packages/common/Anchor/src/main.vue +++ b/packages/common/Anchor/src/AnchorAdapter.vue @@ -9,6 +9,8 @@ v-else :target="target" :top="top" + :bottom="bottom" + :position="position" >