22 <div class =" friend-link-wrapper" >
33 <div
44 class =" friend-link-item"
5- v-for =" (item, index) in $themeConfig.friendLink "
5+ v-for =" (item, index) in dataAddColor "
66 :key =" index"
7- @mouseenter =" showDetail($event, item )"
8- @mouseleave =" hideDetail"
7+ @mouseenter =" showDetail($event)"
8+ @mouseleave =" hideDetail($event) "
99 target =" _blank" >
1010 <span
1111 class =" list-style"
12- :style =" { 'backgroundColor': _tagColor() }" >
12+ :style =" { 'backgroundColor': item.color }" >
1313 </span >
1414 {{item.title}}
15- </ div >
16- < transition name = " fade " >
17- <div
18- @mouseenter = " windowEnter "
19- @mouseleave = " windowLeave "
20- class = " popup-window "
21- v-if = " showDetailStatus "
22- :style = " popupWindowStyle "
23- ref = " popupWindow " >
24- <div class =" avatar " >
25- < img :src = " `http://1.gravatar.com/avatar/${getMd5(detailData.email || '')}?s=50 & amp ; d=mm & amp ; r=x` " / >
26- </ div >
27- < div class = " info " >
28- < div class =" title " >
29- < h4 >{{ detailData.title }}</ h4 >
30- < a
31- class = " btn-go "
32- :style = " { 'backgroundColor': _tagColor() } "
33- :href = " detailData.link "
34- target = " _blank " >GO</ a >
15+ < transition name = " fade " >
16+ < div class = " popup-window-wrapper " >
17+ <div
18+ class = " popup-window "
19+ :style = " popupWindowStyle "
20+ ref = " popupWindow " >
21+ < div class = " avatar " >
22+ < img :src = " getImgUrl(item) " />
23+ </ div >
24+ <div class =" info " >
25+ < div class = " title " >
26+ < h4 >{{ item.title }}</ h4 >
27+ < a
28+ class =" btn-go "
29+ :style = " { 'backgroundColor': item.color } "
30+ :href = " item.link "
31+ target = " _blank " >GO</ a >
32+ </ div >
33+ < p v-if = " item.desc " >{{ item.desc }}</ p >
34+ </ div >
3535 </div >
36- <p >{{ detailData.desc }}</p >
3736 </div >
38- </div >
39- </transition >
37+
38+ </transition >
39+ </div >
4040 </div >
4141</template >
4242
@@ -48,76 +48,63 @@ export default {
4848 mixins: [mixin],
4949 data () {
5050 return {
51- detailData: {},
52- showDetailStatus: false ,
53- popupWindowStyle: {},
54- btnEnterStatus: false ,
55- windowEnterStatus: false
51+ popupWindowStyle: {}
52+ }
53+ },
54+ computed: {
55+ dataAddColor () {
56+ let friendLink = this .$themeConfig .friendLink
57+ friendLink = friendLink .length > 0 ? friendLink .map (item => ({
58+ ... item,
59+ color: this ._tagColor ()
60+ })) : []
61+ return friendLink
5662 }
5763 },
5864 methods: {
5965 getMd5 (str ) {
6066 return md5 (str)
6167 },
62- showDetail (e , info ) {
63- this .btnEnterStatus = true
68+ showDetail (e ) {
6469 const currentDom = e .target
65- const { offsetTop , offsetLeft , clientWidth } = currentDom
70+ const popupWindowWrapper = currentDom .querySelector (' .popup-window-wrapper' )
71+ const popupWindow = currentDom .querySelector (' .popup-window' )
72+ popupWindowWrapper .style .display = ' block'
73+ const { clientWidth } = currentDom
74+ const {
75+ clientWidth: windowWidth ,
76+ clientHeight: windowHeight
77+ } = popupWindow
6678 this .popupWindowStyle = {
67- left: ((offsetLeft + clientWidth / 2 ) - 300 / 2 ) + ' px' ,
68- top: (offsetTop - 150 ) + ' px'
79+ left: (clientWidth - windowWidth) / 2 + ' px' ,
80+ top: - windowHeight + ' px'
6981 }
70- this .detailData = info
71- this .showDetailStatus = true
7282 this .$nextTick (() => {
73- this ._adjustPosition ()
83+ this ._adjustPosition (currentDom . querySelector ( ' .popup-window ' ) )
7484 })
7585 },
76- hideDetail () {
77- // this.btnEnterStatus = false
78- // if (this.windowEnterStatus === false) this.showDetailStatus = false
79- },
80- windowEnter () {
81- this .windowEnterStatus = true
82- this .showDetailStatus = true
86+ hideDetail (e ) {
87+ const currentDom = e .target
88+ currentDom .querySelector (' .popup-window-wrapper' ).style .display = ' none'
8389 },
84- windowLeave () {
85- // this.windowEnterStatus = false
86- // if (this.btnEnterStatus === false) this.showDetailStatus = false
90+ getImgUrl (info ) {
91+ const { avatar , email } = info
92+ if (avatar && / ^ http/ .test (avatar)) return avatar
93+ if (avatar && ! / ^ http/ .test (avatar)) return this .$withBase (avatar)
94+ return ` http://1.gravatar.com/avatar/${ this .getMd5 (email || ' ' )} ?s=50&d=mm&r=x`
8795 },
88- _adjustPosition () {
96+ _adjustPosition (dom ) {
8997 const { offsetWidth } = document .body
90- const { x , width } = this . $refs . popupWindow .getBoundingClientRect ()
98+ const { x , width } = dom .getBoundingClientRect ()
9199 const distanceToRight = offsetWidth - (x + width)
92100 if (distanceToRight < 0 ) {
93- const { offsetLeft } = this . $refs . popupWindow
101+ const { offsetLeft } = dom
94102 this .popupWindowStyle = {
95103 ... this .popupWindowStyle ,
96104 left: offsetLeft + distanceToRight + ' px'
97105 }
98106 }
99107 }
100- },
101- watch: {
102- showDetailStatus (val ) {
103- if (val) {
104- let [prevX, prevY, nextX, nextY] = [0 , 0 , 0 , 0 ]
105-
106- window .addEventListener (' mouseend' , (e ) => {
107- prevX = nextX
108- prevY = nextY
109- nextX = e .x
110- nextY = e .y
111- // console.log(prevX, prevY, nextX, nextY)
112- console .log (Math .atan2 (nextY - prevY, nextX - prevX))
113- if (Math .atan2 (nextY - prevY, nextX - prevX) > - 1.75 && Math .atan2 (nextY - prevY, nextX - prevX)< - 0.75 ) {
114- this .showDetailStatus = true
115- } else {
116- this .showDetailStatus = false
117- }
118- })
119- }
120- }
121108 }
122109}
123110 </script >
@@ -153,42 +140,53 @@ export default {
153140 border-radius .1rem
154141 background $accentColor
155142 content ''
156- .popup-window
157- position absolute
158- display flex
159- background #ff ff ff
160- box-shadow $boxShadow
161- box-sizing border-box
162- padding .4rem
163- width 300px
164- height 150px
165- .avatar
166- margin-right .4rem
167- width 2rem
168- height 2rem
169- border-radius $borderRadius
170- overflow hidden
171- img
172- width 2rem
173- height 2rem
174- .info
175- flex 1
176- .title
143+ .popup-window-wrapper
144+ display none
145+ .popup-window
146+ position absolute
177147 display flex
178- align-items center
179- justify-content space-between
180- height 2rem
181- h4
182- margin .2rem 0
183- .btn-go
184- width 1.4rem
185- height 1.2rem
148+ background #ff ff ff
149+ box-shadow $boxShadow
150+ border-radius $borderRadius
151+ box-sizing border-box
152+ padding .8rem 1rem
153+ width 300px
154+ .avatar
155+ margin-right .4rem
156+ width 2rem
157+ height 2rem
158+ flex 0 0 2rem
186159 border-radius $borderRadius
187- font-size .1rem
188- color #ff ff ff
189- text-align center
190- line-height 1.2rem
191- cursor pointer
160+ overflow hidden
161+ img
162+ width 2rem
163+ height 2rem
164+ .info
165+ flex 0 0 85%
166+ width 85%
167+ .title
168+ display flex
169+ align-items center
170+ justify-content space-between
171+ height 2rem
172+ h4
173+ margin .2rem 0
174+ flex 0 0 86%
175+ overflow : hidden ;
176+ white-space : nowrap ;
177+ text-overflow : ellipsis ;
178+ .btn-go
179+ width 1.4rem
180+ height 1.2rem
181+ border-radius $borderRadius
182+ font-size .1rem
183+ color #ff ff ff
184+ text-align center
185+ line-height 1.2rem
186+ cursor pointer
187+ transition all .5s
188+ & :hover
189+ transform scale (1.1 )
192190
193191.fade-enter-active , .fade-leave-active
194192 transition opacity .5s
0 commit comments