Maison >interface Web >js tutoriel >Comment implémenter Picke dans les effets mobiles

Comment implémenter Picke dans les effets mobiles

一个新手
一个新手original
2017-10-12 09:41:552887parcourir

Écrit avant

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 mobilessélecteur

Swiper pour les effets mobiles

Voir le code ici : github

Comment implémenter Picke dans les effets mobiles

1. Analyse de base

1.1 Structure HTML de base


<!--     说明:    
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>

1.2 Initialisation du DOM

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(&#39;#wrapper&#39;);
var animationFrameId = null;
var currentValue;
var itemHeight = 36;
var visibleItemCount = 3;
var valueIndex = 0;
var rotateEffect = true;
var datas = [&#39;1981&#39;, &#39;1982&#39;, &#39;1983&#39;, &#39;...&#39;, &#39;1999&#39;];// 如果支持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(&#39;.Comment implémenter Picke dans les effets mobiles&#39;);
    var Comment implémenter Picke dans les effets mobilesSlot = document.querySelector(&#39;.Comment implémenter Picke dans les effets mobiles-slot&#39;);
    Comment implémenter Picke dans les effets mobiles.classList.add(&#39;Comment implémenter Picke dans les effets mobiles-3d&#39;);
    Comment implémenter Picke dans les effets mobilesSlot.classList.add(&#39;Comment implémenter Picke dans les effets mobiles-slot-absolute&#39;);}// 限定容器高度el.style.height = `${visibleItemCount * itemHeight}px`;// 生成DOMvar html = &#39;&#39;;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(&#39;.Comment implémenter Picke dans les effets mobiles-item&#39;);Comment implémenter Picke dans les effets mobilesItems[valueIndex].classList.add(&#39;Comment implémenter Picke dans les effets mobiles-selected&#39;);

1.3 Événements d'initialisation

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(&#39;touchstart&#39;, startFn); 并没有多大差别 */// 滑动开始// touchstart 和 mousedown 可见对PC端的兼容// onselectstart/ondragstart 直接return 可见排除了拖动和选择element.addEventListener(supportTouch ? &#39;touchstart&#39; : &#39;mousedown&#39;, function(event) {
    if (isDragging) return;
    document.onselectstart = function() { return false; };
    document.ondragstart = function() { return false; };

    // ...});// 滑动结束var endFn = function(event) {
    // 注销事件
    if (!supportTouch) {
        document.removeEventListener(&#39;mousemove&#39;, moveFn);
        document.removeEventListener(&#39;mouseup&#39;, 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) === &#39;[object Opera]&#39;) {
    engine = &#39;presto&#39;;} else if (&#39;MozAppearance&#39; in docStyle) {
    engine = &#39;gecko&#39;;} else if (&#39;WebkitAppearance&#39; in docStyle) {
    engine = &#39;webkit&#39;;} else if (typeof navigator.cpuClass === &#39;string&#39;) {
    engine = &#39;trident&#39;;}// css前缀var cssPrefix = {
    trident: &#39;-ms-&#39;,        // IE
    gecko: &#39;-moz-&#39;,         // FireFox
    webkit: &#39;-webkit-&#39;,     // Chrome/Safari/etc...
    presto: &#39;-o-&#39;           // Opera}[engine];// style前缀var vendorPrefix = {
    trident: &#39;ms&#39;,
    gecko: &#39;Moz&#39;,
    webkit: &#39;Webkit&#39;,
    presto: &#39;O&#39;}[engine];var helpElem = document.createElement(&#39;p&#39;);var perspectiveProperty = vendorPrefix + &#39;Perspective&#39;;var transformProperty = vendorPrefix + &#39;Transform&#39;;var transformStyleName = cssPrefix + &#39;transform&#39;;var transitionProperty = vendorPrefix + &#39;Transition&#39;;var transitionStyleName = cssPrefix + &#39;transition&#39;;var transitionEndProperty = vendorPrefix.toLowerCase() + &#39;TransitionEnd&#39;;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(&#39;dragging&#39;);

    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(&#39;dragging&#39;);
    // 惯性值
    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(&#39;momentumTranslate&#39;, 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.

3DLe 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.

2. Résumé

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn