ant-design-vue/components/tabs/InkTabBarMixin.js
tangjinzhou 350001ea14 fix
2017-12-01 12:21:43 +08:00

146 lines
4.1 KiB
JavaScript

import { setTransform, isTransformSupported } from './utils'
export function getScroll (w, top) {
let ret = w[`page${top ? 'Y' : 'X'}Offset`]
const method = `scroll${top ? 'Top' : 'Left'}`
if (typeof ret !== 'number') {
const d = w.document
// ie6,7,8 standard mode
ret = d.documentElement[method]
if (typeof ret !== 'number') {
// quirks mode
ret = d.body[method]
}
}
return ret
}
function offset (elem) {
let x
let y
const doc = elem.ownerDocument
const body = doc.body
const docElem = doc && doc.documentElement
const box = elem.getBoundingClientRect()
x = box.left
y = box.top
x -= docElem.clientLeft || body.clientLeft || 0
y -= docElem.clientTop || body.clientTop || 0
const w = doc.defaultView || doc.parentWindow
x += getScroll(w)
y += getScroll(w, true)
return {
left: x, top: y,
}
}
function componentDidUpdate (component, init) {
const { styles = {}} = component.$props
const wrapNode = component.$refs.nav || component.$refs.root
const containerOffset = offset(wrapNode)
const inkBarNode = component.$refs.inkBar
const activeTab = component.$refs.activeTab
const inkBarNodeStyle = inkBarNode.style
const tabBarPosition = component.$props.tabBarPosition
if (init) {
// prevent mount animation
inkBarNodeStyle.display = 'none'
}
if (activeTab) {
const tabNode = activeTab
const tabOffset = offset(tabNode)
const transformSupported = isTransformSupported(inkBarNodeStyle)
if (tabBarPosition === 'top' || tabBarPosition === 'bottom') {
let left = tabOffset.left - containerOffset.left
let width = tabNode.offsetWidth
// If tabNode'width width equal to wrapNode'width when tabBarPosition is top or bottom
// It means no css working, then ink bar should not have width until css is loaded
// Fix https://github.com/ant-design/ant-design/issues/7564
if (width === wrapNode.offsetWidth) {
width = 0
} else if (styles.inkBar && styles.inkBar.width !== undefined) {
width = parseFloat(styles.inkBar.width, 10)
if (width) {
left = left + (tabNode.offsetWidth - width) / 2
}
}
// use 3d gpu to optimize render
if (transformSupported) {
setTransform(inkBarNodeStyle, `translate3d(${left}px,0,0)`)
inkBarNodeStyle.width = `${width}px`
inkBarNodeStyle.height = ''
} else {
inkBarNodeStyle.left = `${left}px`
inkBarNodeStyle.top = ''
inkBarNodeStyle.bottom = ''
inkBarNodeStyle.right = `${wrapNode.offsetWidth - left - width}px`
}
} else {
let top = tabOffset.top - containerOffset.top
let height = tabNode.offsetHeight
if (styles.inkBar && styles.inkBar.height !== undefined) {
height = parseFloat(styles.inkBar.height, 10)
if (height) {
top = top + (tabNode.offsetHeight - height) / 2
}
}
if (transformSupported) {
setTransform(inkBarNodeStyle, `translate3d(0,${top}px,0)`)
inkBarNodeStyle.height = `${height}px`
inkBarNodeStyle.width = ''
} else {
inkBarNodeStyle.left = ''
inkBarNodeStyle.right = ''
inkBarNodeStyle.top = `${top}px`
inkBarNodeStyle.bottom = `${wrapNode.offsetHeight - top - height}px`
}
}
}
inkBarNodeStyle.display = activeTab ? 'block' : 'none'
}
export default {
props: {
inkBarAnimated: {
type: Boolean,
default: true,
},
prefixCls: String,
styles: Object,
},
updated () {
this.$nextTick(function () {
componentDidUpdate(this)
})
},
mounted () {
this.$nextTick(function () {
componentDidUpdate(this, true)
})
},
methods: {
getInkBarNode () {
const { prefixCls, styles = {}, inkBarAnimated } = this
const className = `${prefixCls}-ink-bar`
const classes = {
[className]: true,
[
inkBarAnimated
? `${className}-animated`
: `${className}-no-animated`
]: true,
}
return (
<div
style={styles.inkBar}
class={classes}
key='inkBar'
ref='inkBar'
/>
)
},
},
}