Authored by 李奇

品牌列表侧边索引组件创建

@@ -41,7 +41,7 @@ const handleBrandList = origin => { @@ -41,7 +41,7 @@ const handleBrandList = origin => {
41 logo: subValue.brand_ico, 41 logo: subValue.brand_ico,
42 domain: subValue.brand_domain, 42 domain: subValue.brand_domain,
43 shopId: subValue.shop_id, 43 shopId: subValue.shop_id,
44 - isHot: subValue.is_hot 44 + isRedShop: subValue.is_red_shop
45 }); 45 });
46 }); 46 });
47 47
1 <template> 1 <template>
2 - <ul class="side-idx"> 2 + <v-touch tag="ul"
  3 + class="side-idx"
  4 + @tap="tap"
  5 + @panup="showZoom"
  6 + @pandown="showZoom"
  7 + @panend="hideZoom"
  8 + @press="showZoom"
  9 + @pressup="hideZoom">
3 <div class="bg"></div> 10 <div class="bg"></div>
4 - <div class="zoom-in">M</div>  
5 - <li v-for="item in items" :key="item.name">  
6 - <a class="no-intercept" href="javascript:;"  
7 - @click="() => {loc(item.index)}">{{item.name}}</a> 11 + <div class="zoom-in"
  12 + :class="{show: zoomSwitch}">
  13 + {{zoomName}}
  14 + </div>
  15 + <li v-for="(item, index) in items"
  16 + :key="item.name"
  17 + :data-idx="item.name">
  18 + <a class="idx-item no-intercept"
  19 + :class="{zoom: index === zoomIdx}"
  20 + href="javascript:;">
  21 + {{item.name}}
  22 + </a>
8 </li> 23 </li>
9 - </ul> 24 + </v-touch>
10 </template> 25 </template>
11 <script> 26 <script>
12 export default { 27 export default {
@@ -16,22 +31,74 @@ @@ -16,22 +31,74 @@
16 }, 31 },
17 data() { 32 data() {
18 return { 33 return {
19 - items: [] 34 + items: [],
  35 + timer: '',
  36 + zoomName: '',
  37 + zoomIdx: '',
  38 + $zoomIn: '',
  39 + $sideIdx: '',
  40 + sideRect: {},
  41 + firstIdxRect: {},
  42 + zoomSwitch: false
20 }; 43 };
21 }, 44 },
22 watch: { 45 watch: {
23 indexList() { 46 indexList() {
24 if (this.indexList) { 47 if (this.indexList) {
25 this.items = this.indexList; 48 this.items = this.indexList;
  49 + this.$nextTick(function() {
  50 + this.recordIdxRect();
  51 + });
26 } 52 }
27 } 53 }
28 }, 54 },
29 methods: { 55 methods: {
30 - loc(index) {  
31 - this.$emit('loc-index', index); 56 + tap(e) {
  57 + this.showZoom(e);
  58 + clearTimeout(this.timer);
  59 + this.timer = setTimeout(() => {
  60 + this.hideZoom();
  61 + }, 500);
  62 + },
  63 + hideZoom() {
  64 + this.zoomIdx = '';
  65 + this.zoomSwitch = false;
  66 + },
  67 + showZoom(e) {
  68 + const eX = e.center.x;
  69 + const eY = e.center.y;
  70 + const outRect = eX < this.sideRect.left || eY < this.sideRect.top || eY > this.sideRect.bottom;
  71 +
  72 + if (outRect) {
  73 + return this.hideZoom();
  74 + }
  75 +
  76 + let len = this.items.length;
  77 + let idx = Math.floor((eY - this.firstIdxRect.top) / this.firstIdxRect.height);
  78 +
  79 + if (idx < 0) {
  80 + idx = 0;
  81 + }
  82 +
  83 + if (idx === len || idx > len) {
  84 + idx = len - 1;
  85 + }
  86 +
  87 + this.zoomIdx = idx;
  88 + this.zoomName = this.items[idx].name;
  89 + this.$zoomIn.style.top = this.calcZoomInTop(idx);
  90 + this.zoomSwitch = true;
  91 + this.$emit('loc-index', this.zoomName);
  92 + },
  93 + calcZoomInTop(idx) {
  94 + return (idx + 0.5) * this.firstIdxRect.height - this.$zoomIn.getBoundingClientRect().height / 2 +
  95 + this.firstIdxRect.top - this.sideRect.top + 'px';
32 }, 96 },
33 - touch() {  
34 - console.log('touch') 97 + recordIdxRect() {
  98 + this.$sideIdx = document.querySelector('.side-idx');
  99 + this.$zoomIn = this.$sideIdx.querySelector('.zoom-in');
  100 + this.sideRect = this.$sideIdx.getBoundingClientRect();
  101 + this.firstIdxRect = this.$sideIdx.querySelector('li').getBoundingClientRect();
35 } 102 }
36 }, 103 },
37 created() { 104 created() {
@@ -84,11 +151,17 @@ @@ -84,11 +151,17 @@
84 height: 58px; 151 height: 58px;
85 padding-left: 20px; 152 padding-left: 20px;
86 color: #fff; 153 color: #fff;
  154 + text-align: left;
87 line-height: 58px; 155 line-height: 58px;
88 background: resolve("product/zoom-in-bg.png"); 156 background: resolve("product/zoom-in-bg.png");
89 background-size: cover; 157 background-size: cover;
90 - } 158 + transition: opacity 0.4s ease;
  159 + opacity: 0;
91 160
  161 + &.show {
  162 + opacity: 1;
  163 + }
  164 + }
92 165
93 li { 166 li {
94 position: relative; 167 position: relative;
@@ -96,6 +169,7 @@ @@ -96,6 +169,7 @@
96 text-align: center; 169 text-align: center;
97 width: 100%; 170 width: 100%;
98 171
  172 +
99 a { 173 a {
100 color: #fff; 174 color: #fff;
101 font-size: 18px; 175 font-size: 18px;