Heim  >  Artikel  >  Web-Frontend  >  So implementieren Sie Picke in mobilen Effekten

So implementieren Sie Picke in mobilen Effekten

一个新手
一个新手Original
2017-10-12 09:41:552786Durchsuche

Vorher geschrieben

Im Anschluss an die vorherige Forschung zu mobilen Effekten werfen wir dieses Mal einen Blick auf das Implementierungsprinzip des So implementieren Sie Picke in mobilen EffektenSelektors

Swiper für mobile Effekte

Siehe den Code hier: github

So implementieren Sie Picke in mobilen Effekten

1. Kernanalyse

1.1 Grundlegende HTML-Struktur


<!--     说明:    
1. 类 So implementieren Sie Picke in mobilen Effekten-3d 是为了提供3d视角,如果不需要可以去掉    
2. 类 So implementieren Sie Picke in mobilen Effekten-slot-absolute 在3d视角中需要加上,因为下面相对定位的 So implementieren Sie Picke in mobilen Effekten-items 是要相对父容器进行    transform的,如果不加,就会造成位移不正确    3. DOM中所有的style样式都是在初始化的时候加上的--><p class="So implementieren Sie Picke in mobilen Effekten So implementieren Sie Picke in mobilen Effekten-3d">
    <p class="So implementieren Sie Picke in mobilen Effekten-items">
        <p class="So implementieren Sie Picke in mobilen Effekten-slot So implementieren Sie Picke in mobilen Effekten-slot-absolute" style="flex:1;">
            <p class="So implementieren Sie Picke in mobilen Effekten-slot-wrapper" id="wrapper" style="height: 108px;">
                <p class="So implementieren Sie Picke in mobilen Effekten-item So implementieren Sie Picke in mobilen Effekten-selected" style="height:36px;line-height: 36px">1981</p>
                <!-- ... -->
                <p class="So implementieren Sie Picke in mobilen Effekten-item" style="height:36px;line-height: 36px">1999</p>
            </p>
        </p>
    </p>
    <p class="So implementieren Sie Picke in mobilen Effekten-center-highlight" style="height:36px;margin-top:-18px;"></p></p>

1.2 DOM initialisieren

Da das So implementieren Sie Picke in mobilen Effekten im Ele.me-Quellcode mit der v-for-AnweisungDOM generiert wird, verwende ich einfach javascript, um es hier zu simulierenDOM der Generation.


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="So implementieren Sie Picke in mobilen Effekten"></p>加上类"So implementieren Sie Picke in mobilen Effekten-3d"// <p class="So implementieren Sie Picke in mobilen Effekten-slot" style="flex:1;">加上类"So implementieren Sie Picke in mobilen Effekten-slot-absolute"if (rotateEffect) {
    var So implementieren Sie Picke in mobilen Effekten = document.querySelector(&#39;.So implementieren Sie Picke in mobilen Effekten&#39;);
    var So implementieren Sie Picke in mobilen EffektenSlot = document.querySelector(&#39;.So implementieren Sie Picke in mobilen Effekten-slot&#39;);
    So implementieren Sie Picke in mobilen Effekten.classList.add(&#39;So implementieren Sie Picke in mobilen Effekten-3d&#39;);
    So implementieren Sie Picke in mobilen EffektenSlot.classList.add(&#39;So implementieren Sie Picke in mobilen Effekten-slot-absolute&#39;);}// 限定容器高度el.style.height = `${visibleItemCount * itemHeight}px`;// 生成DOMvar html = &#39;&#39;;datas.forEach(function(data, index) {
    html += `<p class="So implementieren Sie Picke in mobilen Effekten-item" style="height:36px;line-height:36px;">${data}</p>`;});el.innerHTML = html;// 激活当前itemvar So implementieren Sie Picke in mobilen EffektenItems = document.querySelectorAll(&#39;.So implementieren Sie Picke in mobilen Effekten-item&#39;);So implementieren Sie Picke in mobilen EffektenItems[valueIndex].classList.add(&#39;So implementieren Sie Picke in mobilen Effekten-selected&#39;);

1.3 Initialisierungsereignisse

Im Allgemeinen umfassen die Ereignisse von So implementieren Sie Picke in mobilen Effekten auch Gleitstart, Gleitende und Gleitende. Da es sich schließlich um ein mobiles Gerät handelt, ist ein Verrutschen unvermeidlich. Dieses Mal ist das Schiebeereignis im Quellcode gekapselt, kompatibel mit dem PC-Ende und eliminiert die Auswirkungen von Ziehen und Auswählen. Schauen wir uns die Analyse genauer an. `


/**  * 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);
    }}

Wenn DOM Ihrem Gleiten auf dem Telefonbildschirm folgt, ist die Methode ähnlich. Es handelt sich lediglich um die Aufzeichnung der Startposition, wenn Sie mit dem Gleiten beginnen. und berechnet es in Echtzeit während des Gleitens. Nachdem das Gleiten abgeschlossen ist, gleitet DOM an die Position, an der es gleiten soll. Zu diesem Punkt lesen Sie bitte den vorherigen Artikel Swiper für mobile Effekte. Dieser Artikel verwendet die gleiche Methode. Hier konzentrieren wir uns auf die Unterschiede


// 滑动开始的执行事件方法start: function(event) {
    dragState = {
        range: getDragRange(),
        // ...
        startTranslateTop: translateUtil.getElementTranslate(el).top
    };}

Es gibt zwei Methoden, die erste getDragRange und die zweite getElementTranslate(el).

  • Die erste Funktion besteht darin, die minimale und maximale Verschiebung zu ermitteln, die So implementieren Sie Picke in mobilen Effekten gleiten kann und die im Gleitende-Ereignis verwendet wird. Zur Berechnung hier kurz erwähnt: Beim Abwärtsgleiten darf das Maximum den oberen Rand der Mitte nicht überschreiten item, weshalb itemHeight * Math.floor(visibleItemCount / 2), während beim Aufwärtsgleiten das Maximum den unteren Rand der Mitte nicht überschreiten darf item, -itemHeight * (valuesLength - Math.ceil(visibleItemCount / 2)), denk einfach gut darüber nach.

  • Die zweite Funktion besteht darin, den So implementieren Sie Picke in mobilen EffektenWert des aktuellen transform als Grundlage für die nächste gleitende Berechnung zu erhalten. Tatsächlich scheint dies ziemlich mühsam zu sein, da der touchend-Wert am Ende definitiv in translate berechnet wird. Wir müssen jedes Mal nur den letzten Gleitbewegungswert speichern, anstatt ihn in DOM abzurufen jedes Mal.


/** * translateUtil * 对浏览器对前缀支持的一些判断 * 检测浏览器对3d属性的支持情况 * 获取当前的translate值/清空So implementieren Sie Picke in mobilen Effekten的translate值/移动So implementieren Sie Picke in mobilen Effekten * 对于浏览器的检测方面,这也算是一个比较好的工具类 */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;

Schauen Sie sich als nächstes die Schiebetür an


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, So implementieren Sie Picke in mobilen EffektenItems);
    }}

Siehe Da ist a velocityTranslate im obigen Code. Ich wusste zunächst nicht, dass er verwendet wurde, nachdem das Gleiten abgeschlossen war, und erkannte dann, dass es sich um einen Verschiebungswert handelt einer Rate. Was ist Geschwindigkeit? Genau wie beim schnellen Gleiten hofft man immer, dass es mit der Trägheit gleiten kann. Dieser Wert multipliziert mit einem Trägheitswert kann eine Trägheitsverschiebung ergeben. Schauen Sie sich den Code in end an.


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 = {};}

Dies ist der Implementierungsprozess des gesamten So implementieren Sie Picke in mobilen Effekten, Sie können ihn ohne den 3d-Effekt verwenden. Schauen wir uns an, wie man den 3D-Effekt erzielt. Es gibt eine Erstinitialisierung in doOnValuesChange.


[].forEach.call(items, function(item, index) {
    translateUtil.translateElement(item, null, itemHeight * index);});

legt einen Verschiebungswert basierend auf dem Index für jedes item fest. Zu diesem Zeitpunkt muss die Positionierung jedes item der von absolute entsprechen , sodass sie nach der Verschiebung nebeneinander liegen, ansonsten kann in der Mitte ein itemHeight Leerzeichen stehen.

3DDer kritischste Punkt im Effekt ist die Berechnung des Flipwinkels. Im Quellcode ist ein konstantes Objekt definiert:


var VISIBEL_ITEMS_ANGLE_MAP = {
    3: -45,
    5: -20,
    7: -15};

Sie können sehen, dass der hervorgehobene Teil parallel zum X verläuft, wenn nur 3 sichtbare Elemente vorhanden sind axis muss das vorherige item um 45 Grad im Uhrzeigersinn um die X-Achse gedreht werden, und das nächste item muss um 45 Grad gegen den Uhrzeigersinn um die X-Achse gedreht werden. Darüber hinaus gibt es einen Codeabschnitt, der nach meinem Verständnis wie folgt lautet:


// 当前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);

Wenn Sie denken, dass er zu kompliziert ist, Eigentlich ist es nicht nötig, seinem Ansatz zu folgen. Wir müssen nur einen Weg finden, um zu bestimmen, ob sich jedes item in der vorherigen oder nächsten Position relativ zum aktuell ausgewählten item befindet, und wir können den Winkel darauf basierend berechnen Das.

2. Zusammenfassung

Ich habe so viel über die So implementieren Sie Picke in mobilen Effekten-Komponente in Ele.me gesehen. Insgesamt ist sie dem Schieben in swiper sehr ähnlich Berechnen Sie am Ende den Verschiebungswert und verschieben Sie ihn auf der Grundlage des Verschiebungswerts an die richtige Position. Tatsächlich ist die Implementierung bei allen ähnlich und es ist nicht erforderlich, den Quellcode zu befolgen Fügen Sie Ihr eigenes Verständnis entsprechend hinzu, sodass das Schreiben von Code möglicherweise komfortabler wird. Dies ist nur ein kleines persönliches Verständnis, ich hoffe, es kann mir und allen etwas helfen.

Das obige ist der detaillierte Inhalt vonSo implementieren Sie Picke in mobilen Effekten. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn