This article mainly introduces the IndexList of mobile terminal effects in detail. It has certain reference value. Interested friends can refer to it. I hope it can help everyone.
Written in front
Following the previous mobile effects talk, this time I will explain the implementation principle of IndexList. The effect is as follows:
Please see the code here: github
Swiper for mobile effects
Picker for mobile effects
Mobile terminal effect of cellSwiper
1. Core analysis
The overall principle is that when you click or slide the index bar on the right, by getting Click the index value to slide the content on the left to the corresponding position. How to slide to a specific position, see the breakdown below:
1.1 Basic html code
<p class="indexlist"> <ul class="indexlist-content" id="content"> <!-- 需要生成的内容 --> </ul> <p class="indexlist-nav" id="nav"> <ul class="indexlist-navlist" id="navList"> <-- 需要生成的索引条 --> </ul> </p> <p class="indexlist-indicator" style="display: none;" id="indicator"></p> </p>
1.2 DOM initialization
Because I’m hungry The indexList in the component library uses the vue component to generate DOM. I roughly use javascript to simulate the DOM generation here.
// 内容填充 function initialDOM() { // D.data 获取内容数据 var data = D.data; var contentHtml = ''; var navHtml = ''; // 初始化内容和NAV data.forEach(function(d) { var index = d.index; var items = d.items; navHtml += '<li class="indexlist-navitem">'+ index +'</li>'; contentHtml += '<li class="indexsection" data-index="'+ index +'"><p class="indexsection-index">'+ index +'</p><ul>'; items.forEach(function(item) { contentHtml += '<a class="cell"><p class="cell-wrapper"><p class="cell-title"><span class="cell-text">'+ item +'</span></p></p></a>'; }); contentHtml += '</ul></li>'; }); content.innerHTML = contentHtml; navList.innerHTML = navHtml; } // 样式初始化 if (!currentHeight) { currentHeight = document.documentElement.clientHeight -content.getBoundingClientRect().top; } // 右边索引栏的宽度 navWidth = nav.clientWidth; // 左边内容的初始化高度和右边距 // 高度为当前页面的高度与内容top的差值 content.style.marginRight = navWidth + 'px'; content.style.height = currentHeight + 'px';
1.3 Bind sliding event
Add a sliding event to the index bar on the right, which is triggered when clicking or sliding. In the source code, at the end of the touchstart event, the touchmove and touchend events are bound to the window in order to make the sliding area larger. Only when the touchstart event is triggered on the index bar at the beginning, then on the window Trigger sliding and end events, which means that we can slide in the content area on the left during the sliding process, and at the same time achieve the index effect.
function handleTouchstart(e) { // 如果不是从索引栏开始滑动,则直接return // 保证了左侧内容区域能够正常滑动 if (e.target.tagName !== 'LI') { return; } // 记录开始的clientX值,这个clientX值将在之后的滑动中持续用到,用于定位 navOffsetX = e.changedTouches[0].clientX; // 内容滑动到指定区域 scrollList(e.changedTouches[0].clientY); if (indicatorTime) { clearTimeout(indicatorTime); } moving = true; // 在window区域注册滑动和结束事件 window.addEventListener('touchmove', handleTouchMove, { passive: false }); window.addEventListener('touchend', handleTouchEnd); }
e.changedTouches is used here. You can check this API on MDN.
If multi-touch is not used, the difference between changedTouches and touches is not particularly big. If changedTouches is clicked twice on the same point, there will be no touch value the second time. For details, you can read this article
Let’s take a look at how to slide:
function scrollList(y) { // 通过当前的y值以及之前记录的clientX值来获得索引栏中的对应item var currentItem = document.elementFromPoint(navOffsetX, y); if (!currentItem || !currentItem.classList.contains('indexlist-navitem')) { return; } // 显示指示器 currentIndicator = currentItem.innerText; indicator.innerText = currentIndicator; indicator.style.display = ''; // 找到左侧内容的对应section var targets = [].slice.call(sections).filter(function(section) { var index = section.getAttribute('data-index'); return index === currentItem.innerText; }); var targetDOM; if (targets.length > 0) { targetDOM = targets[0]; // 通过对比要滑动到的区域的top值与最开始的一个区域的top值 // 两者的差值即为要滚动的距离 content.scrollTop = targetDOM.getBoundingClientRect().top - firstSection.getBoundingClientRect().top; // 或者使用scrollIntoView来达到相同的目的 // 不过存在兼容性的问题 // targetDOM.scrollIntoView(); } }
For the API of elementFromPoint, you can see here
caniuse.com About the compatibility of getBoundingClientRect and scrollIntoView
getBoundingClientRect
##scrollIntoViewFinally, you need to log out of the window Sliding event onwindow.removeEventListener('touchmove', handleTouchMove); window.removeEventListener('touchend', handleTouchEnd);
2. Summary
So much for analysis, you can learn excellent design concepts by looking more at the source code. For example, if I were asked to do it at the beginning, I could only bind the event to the index bar on the right and not associate the content on the left, so that the sliding area will be greatly reduced.
Introduction to the IndexList effect on the mobile terminal
js realizes the finger sliding carousel effect on the mobile terminal
How to determine horizontal and vertical screens in mobile HTML5
The above is the detailed content of Detailed explanation of IndexList on mobile terminal. For more information, please follow other related articles on the PHP Chinese website!