Heim >Web-Frontend >js-Tutorial >So implementieren Sie den Picker-Effekt in Vue

So implementieren Sie den Picker-Effekt in Vue

亚连
亚连Original
2018-06-22 15:38:284669Durchsuche

Dieser Artikel stellt hauptsächlich die Vue-Implementierung des nativen iOS-Pickereffekts und die Analyse der Implementierungsideen vor. Dieser Artikel stellt Sie ausführlich vor und hat Referenzwert.

Ich war Der erste, der zuvor eines implementiert hat. Es gibt ein ähnliches Zeitauswahl-Plug-In, aber sein Anwendungsbereich ist zu eng. Ich möchte diese Implementierung einfach vor Kurzem veröffentlichen und eine hochgradig wiederverwendbare Vue-Komponente neu schreiben.

Unterstützt Android 4.0 oder höher, Safari 7 oder höher

Effektvorschau

GitHub

Hauptsächlich die Scrollrad-Teil-DOM-Struktur

<template data-filtered="filtered">
 <p class="pd-select-item">
  <p class="pd-select-line"></p>
  <ul class="pd-select-list">
   <li class="pd-select-list-item">1</li>
  </ul>
  <ul class="pd-select-wheel">
   <li class="pd-select-wheel-item">1</li>
  </ul>
 </p>
</template>
props
props: {
   data: {
    type: Array,
    required: true
   },
   type: {
    type: String,
    default: &#39;cycle&#39;
   },
   value: {}
  }

CSS-Stil so einstellen, dass er vertikal zentriert wird

.pd-select-line, .pd-select-list, .pd-select-wheel {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
}
.pd-select-list {
  overflow: hidden;
}

Scroller-3D-Stileinstellung

/* 滚轮盒子 */
.pd-select-wheel {
  transform-style: preserve-3d;
  height: 30px;
}
/* 滚轮单项 */
.pd-select-wheel-item {
  white-space: nowrap;
  text-overflow: ellipsis;
  backface-visibility: hidden;
  position: absolute;
  top: 0px;
  width: 100%;
  overflow: hidden;
}

Achten Sie hauptsächlich auf zwei Attribute: Transformationsstil: Preserve-3D; Rückseitensichtbarkeit: Versteckt;

Das erste ist das 3D-Layout zur Erstellung der Benutzeroberfläche 3D, und die zweite besteht darin, die Schnittstelle 3D zu machen. Die Rückseite des Scrollrads wird automatisch ausgeblendet (der rote Teil im Bild oben, der DOM-Knoten auf der Rückseite wird automatisch ausgeblendet)

So implementieren Sie ein 3D-Scrollrad

Der Hauptsatz der Box ist diese CSS-Transformation: rotation3d(1 , 0, 0, x deg);

item verwendet hauptsächlich dies CSS-Transformation: rotate3d(1, 0, 0, xdeg) translator3d(0px, 0px, [x]px);


Die beiden Bilder oben zeigen den Effekt von translator3d(0px, 0px, [x]px); [x ] ist der Radius des Kreises

As Sie können dem obigen Bild entnehmen, dass wir nur jeden Dom selbst drehen müssen und dann „translate3d(0px, 0px, [x]px)“ verwenden müssen, um jeden Dom zu erweitern. α ist der Winkel Da hier nur 0 bis 180° verwendet werden, wird eine Box verwendet, um diese Doms aufzunehmen

Berechnung der Linienhöhe und des Winkels

Berechnen Sie die Länge der dritten Seite, indem Sie die beiden Seiten und den Winkel kennen~=34px

http ://tool.520101.com/calculator/sanjiaoxingjiaodu/

Unendliche Scrollrad-Implementierung

/* 滚轮展示大小限定 */
spin: {start: 0, end: 9, branch: 9}
 
/* 获取spin 数据 */
 getSpinData (index) {
  index = index % this.listData.length
  return this.listData[index >= 0 ? index : index + this.listData.length]
 }
 /* 模运算 获取数组有的索引 这样就构成 圆环了 */

touchend führt eine spezielle Verarbeitung durch

Setzen Sie den setCSS-Typ in touchend so ein, dass die Bildlaufdaten gerundet werden, sodass, wenn sie stoppt, es wird

genau um jeweils ein Bild gedreht

// other code ....
/* 计算touchEnd移动的整数距离 */
    let endMove = margin
    let endDeg = Math.round(updateDeg / deg) * deg
    if (type === &#39;end&#39;) {
     this.setListTransform(endMove, margin)
     this.setWheelDeg(endDeg)
    } else {
     this.setListTransform(updateMove, margin)
     this.setWheelDeg(updateDeg)
    }
 // other code ....
惯性缓动
// other code ....
setWheelDeg (updateDeg, type, time = 1000) {
    if (type === &#39;end&#39;) {
     this.$refs.wheel.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)`
     this.$refs.wheel.style.webkitTransform = `rotate3d(1, 0, 0, ${updateDeg}deg)`
    } else {
     this.$refs.wheel.style.webkitTransition = &#39;&#39;
     this.$refs.wheel.style.webkitTransform = `rotate3d(1, 0, 0, ${updateDeg}deg)`
    }
   }
setListTransform (translateY = 0, marginTop = 0, type, time = 1000) {
    if (type === &#39;end&#39;) {
     this.$refs.list.style.webkitTransition = `transform ${time}ms cubic-bezier(0.19, 1, 0.22, 1)`
     this.$refs.list.style.webkitTransform = `translateY(${translateY - this.spin.branch * 34}px)`
     this.$refs.list.style.marginTop = `${-marginTop}px`
     this.$refs.list.setAttribute(&#39;scroll&#39;, translateY)
     console.log(&#39;end&#39;)
    } else {
     this.$refs.list.style.webkitTransition = &#39;&#39;
     this.$refs.list.style.webkitTransform = `translateY(${translateY - this.spin.branch * 34}px)`
     this.$refs.list.style.marginTop = `${-marginTop}px`
     this.$refs.list.setAttribute(&#39;scroll&#39;, translateY)
    }
}
// other code ....

Den aktuell ausgewählten Wert abrufen

/* 在设置完css后获取值 */
setStyle (move, type, time) {
  // ...other code
  /* 设置$emit 延迟 */
  setTimeout(() => this.getPickValue(endMove), 1000)
 // ...other code
}
/* 获取选中值 */
   getPickValue (move) {
    let index = Math.abs(move / 34)
    let pickValue = this.getSpinData(index)
    this.$emit(&#39;input&#39;, pickValue)
   }

Anfangseinstellungen

mounted () {
   /* 事件绑定 */
   this.$el.addEventListener(&#39;touchstart&#39;, this.itemTouchStart)
   this.$el.addEventListener(&#39;touchmove&#39;, this.itemTouchMove)
   this.$el.addEventListener(&#39;touchend&#39;, this.itemTouchEnd)
   /* 初始化状态 */
   let index = this.listData.indexOf(this.value)
   if (index === -1) {
    console.warn(&#39;当前初始值不存在,请检查后listData范围!!&#39;)
    this.setListTransform()
    this.getPickValue(0)
   } else {
    let move = index * 34
    /* 因为往上滑动所以是负 */
    this.setStyle(-move)
    this.setListTransform(-move, -move)
   }

Bei Anzeige als nicht unendliches Scrollrad

Hier sind wir sehr Ein gutes Urteil ist, dass der Scrollabstand das Array nicht überschreiten darf Länge der ursprünglichen Zahl * 34 und darf nicht kleiner als 0 sein (Richtung im eigentlichen Code)

/* 根据滚轮类型 line or cycle 判断 updateMove最大距离 */
    if (this.type === &#39;line&#39;) {
     if (updateMove > 0) {
      updateMove = 0
     }
     if (updateMove < -(this.listData.length - 1) * singleHeight) {
      updateMove = -(this.listData.length - 1) * singleHeight
     }
    }
 /* 根据type 控制滚轮显示效果 */
   setHidden (index) {
    if (this.type === &#39;line&#39;) {
     return index < 0 || index > this.listData.length - 1
    } else {
     return false
    }
   },

Die Dom-Struktur fügt auch eine entsprechende Antwort hinzu

<p class="pd-select-item">
  <p class="pd-select-line"></p>
  <p class="pd-select-list">
   <ul class="pd-select-ul" ref="list">
    <li class="pd-select-list-item" v-for="el,index in renderData " :class="{&#39;hidden&#39;:setHidden(el.index)}" :key="index">{{el.value}}</li>
   </ul>
  </p>
  <ul class="pd-select-wheel" ref="wheel">
   <li class="pd-select-wheel-item" :class="{&#39;hidden&#39;:setHidden(el.index)}" :style="setWheelItemDeg(el.index)" :index="el.index" v-for="el,index in renderData " :key="index">{{el.value}}</li>
  </ul>
 </p>
Ich habe das Obige für Sie zusammengestellt und hoffe, dass es Ihnen in Zukunft hilfreich sein wird.

Verwandte Artikel:

JavaScript-Moduloptimierung

So extrahieren Sie Bibliotheken von Drittanbietern mit Webpack

So ermitteln Sie den Client-Typ mithilfe von JS

Das obige ist der detaillierte Inhalt vonSo implementieren Sie den Picker-Effekt in Vue. 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