Merge branch 'master' of https://github.com/vueComponent/ant-design
commit
f2ea0ccc0f
|
@ -0,0 +1,97 @@
|
|||
<template>
|
||||
<div>
|
||||
<tool-tip
|
||||
placement="top"
|
||||
:title="showText"
|
||||
:autoAdjustOverflow="autoAdjustOverflow"
|
||||
>
|
||||
<h1 @click="boom" class="test">撞到边缘翻转位置 & 点击更新</h1>
|
||||
</tool-tip>
|
||||
<ant-button @click="reverse" type="primary">{{autoAdjustOverflow ? '启用' : '关闭'}}自动调整中</ant-button>
|
||||
<div class="box">
|
||||
<h2>切换arrowPointAtCenter模式</h2>
|
||||
<ant-button @click="change">{{arrowPointAtCenter}}</ant-button>
|
||||
<table>
|
||||
<tr v-for="(tr, index) in table" :key="index">
|
||||
<td v-for="(td, i) in tr" :key="i">
|
||||
<tool-tip
|
||||
v-if="td"
|
||||
:placement="td"
|
||||
:title="td"
|
||||
:arrowPointAtCenter="arrowPointAtCenter"
|
||||
>
|
||||
<AntButton type="primary">{{td}}</AntButton>
|
||||
</tool-tip>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<div>
|
||||
<p>
|
||||
<tool-tip :arrowPointAtCenter="true" title="Consider using the NamedModulesPlugin for module names." placement="topLeft">
|
||||
<ant-button>arrowPointAtCenter arrowPointAtCenter arrowPointAtCenter</ant-button>
|
||||
</tool-tip>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ToolTip, Button } from 'antd'
|
||||
import 'antd/button/style'
|
||||
export default {
|
||||
name: 'tooltip-basic',
|
||||
data() {
|
||||
return {
|
||||
show: true,
|
||||
showText: '你好啊,233',
|
||||
table: [
|
||||
['', 'topLeft', 'top', 'topRight', ''],
|
||||
['leftTop', '', '', '', 'rightTop'],
|
||||
['left', '', '', '', 'right'],
|
||||
['leftBottom', '', '', '', 'rightBottom'],
|
||||
['', 'bottomLeft', 'bottom', 'bottomRight', ''],
|
||||
],
|
||||
arrowPointAtCenter: false,
|
||||
autoAdjustOverflow: true,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
boom() {
|
||||
if (this.showText.length % 20) {
|
||||
this.showText += '3'
|
||||
} else {
|
||||
this.showText += ' '
|
||||
}
|
||||
},
|
||||
change() {
|
||||
this.arrowPointAtCenter = !this.arrowPointAtCenter
|
||||
},
|
||||
reverse() {
|
||||
this.autoAdjustOverflow = !this.autoAdjustOverflow
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ToolTip,
|
||||
AntButton: Button,
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style scoped lang="less">
|
||||
.test {
|
||||
margin: 20px;
|
||||
display: inline-block;
|
||||
}
|
||||
.box {
|
||||
margin: 100px;
|
||||
}
|
||||
table {
|
||||
td {
|
||||
padding: 20px;
|
||||
}
|
||||
p {
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
</style>
|
|
@ -1,3 +1,4 @@
|
|||
import ToolTip from './tooltip.vue'
|
||||
import './style'
|
||||
export default ToolTip
|
||||
|
||||
|
|
|
@ -33,7 +33,9 @@ export default {
|
|||
visible: false,
|
||||
left: 0,
|
||||
top: 0,
|
||||
domNode: null,
|
||||
realPlacement: this.placement,
|
||||
t1: null,
|
||||
t2: null,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
@ -44,63 +46,96 @@ export default {
|
|||
}
|
||||
},
|
||||
},
|
||||
created() {
|
||||
const div = document.createElement('div')
|
||||
document.body.appendChild(div)
|
||||
const that = this
|
||||
const vnode = new Vue({
|
||||
data() {
|
||||
return {
|
||||
left: 0,
|
||||
top: 0,
|
||||
}
|
||||
},
|
||||
render(h) {
|
||||
return (
|
||||
<transition name="zoom-big">
|
||||
<div
|
||||
v-show={that.visible}
|
||||
class={`ant-tooltip ant-tooltip-placement-${that.placement}`}
|
||||
style={{ left: this.left + 'px', top: this.top + 'px' }}
|
||||
>
|
||||
<div class="ant-tooltip-content">
|
||||
<div class="ant-tooltip-arrow"/>
|
||||
<div class="ant-tooltip-inner">
|
||||
<span>{that.title}</span>
|
||||
methods: {
|
||||
checkPosition(popup, text, placement) {
|
||||
let { top, left, bottom, right } = text
|
||||
const reg = /(top|bottom|left|right)(.*)/
|
||||
const [, abstractPos, suffix] = placement.match(reg)
|
||||
let ret = placement
|
||||
// we can change the position many times
|
||||
if (abstractPos === 'left' && left < popup.width) ret = 'right' + suffix
|
||||
if (abstractPos === 'right' && document.documentElement.clientWidth - right < popup.width) ret = 'left' + suffix
|
||||
if (abstractPos === 'top' && top < popup.height) ret = 'bottom' + suffix
|
||||
if (abstractPos === 'bottom' && document.documentElement.clientHeight - bottom < popup.height) ret = 'left' + suffix
|
||||
return ret
|
||||
},
|
||||
mountNode(callback) {
|
||||
if (this.vnode) {
|
||||
callback()
|
||||
return
|
||||
}
|
||||
const div = document.createElement('div')
|
||||
document.body.appendChild(div)
|
||||
const that = this
|
||||
const vnode = new Vue({
|
||||
data() {
|
||||
return {
|
||||
left: 0,
|
||||
top: 0,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
hideSelf(e) {
|
||||
if (that.t1) {
|
||||
clearTimeout(that.t1)
|
||||
that.t1 = null
|
||||
}
|
||||
if (that.mouseLeaveDelay) {
|
||||
that.t2 = window.setTimeout(() => {
|
||||
if (e.relatedTarget === that.$el) {
|
||||
return
|
||||
}
|
||||
that.visible = false
|
||||
}, +that.mouseLeaveDelay * 1e3)
|
||||
}
|
||||
}
|
||||
},
|
||||
render(h) {
|
||||
return (
|
||||
<transition name={that.transitionName}>
|
||||
<div
|
||||
v-show={that.visible}
|
||||
class={`ant-tooltip ant-tooltip-placement-${that.realPlacement}`}
|
||||
style={{ left: this.left + 'px', top: this.top + 'px' }}
|
||||
onMouseleave={this.hideSelf}
|
||||
>
|
||||
<div class="ant-tooltip-content">
|
||||
<div class="ant-tooltip-arrow"/>
|
||||
<div class="ant-tooltip-inner">
|
||||
<span>{that.title}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</transition>
|
||||
)
|
||||
}
|
||||
}).$mount(div)
|
||||
this.$nextTick(() => {
|
||||
this.vnode = vnode
|
||||
this.domNode = div
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
</transition>
|
||||
)
|
||||
}
|
||||
}).$mount(div)
|
||||
this.$nextTick(() => {
|
||||
this.vnode = vnode
|
||||
callback()
|
||||
})
|
||||
},
|
||||
onPopupAlign: (placement, domNode, target, align) => {
|
||||
if (!placement) {
|
||||
return;
|
||||
return
|
||||
}
|
||||
// 根据当前坐标设置动画点
|
||||
const rect = domNode.getBoundingClientRect()
|
||||
const transformOrigin = {
|
||||
top: '50%',
|
||||
left: '50%',
|
||||
};
|
||||
}
|
||||
if (placement.indexOf('top') >= 0 || placement.indexOf('Bottom') >= 0) {
|
||||
transformOrigin.top = `${rect.height - align.offset[1]}px`;
|
||||
transformOrigin.top = `${rect.height - align.offset[1]}px`
|
||||
} else if (placement.indexOf('Top') >= 0 || placement.indexOf('bottom') >= 0) {
|
||||
transformOrigin.top = `${-align.offset[1]}px`;
|
||||
transformOrigin.top = `${-align.offset[1]}px`
|
||||
}
|
||||
if (placement.indexOf('left') >= 0 || placement.indexOf('Right') >= 0) {
|
||||
transformOrigin.left = `${rect.width - align.offset[0]}px`;
|
||||
transformOrigin.left = `${rect.width - align.offset[0]}px`
|
||||
} else if (placement.indexOf('right') >= 0 || placement.indexOf('Left') >= 0) {
|
||||
transformOrigin.left = `${-align.offset[0]}px`;
|
||||
transformOrigin.left = `${-align.offset[0]}px`
|
||||
}
|
||||
target.style.transformOrigin = `${transformOrigin.left} ${transformOrigin.top}`;
|
||||
target.style.transformOrigin = `${transformOrigin.left} ${transformOrigin.top}`
|
||||
},
|
||||
addEventHandle(old, fn) {
|
||||
if (!old) {
|
||||
|
@ -111,68 +146,107 @@ export default {
|
|||
return old === fn ? old : [old, fn]
|
||||
}
|
||||
},
|
||||
computeOffset(popup, text, placement) {
|
||||
computeOffset(popup, text, placement, scale) {
|
||||
let { width, height, top, left } = text
|
||||
// you cant change the properties of DOMRect
|
||||
top += window.scrollY
|
||||
left += window.scrollX
|
||||
// FIXME: we can get the numbers from scale, but that's not what we really want
|
||||
const p = { width: popup.width / scale, height: popup.height / scale }
|
||||
const ret = { left, top }
|
||||
|
||||
if (/top/.test(placement)) ret.top -= popup.height
|
||||
if (/top/.test(placement)) ret.top -= p.height
|
||||
if (/bottom/.test(placement)) ret.top += height
|
||||
if (/left/.test(placement)) ret.left -= popup.width
|
||||
if (/left/.test(placement)) ret.left -= p.width
|
||||
if (/right/.test(placement)) ret.left += width
|
||||
|
||||
// FIXME: magic number 20 & 14 comes from the offset of triangle
|
||||
if (/Left/.test(placement)) {
|
||||
if (this.arrowPointAtCenter) ret.left += width / 2 - 20
|
||||
} else if(/Right/.test(placement)) {
|
||||
ret.left += (width - popup.width)
|
||||
ret.left += (width - p.width)
|
||||
if (this.arrowPointAtCenter) ret.left -= width / 2 - 20
|
||||
} else if(/(top)|(bottom)/.test(placement)) {
|
||||
ret.left += (width - popup.width) / 2
|
||||
ret.left += (width - p.width) / 2
|
||||
}
|
||||
if (/Top/.test(placement)) {
|
||||
if (this.arrowPointAtCenter) ret.top += height / 2 - 14
|
||||
} else if(/Bottom/.test(placement)) {
|
||||
ret.top += (height - popup.height)
|
||||
ret.top += (height - p.height)
|
||||
if (this.arrowPointAtCenter) ret.top -= height / 2 - 14
|
||||
} else if(/(left)|(right)/.test(placement)) {
|
||||
ret.top += (height - popup.height) / 2
|
||||
ret.top += (height - p.height) / 2
|
||||
}
|
||||
return ret
|
||||
},
|
||||
showNode() {
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
const popup = this.vnode.$el.getBoundingClientRect()
|
||||
const content = this.$el.getBoundingClientRect()
|
||||
const { left, top } = this.computeOffset(popup, content, this.placement)
|
||||
this.vnode.left = left
|
||||
this.vnode.top = top
|
||||
this.mountNode(() => {
|
||||
this.visible = true
|
||||
this.$nextTick(() => {
|
||||
const popup = this.vnode.$el.getBoundingClientRect()
|
||||
const [, scale = 1] = window.getComputedStyle(this.vnode.$el).transform.match(/matrix\((.*?),/) || []
|
||||
const content = this.$el.getBoundingClientRect()
|
||||
const place = this.autoAdjustOverflow ? this.checkPosition(popup, content, this.placement, scale) : this.placement
|
||||
this.realPlacement = place
|
||||
const { left, top } = this.computeOffset(popup, content, place, scale)
|
||||
this.vnode.left = left
|
||||
this.vnode.top = top
|
||||
})
|
||||
this.onPopupAlign(this.realPlacement, this.$el, this.vnode.$el, { offset: [0,0] })
|
||||
})
|
||||
this.onPopupAlign(this.placement, this.$el, this.vnode.$el, { offset: [0,0] })
|
||||
},
|
||||
hideNode() {
|
||||
hideNode(e) {
|
||||
if (!this.vnode) return
|
||||
if (e.relatedTarget === this.vnode.$el) {
|
||||
return
|
||||
}
|
||||
this.visible = false
|
||||
},
|
||||
checkShow(e) {
|
||||
if (this.t2) {
|
||||
clearTimeout(this.t2)
|
||||
this.t2 = null
|
||||
}
|
||||
if (this.mouseEnterDelay) {
|
||||
this.t1 = window.setTimeout(() => {
|
||||
this.showNode(e)
|
||||
}, +this.mouseEnterDelay * 1e3)
|
||||
}
|
||||
},
|
||||
checkHide(e) {
|
||||
if (this.t1) {
|
||||
clearTimeout(this.t1)
|
||||
this.t1 = null
|
||||
}
|
||||
if (this.mouseLeaveDelay) {
|
||||
this.t2 = window.setTimeout(() => {
|
||||
this.hideNode(e)
|
||||
}, +this.mouseLeaveDelay * 1e3)
|
||||
}
|
||||
}
|
||||
},
|
||||
render(h) {
|
||||
let node = this.vnode
|
||||
const inner = this.$slots.default[0]
|
||||
inner.data = inner.data || {}
|
||||
inner.data.on = inner.data.on || {}
|
||||
inner.data.on.mouseenter = this.addEventHandle(inner.data.on.mouseenter, this.showNode)
|
||||
inner.data.on.mouseleave = this.addEventHandle(inner.data.on.mouseleave, this.hideNode)
|
||||
// console.info(inner)
|
||||
inner.data.on.mouseenter = this.addEventHandle(inner.data.on.mouseenter, this.checkShow)
|
||||
inner.data.on.mouseleave = this.addEventHandle(inner.data.on.mouseleave, this.checkHide)
|
||||
|
||||
return this.$slots.default[0]
|
||||
},
|
||||
updated() {
|
||||
if (!this.vnode) return
|
||||
const popup = this.vnode.$el.getBoundingClientRect()
|
||||
const [, scale = 1] = window.getComputedStyle(this.vnode.$el).transform.match(/matrix\((.*?),/) || []
|
||||
const content = this.$el.getBoundingClientRect()
|
||||
const { left, top } = this.computeOffset(popup, content, this.placement)
|
||||
const { left, top } = this.computeOffset(popup, content, this.realPlacement, scale)
|
||||
this.vnode.left = left
|
||||
this.vnode.top = top
|
||||
},
|
||||
beforeDestory() {
|
||||
console.info('没有成功清除实例 ,看vue panel')
|
||||
this.vnode.$destroy();
|
||||
this.domNode && this.domNode.remove()
|
||||
beforeDestroy() {
|
||||
if (!this.vnode) return
|
||||
this.vnode.$el.remove()
|
||||
this.vnode.$destroy()
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
<template>
|
||||
<div>
|
||||
<tool-tip
|
||||
placement="top"
|
||||
:title="showText">
|
||||
<h1 @click="boom" style="display: inline-block">This is just a test, put your cursor here</h1>
|
||||
</tool-tip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { ToolTip } from '../components'
|
||||
export default {
|
||||
name: '',
|
||||
data() {
|
||||
return {
|
||||
show: true,
|
||||
showText: '你好啊,23'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
boom() {
|
||||
this.showText += '3'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
ToolTip
|
||||
}
|
||||
}
|
||||
</script>
|
Loading…
Reference in New Issue