H5手机开发锁定表头和首列(惯性滚动)解决方案
前端时间移动端在做表格的时候需要这个功能,由于还有实现类似原生的惯性滚动功能,于是使用了iscroll插件。
iscroll插件下载地址:iscroll5
该功能demo github地址: https://github.com/lyc152/front-special-effects/tree/master/table-fixed
下面看下代码结构:
HTML:
1 <div class="data-table"> 2 <div class="t_l"> 3 <table> 4 <tbody> 5 <tr> 6 <th>品类</th> 7 </tr> 8 </tbody> 9 </table> 10 <div class="t_l_freeze" id="t_l_freeze"> 11 <table> 12 <tr> 13 <td>品类</td> 14 </tr> 15 <tr> 16 <td>男鞋</td> 17 </tr> 18 <tr> 19 <td>男鞋</td> 20 </tr> 21 <tr> 22 <td>男鞋</td> 23 </tr> 24 <tr> 25 <td>男鞋</td> 26 </tr> 27 <tr> 28 <td>男鞋</td> 29 </tr> 30 <tr> 31 <td>男鞋</td> 32 </tr> 33 <tr> 34 <td>男鞋</td> 35 </tr> 36 <tr> 37 <td>男鞋</td> 38 </tr> 39 <tr> 40 <td>男鞋</td> 41 </tr> 42 <tr> 43 <td>男鞋</td> 44 </tr> 45 <tr> 46 <td>男鞋</td> 47 </tr> 48 <tr> 49 <td>男鞋</td> 50 </tr> 51 <tr> 52 <td>男鞋</td> 53 </tr> 54 <tr> 55 <td>男鞋</td> 56 </tr> 57 <tr> 58 <td>男鞋</td> 59 </tr> 60 <tr> 61 <td>男鞋</td> 62 </tr> 63 </table> 64 </div> 65 </div> 66 <div class="t_r"> 67 <div class="t_r_t" id="t_r_t"> 68 <table> 69 <tbody> 70 <tr> 71 <th>1</th> 72 <th>2</th> 73 <th>3</th> 74 <th>4</th> 75 <th>5</th> 76 <th>6</th> 77 <th>7</th> 78 <th>8</th> 79 <th>9</th> 80 </tr> 81 </tbody> 82 </table> 83 </div> 84 <div class="t_r_content" id="t_r_content"> 85 <table> 86 <tbody> 87 <tr> 88 <td>1</td> 89 <td>2</td> 90 <td>3</td> 91 <td>4</td> 92 <td>5</td> 93 <td>6</td> 94 <td>7</td> 95 <td>8</td> 96 <td>9</td> 97 </tr> 98 <tr> 99 <td>1</td> 100 <td>2</td> 101 <td>3</td> 102 <td>4</td> 103 <td>5</td> 104 <td>6</td> 105 <td>7</td> 106 <td>8</td> 107 <td>9</td> 108 </tr> 109 <tr> 110 <td>1</td> 111 <td>2</td> 112 <td>3</td> 113 <td>4</td> 114 <td>5</td> 115 <td>6</td> 116 <td>7</td> 117 <td>8</td> 118 <td>9</td> 119 </tr> 120 <tr> 121 <td>1</td> 122 <td>2</td> 123 <td>3</td> 124 <td>4</td> 125 <td>5</td> 126 <td>6</td> 127 <td>7</td> 128 <td>8</td> 129 <td>9</td> 130 </tr> 131 <tr> 132 <td>1</td> 133 <td>2</td> 134 <td>3</td> 135 <td>4</td> 136 <td>5</td> 137 <td>6</td> 138 <td>7</td> 139 <td>8</td> 140 <td>9</td> 141 </tr> 142 <tr> 143 <td>1</td> 144 <td>2</td> 145 <td>3</td> 146 <td>4</td> 147 <td>5</td> 148 <td>6</td> 149 <td>7</td> 150 <td>8</td> 151 <td>9</td> 152 </tr> 153 <tr> 154 <td>1</td> 155 <td>2</td> 156 <td>3</td> 157 <td>4</td> 158 <td>5</td> 159 <td>6</td> 160 <td>7</td> 161 <td>8</td> 162 <td>9</td> 163 </tr> 164 <tr> 165 <td>1</td> 166 <td>2</td> 167 <td>3</td> 168 <td>4</td> 169 <td>5</td> 170 <td>6</td> 171 <td>7</td> 172 <td>8</td> 173 <td>9</td> 174 </tr> 175 <tr> 176 <td>1</td> 177 <td>2</td> 178 <td>3</td> 179 <td>4</td> 180 <td>5</td> 181 <td>6</td> 182 <td>7</td> 183 <td>8</td> 184 <td>9</td> 185 </tr> 186 <tr> 187 <td>1</td> 188 <td>2</td> 189 <td>3</td> 190 <td>4</td> 191 <td>5</td> 192 <td>6</td> 193 <td>7</td> 194 <td>8</td> 195 <td>9</td> 196 </tr> 197 <tr> 198 <td>1</td> 199 <td>2</td> 200 <td>3</td> 201 <td>4</td> 202 <td>5</td> 203 <td>6</td> 204 <td>7</td> 205 <td>8</td> 206 <td>9</td> 207 </tr> 208 <tr> 209 <td>1</td> 210 <td>2</td> 211 <td>3</td> 212 <td>4</td> 213 <td>5</td> 214 <td>6</td> 215 <td>7</td> 216 <td>8</td> 217 <td>9</td> 218 </tr> 219 <tr> 220 <td>1</td> 221 <td>2</td> 222 <td>3</td> 223 <td>4</td> 224 <td>5</td> 225 <td>6</td> 226 <td>7</td> 227 <td>8</td> 228 <td>9</td> 229 </tr> 230 <tr> 231 <td>1</td> 232 <td>2</td> 233 <td>3</td> 234 <td>4</td> 235 <td>5</td> 236 <td>6</td> 237 <td>7</td> 238 <td>8</td> 239 <td>9</td> 240 </tr> 241 <tr> 242 <td>1</td> 243 <td>2</td> 244 <td>3</td> 245 <td>4</td> 246 <td>5</td> 247 <td>6</td> 248 <td>7</td> 249 <td>8</td> 250 <td>9</td> 251 </tr> 252 <tr> 253 <td>1</td> 254 <td>2</td> 255 <td>3</td> 256 <td>4</td> 257 <td>5</td> 258 <td>6</td> 259 <td>7</td> 260 <td>8</td> 261 <td>9</td> 262 </tr> 263 <tr> 264 <td>1</td> 265 <td>2</td> 266 <td>3</td> 267 <td>4</td> 268 <td>5</td> 269 <td>6</td> 270 <td>7</td> 271 <td>8</td> 272 <td>9</td> 273 </tr> 274 </tbody> 275 </table> 276 </div> 277 </div> 278 </div>
实现表头和首列固定比较简单,可以将可以滚动的content容器的scrollTop和scrollLeft值分别赋值给锁定表列容器的scrollTop和锁定表头的scrollLeft。即:
1 function aa() { 2 var a = document.getElementById("t_r_content").scrollTop; 3 var b = document.getElementById("t_r_content").scrollLeft; 4 document.getElementById("cl_freeze").scrollTop = a; 5 document.getElementById("t_r_t").scrollLeft = b; 6 }
但是实现 惯性滚动 中还要 固定表头和表列就要麻烦些:
1 var win = $(window), 2 scrollAreaEl = $('.t_r_content'), 3 leftFreezeEl = $('.t_l_freeze'), 4 leftTableEl = leftFreezeEl.find('table'), 5 rightTableEl = $('.t_r_t table'); 6 7 //动态计算容器最大高度 8 function adjustHeight() { 9 var winHeight = win.height(), 10 tableHeight = winHeight - 90; 11 leftFreezeEl.height(tableHeight); 12 scrollAreaEl.height(tableHeight); 13 } 14 15 adjustHeight(); 16 win.on('resize', adjustHeight); 17 18 //设置iscroll 19 var myScroll = new IScroll('.t_r_content', { 20 scrollX: true, 21 scrollY: true, 22 probeType: 3 23 }); 24 25 //阻止默认滚动 26 scrollAreaEl.on('touchmove mousewheel', function(e) { 27 e.preventDefault(); 28 }); 29 30 //固定上左表头的滚动 31 myScroll.on('scroll', updatePosition); 32 myScroll.on('scrollEnd', updatePosition); 33 34 function updatePosition() { 35 var a = this.y; 36 var b = this.x; 37 leftTableEl.css('transform', 'translate(0px, ' + a + 'px) translateZ(0px)'); 38 rightTableEl.css('transform', 'translate(' + b + 'px, 0px) translateZ(0px)'); 39 }
实现步骤
1.引用 iscroll-probe.js 插件
2. 动态计算容器的最大高度,当resize的时候重新计算容器的最大高度;
3. 设置iscroll;
4. 阻止可滚动部分content的默认滚动;
5. 阻止上左表头的滚动,需要引用iscroll 中的 scroll,scrollEnd,要阻止表头和表列的滚动 ,就需要计算滚动的x和y值,更新leftTable和rightTable的transform的值就可以做到了。
当然,可以实现这个功能的方法很多,大家有什么比较好的方法我们都可以一起讨论,欢迎拍砖