Maison >interface Web >js tutoriel >Comment implémenter Picke dans les effets mobiles
Suite aux recherches précédentes sur les effets mobiles, examinons cette fois le principe de mise en œuvre du Comment implémenter Picke dans les effets mobiles
sélecteur
Swiper pour les effets mobiles
Voir le code ici : github
<!-- 说明: 1. 类 Comment implémenter Picke dans les effets mobiles-3d 是为了提供3d视角,如果不需要可以去掉 2. 类 Comment implémenter Picke dans les effets mobiles-slot-absolute 在3d视角中需要加上,因为下面相对定位的 Comment implémenter Picke dans les effets mobiles-items 是要相对父容器进行 transform的,如果不加,就会造成位移不正确 3. DOM中所有的style样式都是在初始化的时候加上的--><p class="Comment implémenter Picke dans les effets mobiles Comment implémenter Picke dans les effets mobiles-3d"> <p class="Comment implémenter Picke dans les effets mobiles-items"> <p class="Comment implémenter Picke dans les effets mobiles-slot Comment implémenter Picke dans les effets mobiles-slot-absolute" style="flex:1;"> <p class="Comment implémenter Picke dans les effets mobiles-slot-wrapper" id="wrapper" style="height: 108px;"> <p class="Comment implémenter Picke dans les effets mobiles-item Comment implémenter Picke dans les effets mobiles-selected" style="height:36px;line-height: 36px">1981</p> <!-- ... --> <p class="Comment implémenter Picke dans les effets mobiles-item" style="height:36px;line-height: 36px">1999</p> </p> </p> </p> <p class="Comment implémenter Picke dans les effets mobiles-center-highlight" style="height:36px;margin-top:-18px;"></p></p>
Puisque le Comment implémenter Picke dans les effets mobiles
dans le code source d'Ele.me est généré à l'aide de l'v-for
instructionDOM
, j'utilise donc simplement javascript
pour le simuler iciDOM
de génération.
var el = document.querySelector('#wrapper'); var animationFrameId = null; var currentValue; var itemHeight = 36; var visibleItemCount = 3; var valueIndex = 0; var rotateEffect = true; var datas = ['1981', '1982', '1983', '...', '1999'];// 如果支持3d视角,则给<p class="Comment implémenter Picke dans les effets mobiles"></p>加上类"Comment implémenter Picke dans les effets mobiles-3d"// <p class="Comment implémenter Picke dans les effets mobiles-slot" style="flex:1;">加上类"Comment implémenter Picke dans les effets mobiles-slot-absolute"if (rotateEffect) { var Comment implémenter Picke dans les effets mobiles = document.querySelector('.Comment implémenter Picke dans les effets mobiles'); var Comment implémenter Picke dans les effets mobilesSlot = document.querySelector('.Comment implémenter Picke dans les effets mobiles-slot'); Comment implémenter Picke dans les effets mobiles.classList.add('Comment implémenter Picke dans les effets mobiles-3d'); Comment implémenter Picke dans les effets mobilesSlot.classList.add('Comment implémenter Picke dans les effets mobiles-slot-absolute');}// 限定容器高度el.style.height = `${visibleItemCount * itemHeight}px`;// 生成DOMvar html = '';datas.forEach(function(data, index) { html += `<p class="Comment implémenter Picke dans les effets mobiles-item" style="height:36px;line-height:36px;">${data}</p>`;});el.innerHTML = html;// 激活当前itemvar Comment implémenter Picke dans les effets mobilesItems = document.querySelectorAll('.Comment implémenter Picke dans les effets mobiles-item');Comment implémenter Picke dans les effets mobilesItems[valueIndex].classList.add('Comment implémenter Picke dans les effets mobiles-selected');
De manière générale, les événements de Comment implémenter Picke dans les effets mobiles
incluent également le début, le glissement et la fin du glissement. Puisqu’il s’agit après tout d’un appareil mobile, le glissement est inévitable. Cette fois, l'événement de glissement est encapsulé dans le code source, compatible avec la fin PC
, et élimine l'impact du glisser et de la sélection. Regardons de plus près l'analyse. `
/** * draggable.js * 只是起到一定的兼容性 * 实质和直接调用 el.addEventListener('touchstart', startFn); 并没有多大差别 */// 滑动开始// touchstart 和 mousedown 可见对PC端的兼容// onselectstart/ondragstart 直接return 可见排除了拖动和选择element.addEventListener(supportTouch ? 'touchstart' : 'mousedown', function(event) { if (isDragging) return; document.onselectstart = function() { return false; }; document.ondragstart = function() { return false; }; // ...});// 滑动结束var endFn = function(event) { // 注销事件 if (!supportTouch) { document.removeEventListener('mousemove', moveFn); document.removeEventListener('mouseup', endFn); } document.onselectstart = null; document.ondragstart = null; isDragging = false; if (options.end) { options.end(supportTouch ? event.changedTouches[0] || event.touches[0] : event); }}
Si DOM
suit votre glissement sur l'écran du téléphone, la méthode est similaire. Il ne s'agit que d'enregistrer la position de départ lorsque vous commencez à glisser, et le calculant en temps réel pendant le déplacement, une fois le glissement terminé, DOM
glissera vers la position où il devrait glisser. Pour ce point, veuillez vous référer à l'article précédent Swiper pour les effets mobiles. Cet article a la même méthode. Ici on se concentre sur les différences
// 滑动开始的执行事件方法start: function(event) { dragState = { range: getDragRange(), // ... startTranslateTop: translateUtil.getElementTranslate(el).top };}
Il existe deux méthodes, la première getDragRange
et la seconde getElementTranslate(el)
.
La première fonction est d'obtenir le déplacement minimum et maximum que Comment implémenter Picke dans les effets mobiles
peut glisser, qui sera utilisé lors de l'événement de fin de glissement. Concernant la façon de calculer, voici une brève mention : en glissant vers le bas, le maximum ne peut pas dépasser le haut du milieu item
, c'est pourquoi itemHeight * Math.floor(visibleItemCount / 2)
, tandis qu'en glissant vers le haut, le maximum ne peut pas dépasser le bas du milieu item
🎜>, -itemHeight * (valuesLength - Math.ceil(visibleItemCount / 2))
, réfléchissez-y bien.
La deuxième fonction est d'obtenir la Comment implémenter Picke dans les effets mobiles
valeur du courant transform
comme base du prochain calcul glissant. En fait, cela semble assez gênant, car la valeur touchend
sera définitivement calculée dans translate
à la fin. Nous n'avons besoin que de sauvegarder la dernière valeur de mouvement coulissant à chaque fois, au lieu de la récupérer dans DOM
. à chaque fois.
/** * translateUtil * 对浏览器对前缀支持的一些判断 * 检测浏览器对3d属性的支持情况 * 获取当前的translate值/清空Comment implémenter Picke dans les effets mobiles的translate值/移动Comment implémenter Picke dans les effets mobiles * 对于浏览器的检测方面,这也算是一个比较好的工具类 */var docStyle = document.documentElement.style;var engine;var translate3d = false;// 浏览器判断if (window.opera && Object.prototype.toString.call(opera) === '[object Opera]') { engine = 'presto';} else if ('MozAppearance' in docStyle) { engine = 'gecko';} else if ('WebkitAppearance' in docStyle) { engine = 'webkit';} else if (typeof navigator.cpuClass === 'string') { engine = 'trident';}// css前缀var cssPrefix = { trident: '-ms-', // IE gecko: '-moz-', // FireFox webkit: '-webkit-', // Chrome/Safari/etc... presto: '-o-' // Opera}[engine];// style前缀var vendorPrefix = { trident: 'ms', gecko: 'Moz', webkit: 'Webkit', presto: 'O'}[engine];var helpElem = document.createElement('p');var perspectiveProperty = vendorPrefix + 'Perspective';var transformProperty = vendorPrefix + 'Transform';var transformStyleName = cssPrefix + 'transform';var transitionProperty = vendorPrefix + 'Transition';var transitionStyleName = cssPrefix + 'transition';var transitionEndProperty = vendorPrefix.toLowerCase() + 'TransitionEnd';if (helpElem.style[perspectiveProperty] !== undefined) { translate3d = true;}// 讲一下这个正则// \s*(-?\d+(\.\d+?)?)px 这是一个单元,匹配这样的 -23.15px, 剩下的应该就好理解了var regexp = /translate\(\s*(-?\d+(\.\d+?)?)px,\s*(-?\d+(\.\d+?)?)px\)\s*translateZ\(0px\)/ig;
Regardez ensuite le coulissant
drag: function(event) { // 加上 dragging 类是为了清除过渡效果,在swiper中也有同样的应用 el.classList.add('dragging'); dragState.left = event.pageX; dragState.top = event.pageY; var deltaY = dragState.top - dragState.startTop; // 计算当前的滑动位移 var translate = dragState.startTranslateTop + deltaY; // 滑动元素 translateUtil.translateElement(el, null, translate); velocityTranslate = translate - prevTranslate || translate; prevTranslate = translate; if (rotateEffect) { updateRotate(prevTranslate, Comment implémenter Picke dans les effets mobilesItems); }}
Voir Il y a See More a velocityTranslate
dans le code ci-dessus. Cette valeur a un effet magique. Je ne la connaissais pas au début, j'ai découvert plus tard qu'elle était utilisée une fois le glissement terminé, puis j'ai réalisé qu'elle représentait une valeur de déplacement. d'un taux. Qu’est-ce que la vitesse ? Tout comme lorsque vous glissez rapidement, vous espérez toujours qu'il puisse glisser avec inertie. Cette valeur multipliée par une valeur d'inertie peut obtenir un déplacement inertiel. Regardez le code dans end
.
end: function() { // 添加过渡 el.classList.remove('dragging'); // 惯性值 var momentumRatio = 7; var currentTranslate = translateUtil.getElementTranslate(el).top; var duration = new Date() - dragState.start; var momentumTranslate; if (duration < 300) { momentumTranslate = currentTranslate + velocityTranslate * momentumRatio; } // 加上惯性速率之后的位移值 console.log('momentumTranslate', momentumTranslate); dragRange = dragState.range; setTimeout(function() { var translate; if (momentumTranslate) { translate = Math.round(momentumTranslate / itemHeight) * itemHeight; } else { translate = Math.round(currentTranslate / itemHeight) * itemHeight; } // 取得最终的位移值, // 必须为itemHeight的倍数 // 在范围的最大值和最小值中取 translate = Math.max(Math.min(translate, dragRange[1]), dragRange[0]); translateUtil.translateElement(el, null, translate); // 计算得出当前位移下应该对应的实际值 currentValue = translate2Value(translate); // 3d效果 if (rotateEffect) { planUpdateRotate(); } }, 10); dragState = {};}
Il s'agit du processus de mise en œuvre de l'ensemble du Comment implémenter Picke dans les effets mobiles
, vous pouvez l'utiliser sans l'effet 3d
. Voyons comment obtenir l'effet 3D
. Il y a une initialisation initiale dans doOnValuesChange
.
[].forEach.call(items, function(item, index) { translateUtil.translateElement(item, null, itemHeight * index);});
définit une valeur de déplacement basée sur l'indice pour chaque item
A ce moment, le positionnement de chaque item
doit être celui de absolute
. , pour qu'ils soient côte à côte après le déplacement, sinon il peut y avoir un espace itemHeight
au milieu.
3D
Le point le plus critique de l'effet est de savoir comment calculer l'angle de retournement. Un objet constant est défini dans le code source :
var VISIBEL_ITEMS_ANGLE_MAP = { 3: -45, 5: -20, 7: -15};
Vous pouvez voir que lorsqu'il n'y a que 3 éléments visibles, la partie en surbrillance est parallèle au X
axe , le item
précédent doit être tourné de 45 degrés dans le sens des aiguilles d'une montre autour de l'axe X
, et le item
suivant doit être tourné de 45 degrés dans le sens inverse des aiguilles d'une montre autour de l'axe X
. De plus, il y a une section de code qui est particulièrement alambiquée D'après ma compréhension, elle est la suivante :
// 当前item相对于顶部原本应该有的位移值var itemOffsetTop = index * itemHeight; // 滑动过程中,相对于最开始的位置滑动的位移值var translateOffset = dragRange[1] - currentTranslate;// 当应该有的位移值和滑动的位移值相等的时候,也就说明了当前的`item`被选中// 也就是说此时当前的角度为0var itemOffset = itemOffsetTop - translateOffset;var percentage = itemOffset / itemHeight;var angle = angleUnit * percentage;if (angle > 180) angle = 180;if (angle < -180) angle = -180;rotateElement(item, angle);
Si vous pensez que c'est trop alambiqué, il n'est en fait pas nécessaire de suivre son approche. Allez, il nous suffit de trouver un moyen de déterminer si chaque item
est dans la position précédente ou suivante par rapport au item
actuellement sélectionné, et nous pouvons calculer l'angle en fonction. à ce sujet.
J'ai vu tellement de choses sur le composant Comment implémenter Picke dans les effets mobiles
dans Ele.me Dans l'ensemble, il est très similaire au glissement dans swiper
. la fin. Calculez la valeur de déplacement et faites-la glisser vers la bonne position en fonction de la valeur de déplacement, en fait, l'implémentation de tout le monde peut être similaire, et il n'est pas nécessaire de suivre le code source. ajoutez votre propre compréhension de manière appropriée, alors peut-être que l'écriture de code devient plus confortable. Ceci est juste une petite compréhension personnelle, j'espère que cela pourra m'aider, ainsi qu'à tout le monde.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!