Maison interface Web js tutoriel Créer un composant de pile coulissante en utilisant vue (tutoriel détaillé)

Créer un composant de pile coulissante en utilisant vue (tutoriel détaillé)

Jun 01, 2018 am 09:13 AM
制作 empiler 滑动

Le composant coulissant empilé de Tantan joue un rôle clé. Voyons comment utiliser Vue pour écrire un composant empilé Tantan. Les amis intéressés peuvent y jeter un œil ensemble

Le rendu est le suivant :

Avant-propos

Bonjour, dis que Tantan doit être familier à tous les programmeurs (après tout, il y a beaucoup de filles). Les composants coulissants empilés de Tantan jouent un rôle clé dans la capacité de transformer les marques en douceur. Voyons comment écrire un composant Stacking Tantan

.

1. Analyse fonctionnelle

Après une utilisation simple, vous constaterez que la fonction coulissante d'empilement est très simple, utilisez simplement une image Le résumé est :

Un bref résumé des points fonctionnels de base inclus :

  • Empilage d'images

  • Glisser la première image

  • Glisser une fois la condition réussie, rebondir après l'échec de la condition

  • Glisser L'image suivante est empilée vers le haut

  • Optimisation de l'expérience

  • Selon les différents points de contact, la première image sera décalée sous différents angles lors du glissement

  • Déterminer si la zone de décalage a réussi à glisser

Mise en œuvre spécifique

Avec les points fonctionnels résumés, notre idée de mise en œuvre des composants sera plus claire

1 Effet d'empilage

L'effet d'image d'empilement est disponible en ligne. Dans un grand nombre d'exemples, les méthodes de mise en œuvre sont similaires, principalement en définissant la perspective et l'origine de la perspective sur le calque parent pour obtenir la perspective de la sous-couche. Après avoir défini la valeur de l'axe Z Translate3d sur la sous-couche, l'empilement. L'effet peut être simulé. Le code spécifique est le suivant

// 图片堆叠dom
 <!--opacity: 0 隐藏我们不想看到的stack-item层级-->
 <!--z-index: -1 调整stack-item层级"-->
<ul class="stack">
 <li class="stack-item" style="transform: translate3d(0px, 0px, 0px);opacity: 1;z-index: 10;"><img src="1.png" alt="01"></li>
 <li class="stack-item" style="transform: translate3d(0px, 0px, -60px);opacity: 1;z-index: 1"><img src="2.png" alt="02"></li>
 <li class="stack-item" style="transform: translate3d(0px, 0px, -120px);opacity: 1;z-index: 1"><img src="3.png" alt="03"></li>
 <li class="stack-item" style="transform: translate3d(0px, 0px, -180px);opacity: 0;z-index: -1"><img src="4.png" alt="04"></li>
 <li class="stack-item" style="transform: translate3d(0px, 0px, -180px);opacity: 0;z-index: -1"><img src="5.png" alt="05"></li>
</ul>
<style>
.stack {
 width: 100%;
 height: 100%;
 position: relative;
 perspective: 1000px; //子元素视距
 perspective-origin: 50% 150%; //子元素透视位置
 -webkit-perspective: 1000px;
 -webkit-perspective-origin: 50% 150%;
 margin: 0;
 padding: 0;
 }
 .stack-item{
 background: #fff;
 height: 100%;
 width: 100%;
 border-radius: 4px;
 text-align: center;
 overflow: hidden;
 }
 .stack-item img {
 width: 100%;
 display: block;
 pointer-events: none;
 }
</style>
Copier après la connexion

Ce qui précède n'est qu'un ensemble de code statique. Ce que nous espérons obtenir est une vue. composant, nous devons donc d'abord créer un modèle de composant stack.vue. Dans le modèle, nous pouvons utiliser v-for pour parcourir le nœud de pile et utiliser :style pour modifier le style de chaque élément. Le code est le suivant

<. 🎜>

<template>
 <ul class="stack">
  <li class="stack-item" v-for="(item, index) in pages" :style="[transform(index)]">
  <img :src="item.src">
  </li>
 </ul>
</template>
<script>
export default {
 props: {
 // pages数据包含基础的图片数据
 pages: {
  type: Array,
  default: []
 }
 },
 data () {
 return {
  // basicdata数据包含组件基本数据
  basicdata: {
  currentPage: 0 // 默认首图的序列
  },
  // temporaryData数据包含组件临时数据
  temporaryData: {
  opacity: 1, // 记录opacity
  zIndex: 10, // 记录zIndex
  visible: 3 // 记录默认显示堆叠数visible
  }
 }
 },
 methods: {
 // 遍历样式
 transform (index) {
  if (index >= this.basicdata.currentPage) {
  let style = {}
  let visible = this.temporaryData.visible
  let perIndex = index - this.basicdata.currentPage
  // visible可见数量前滑块的样式
  if (index <= this.basicdata.currentPage + visible - 1) {
   style[&#39;opacity&#39;] = &#39;1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * perIndex * 60 + &#39;px&#39; + &#39;)&#39;
   style[&#39;zIndex&#39;] = visible - index + this.basicdata.currentPage
   style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
   style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  } else {
   style[&#39;zIndex&#39;] = &#39;-1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * visible * 60 + &#39;px&#39; + &#39;)&#39;
  }
  return style
  }
 }
 }
}
</script>
Copier après la connexion

Clic clé

 : style pour lier des objets ainsi que des tableaux et des fonctions, qui est très utile lors de la traversée

La structure dom la plus basique a été construite, ensuite La première étape consiste à faire "bouger" la première image

2. Glissement de l'image

L'effet de glissement d'image apparaît dans de nombreuses scènes. Son principe n'est rien de plus que de surveiller l'événement tactile, d'obtenir le déplacement, puis de modifier le déplacement cible via Translate3D, les étapes que nous souhaitons mettre en œuvre sont donc les suivantes

<🎜. >

    Lier l'événement Touchs à la pile
  • Surveiller et stocker les valeurs des changements de position des gestes
  • Changer les valeurs x, y de translate3D dans l'attribut css de la première image
  • #### Implémentation spécifique

Dans le framework vue, ce n'est pas recommandé pour faire fonctionner les nœuds directement, mais pour lier les éléments via l'instruction v-on, nous écrivons donc toutes les liaisons dans v-for traversal et les jugeons via index. Qu'il s'agisse de la première image, utilisez :style pour modifier le style de la page d'accueil. le code spécifique est le suivant :

<template>
 <ul class="stack">
  <li class="stack-item" v-for="(item, index) in pages"
  :style="[transformIndex(index),transform(index)]"
  @touchstart.stop.capture="touchstart"
  @touchmove.stop.capture="touchmove"
  @touchend.stop.capture="touchend"
  @mousedown.stop.capture="touchstart"
  @mouseup.stop.capture="touchend"
  @mousemove.stop.capture="touchmove">
  <img :src="item.src">
  </li>
 </ul>
</template>
<script>
export default {
 props: {
 // pages数据包含基础的图片数据
 pages: {
  type: Array,
  default: []
 }
 },
 data () {
 return {
  // basicdata数据包含组件基本数据
  basicdata: {
  start: {}, // 记录起始位置
  end: {}, // 记录终点位置
  currentPage: 0 // 默认首图的序列
  },
  // temporaryData数据包含组件临时数据
  temporaryData: {
  poswidth: &#39;&#39;, // 记录位移
  posheight: &#39;&#39;, // 记录位移
  tracking: false // 是否在滑动,防止多次操作,影响体验
  }
 }
 },
 methods: {
 touchstart (e) {
  if (this.temporaryData.tracking) {
  return
  }
  // 是否为touch
  if (e.type === &#39;touchstart&#39;) {
  if (e.touches.length > 1) {
   this.temporaryData.tracking = false
   return
  } else {
   // 记录起始位置
   this.basicdata.start.t = new Date().getTime()
   this.basicdata.start.x = e.targetTouches[0].clientX
   this.basicdata.start.y = e.targetTouches[0].clientY
   this.basicdata.end.x = e.targetTouches[0].clientX
   this.basicdata.end.y = e.targetTouches[0].clientY
  }
  // pc操作
  } else {
  this.basicdata.start.t = new Date().getTime()
  this.basicdata.start.x = e.clientX
  this.basicdata.start.y = e.clientY
  this.basicdata.end.x = e.clientX
  this.basicdata.end.y = e.clientY
  }
  this.temporaryData.tracking = true
 },
 touchmove (e) {
  // 记录滑动位置
  if (this.temporaryData.tracking && !this.temporaryData.animation) {
  if (e.type === &#39;touchmove&#39;) {
   this.basicdata.end.x = e.targetTouches[0].clientX
   this.basicdata.end.y = e.targetTouches[0].clientY
  } else {
   this.basicdata.end.x = e.clientX
   this.basicdata.end.y = e.clientY
  }
  // 计算滑动值
  this.temporaryData.poswidth = this.basicdata.end.x - this.basicdata.start.x
  this.temporaryData.posheight = this.basicdata.end.y - this.basicdata.start.y
  }
 },
 touchend (e) {
  this.temporaryData.tracking = false
  // 滑动结束,触发判断
 },
 // 非首页样式切换
 transform (index) {
  if (index > this.basicdata.currentPage) {
  let style = {}
  let visible = 3
  let perIndex = index - this.basicdata.currentPage
  // visible可见数量前滑块的样式
  if (index <= this.basicdata.currentPage + visible - 1) {
   style[&#39;opacity&#39;] = &#39;1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * perIndex * 60 + &#39;px&#39; + &#39;)&#39;
   style[&#39;zIndex&#39;] = visible - index + this.basicdata.currentPage
   style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
   style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  } else {
   style[&#39;zIndex&#39;] = &#39;-1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * visible * 60 + &#39;px&#39; + &#39;)&#39;
  }
  return style
  }
 },
 // 首页样式切换
 transformIndex (index) {
  // 处理3D效果
  if (index === this.basicdata.currentPage) {
  let style = {}
  style[&#39;transform&#39;] = &#39;translate3D(&#39; + this.temporaryData.poswidth + &#39;px&#39; + &#39;,&#39; + this.temporaryData.posheight + &#39;px&#39; + &#39;,0px)&#39;
  style[&#39;opacity&#39;] = 1
  style[&#39;zIndex&#39;] = 10
  return style
  }
 }
 }
}
</script>
Copier après la connexion

3. Glisser une fois la condition réussie, le rebond après l'échec de la condition

Le jugement déclencheur de la condition est effectué après le toucher/mouseup. Ici, nous utilisons d'abord des conditions simples pour juger, et en même temps donnons les premiers effets de pop-up et de rebond d'image. Le code est le suivant <🎜. >

<template>
 <ul class="stack">
  <li class="stack-item" v-for="(item, index) in pages"
  :style="[transformIndex(index),transform(index)]"
  @touchmove.stop.capture="touchmove"
  @touchstart.stop.capture="touchstart"
  @touchend.stop.capture="touchend"
  @mousedown.stop.capture="touchstart"
  @mouseup.stop.capture="touchend"
  @mousemove.stop.capture="touchmove">
  <img :src="item.src">
  </li>
 </ul>
</template>
<script>
export default {
 props: {
  // pages数据包含基础的图片数据
 pages: {
  type: Array,
  default: []
 }
 },
 data () {
 return {
  // basicdata数据包含组件基本数据
  basicdata: {
  start: {}, // 记录起始位置
  end: {}, // 记录终点位置
  currentPage: 0 // 默认首图的序列
  },
  // temporaryData数据包含组件临时数据
  temporaryData: {
  poswidth: &#39;&#39;, // 记录位移
  posheight: &#39;&#39;, // 记录位移
  tracking: false, // 是否在滑动,防止多次操作,影响体验
  animation: false, // 首图是否启用动画效果,默认为否
  opacity: 1 // 记录首图透明度
  }
 }
 },
 methods: {
 touchstart (e) {
  if (this.temporaryData.tracking) {
  return
  }
  // 是否为touch
  if (e.type === &#39;touchstart&#39;) {
  if (e.touches.length > 1) {
   this.temporaryData.tracking = false
   return
  } else {
   // 记录起始位置
   this.basicdata.start.t = new Date().getTime()
   this.basicdata.start.x = e.targetTouches[0].clientX
   this.basicdata.start.y = e.targetTouches[0].clientY
   this.basicdata.end.x = e.targetTouches[0].clientX
   this.basicdata.end.y = e.targetTouches[0].clientY
  }
  // pc操作
  } else {
  this.basicdata.start.t = new Date().getTime()
  this.basicdata.start.x = e.clientX
  this.basicdata.start.y = e.clientY
  this.basicdata.end.x = e.clientX
  this.basicdata.end.y = e.clientY
  }
  this.temporaryData.tracking = true
  this.temporaryData.animation = false
 },
 touchmove (e) {
  // 记录滑动位置
  if (this.temporaryData.tracking && !this.temporaryData.animation) {
  if (e.type === &#39;touchmove&#39;) {
   this.basicdata.end.x = e.targetTouches[0].clientX
   this.basicdata.end.y = e.targetTouches[0].clientY
  } else {
   this.basicdata.end.x = e.clientX
   this.basicdata.end.y = e.clientY
  }
  // 计算滑动值
  this.temporaryData.poswidth = this.basicdata.end.x - this.basicdata.start.x
  this.temporaryData.posheight = this.basicdata.end.y - this.basicdata.start.y
  }
 },
 touchend (e) {
  this.temporaryData.tracking = false
  this.temporaryData.animation = true
  // 滑动结束,触发判断
  // 简单判断滑动宽度超出100像素时触发滑出
  if (Math.abs(this.temporaryData.poswidth) >= 100) {
  // 最终位移简单设定为x轴200像素的偏移
  let ratio = Math.abs(this.temporaryData.posheight / this.temporaryData.poswidth)
  this.temporaryData.poswidth = this.temporaryData.poswidth >= 0 ? this.temporaryData.poswidth + 200 : this.temporaryData.poswidth - 200
  this.temporaryData.posheight = this.temporaryData.posheight >= 0 ? Math.abs(this.temporaryData.poswidth * ratio) : -Math.abs(this.temporaryData.poswidth * ratio)
  this.temporaryData.opacity = 0
  // 不满足条件则滑入
  } else {
  this.temporaryData.poswidth = 0
  this.temporaryData.posheight = 0
  }
 },
 // 非首页样式切换
 transform (index) {
  if (index > this.basicdata.currentPage) {
  let style = {}
  let visible = 3
  let perIndex = index - this.basicdata.currentPage
  // visible可见数量前滑块的样式
  if (index <= this.basicdata.currentPage + visible - 1) {
   style[&#39;opacity&#39;] = &#39;1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * perIndex * 60 + &#39;px&#39; + &#39;)&#39;
   style[&#39;zIndex&#39;] = visible - index + this.basicdata.currentPage
   style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
   style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  } else {
   style[&#39;zIndex&#39;] = &#39;-1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * visible * 60 + &#39;px&#39; + &#39;)&#39;
  }
  return style
  }
 },
 // 首页样式切换
 transformIndex (index) {
  // 处理3D效果
  if (index === this.basicdata.currentPage) {
  let style = {}
  style[&#39;transform&#39;] = &#39;translate3D(&#39; + this.temporaryData.poswidth + &#39;px&#39; + &#39;,&#39; + this.temporaryData.posheight + &#39;px&#39; + &#39;,0px)&#39;
  style[&#39;opacity&#39;] = this.temporaryData.opacity
  style[&#39;zIndex&#39;] = 10
  if (this.temporaryData.animation) {
   style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
   style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  }
  return style
  }
 }
 }
}
</script>
Copier après la connexion

4. Après avoir glissé, l'image suivante est empilée sur le dessus

La réempilage est la dernière. la fonction du composant est également la fonction la plus importante et la plus complexe. Dans notre code, le tri des éléments de pile dépend de la fonction transformIndex et transform du style de liaison. La condition déterminée dans la fonction est currentPage. Est-il nécessaire de modifier la page actuelle et de la laisser +1 pour terminer le réempilement. ?

La réponse n'est pas si simple, car notre slide out est un effet d'animation, qui durera 300 ms, et le réarrangement provoqué par le changement de currentPage changera immédiatement, interrompant la progression de l'animation. Par conséquent, nous devons d'abord modifier les conditions de tri de la fonction de transformation, puis modifier la page actuelle.

#### Implémentation spécifique

Modifier la condition de tri de la fonction de transformation
  • Laisser currentPage+1
  • Ajoutez l'événement onTransitionEnd, et une fois le curseur terminé, déplacez-le dans la liste des piles

  • Le code est le suivant :

<template>
 <ul class="stack">
  <li class="stack-item" v-for="(item, index) in pages"
  :style="[transformIndex(index),transform(index)]"
  @touchmove.stop.capture="touchmove"
  @touchstart.stop.capture="touchstart"
  @touchend.stop.capture="touchend"
  @mousedown.stop.capture="touchstart"
  @mouseup.stop.capture="touchend"
  @mousemove.stop.capture="touchmove"
  @webkit-transition-end="onTransitionEnd"
  @transitionend="onTransitionEnd"
  >
  <img :src="item.src">
  </li>
 </ul>
</template>
<script>
export default {
 props: {
 // pages数据包含基础的图片数据
 pages: {
  type: Array,
  default: []
 }
 },
 data () {
 return {
  // basicdata数据包含组件基本数据
  basicdata: {
  start: {}, // 记录起始位置
  end: {}, // 记录终点位置
  currentPage: 0 // 默认首图的序列
  },
  // temporaryData数据包含组件临时数据
  temporaryData: {
  poswidth: &#39;&#39;, // 记录位移
  posheight: &#39;&#39;, // 记录位移
  lastPosWidth: &#39;&#39;, // 记录上次最终位移
  lastPosHeight: &#39;&#39;, // 记录上次最终位移
  tracking: false, // 是否在滑动,防止多次操作,影响体验
  animation: false, // 首图是否启用动画效果,默认为否
  opacity: 1, // 记录首图透明度
  swipe: false // onTransition判定条件
  }
 }
 },
 methods: {
 touchstart (e) {
  if (this.temporaryData.tracking) {
  return
  }
  // 是否为touch
  if (e.type === &#39;touchstart&#39;) {
  if (e.touches.length > 1) {
   this.temporaryData.tracking = false
   return
  } else {
   // 记录起始位置
   this.basicdata.start.t = new Date().getTime()
   this.basicdata.start.x = e.targetTouches[0].clientX
   this.basicdata.start.y = e.targetTouches[0].clientY
   this.basicdata.end.x = e.targetTouches[0].clientX
   this.basicdata.end.y = e.targetTouches[0].clientY
  }
  // pc操作
  } else {
  this.basicdata.start.t = new Date().getTime()
  this.basicdata.start.x = e.clientX
  this.basicdata.start.y = e.clientY
  this.basicdata.end.x = e.clientX
  this.basicdata.end.y = e.clientY
  }
  this.temporaryData.tracking = true
  this.temporaryData.animation = false
 },
 touchmove (e) {
  // 记录滑动位置
  if (this.temporaryData.tracking && !this.temporaryData.animation) {
  if (e.type === &#39;touchmove&#39;) {
   this.basicdata.end.x = e.targetTouches[0].clientX
   this.basicdata.end.y = e.targetTouches[0].clientY
  } else {
   this.basicdata.end.x = e.clientX
   this.basicdata.end.y = e.clientY
  }
  // 计算滑动值
  this.temporaryData.poswidth = this.basicdata.end.x - this.basicdata.start.x
  this.temporaryData.posheight = this.basicdata.end.y - this.basicdata.start.y
  }
 },
 touchend (e) {
  this.temporaryData.tracking = false
  this.temporaryData.animation = true
  // 滑动结束,触发判断
  // 简单判断滑动宽度超出100像素时触发滑出
  if (Math.abs(this.temporaryData.poswidth) >= 100) {
  // 最终位移简单设定为x轴200像素的偏移
  let ratio = Math.abs(this.temporaryData.posheight / this.temporaryData.poswidth)
  this.temporaryData.poswidth = this.temporaryData.poswidth >= 0 ? this.temporaryData.poswidth + 200 : this.temporaryData.poswidth - 200
  this.temporaryData.posheight = this.temporaryData.posheight >= 0 ? Math.abs(this.temporaryData.poswidth * ratio) : -Math.abs(this.temporaryData.poswidth * ratio)
  this.temporaryData.opacity = 0
  this.temporaryData.swipe = true
  // 记录最终滑动距离
  this.temporaryData.lastPosWidth = this.temporaryData.poswidth
  this.temporaryData.lastPosHeight = this.temporaryData.posheight
  // currentPage+1 引发排序变化
  this.basicdata.currentPage += 1
  // currentPage切换,整体dom进行变化,把第一层滑动置零
  this.$nextTick(() => {
   this.temporaryData.poswidth = 0
   this.temporaryData.posheight = 0
   this.temporaryData.opacity = 1
  })
  // 不满足条件则滑入
  } else {
  this.temporaryData.poswidth = 0
  this.temporaryData.posheight = 0
  this.temporaryData.swipe = false
  }
 },
 onTransitionEnd (index) {
  // dom发生变化后,正在执行的动画滑动序列已经变为上一层
  if (this.temporaryData.swipe && index === this.basicdata.currentPage - 1) {
  this.temporaryData.animation = true
  this.temporaryData.lastPosWidth = 0
  this.temporaryData.lastPosHeight = 0
  this.temporaryData.swipe = false
  }
 },
 // 非首页样式切换
 transform (index) {
  if (index > this.basicdata.currentPage) {
  let style = {}
  let visible = 3
  let perIndex = index - this.basicdata.currentPage
  // visible可见数量前滑块的样式
  if (index <= this.basicdata.currentPage + visible - 1) {
   style[&#39;opacity&#39;] = &#39;1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * perIndex * 60 + &#39;px&#39; + &#39;)&#39;
   style[&#39;zIndex&#39;] = visible - index + this.basicdata.currentPage
   style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
   style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  } else {
   style[&#39;zIndex&#39;] = &#39;-1&#39;
   style[&#39;transform&#39;] = &#39;translate3D(0,0,&#39; + -1 * visible * 60 + &#39;px&#39; + &#39;)&#39;
  }
  return style
  // 已滑动模块释放后
  } else if (index === this.basicdata.currentPage - 1) {
  let style = {}
  // 继续执行动画
  style[&#39;transform&#39;] = &#39;translate3D(&#39; + this.temporaryData.lastPosWidth + &#39;px&#39; + &#39;,&#39; + this.temporaryData.lastPosHeight + &#39;px&#39; + &#39;,0px)&#39;
  style[&#39;opacity&#39;] = &#39;0&#39;
  style[&#39;zIndex&#39;] = &#39;-1&#39;
  style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
  style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  return style
  }
 },
 // 首页样式切换
 transformIndex (index) {
  // 处理3D效果
  if (index === this.basicdata.currentPage) {
  let style = {}
  style[&#39;transform&#39;] = &#39;translate3D(&#39; + this.temporaryData.poswidth + &#39;px&#39; + &#39;,&#39; + this.temporaryData.posheight + &#39;px&#39; + &#39;,0px)&#39;
  style[&#39;opacity&#39;] = this.temporaryData.opacity
  style[&#39;zIndex&#39;] = 10
  if (this.temporaryData.animation) {
   style[&#39;transitionTimingFunction&#39;] = &#39;ease&#39;
   style[&#39;transitionDuration&#39;] = 300 + &#39;ms&#39;
  }
  return style
  }
 }
 }
}
</script>
Copier après la connexion
ok~ Après avoir terminé les quatre étapes ci-dessus, les fonctions de base de l'empilage des composants ont été mises en œuvre. Venez voir l'effet

<.>

L'effet de glissement empilé a déjà été publié, mais Tantan a également ajouté le décalage de l'angle de contact et la détermination du rapport de la zone de glissement en termes d'expérience

Le principe du décalage d'angle est d'enregistrer la position tactile de l'utilisateur à chaque fois que l'utilisateur la touche, de calculer l'angle de décalage maximum et, lorsque le déplacement coulissant se produit, d'augmenter linéairement l'angle jusqu'à l'angle de décalage maximum.

Ce que vous devez faire dans la pile est :

  • Calculer l'angle et la direction requis dans touchmove

  • touchend Et dans onTransitionEnd, réglez l'angle sur zéro

pour déterminer le rapport de zone coulissante. La zone de décalage est principalement calculée à travers la quantité de décalage pour obtenir le rapport de zone et compléter le jugement.

Le code complet et la démo peuvent être consultés sur github. Le code source ne sera pas publié ici

Merci à tous d'avoir lu cet article. :star:️ sur github. Enfin, je vous souhaite tout le meilleur. Vous pouvez trouver votre ex-petite amie sur Tantan : green_heart :

Ce qui précède est ce que j'ai compilé pour tout le monde. tout le monde dans le futur.

Articles connexes :

Explication détaillée de l'utilisation de l'échafaudage vue-cli pour initialiser la structure du projet sous le projet Vue

Modifier la méthode de demande de vue pour une certaine valeur d'élément dans les données

Méthode d'implémentation de la barre de navigation en étoile JavaScript

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 de ce site Web
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

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

Video Face Swap

Video Face Swap

Échangez les visages dans n'importe quelle vidéo sans effort grâce à notre outil d'échange de visage AI entièrement gratuit !

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Méthode spécifique pour créer un effet de mouvement de film en PPT Méthode spécifique pour créer un effet de mouvement de film en PPT Mar 26, 2024 pm 04:00 PM

1. Démarrez PPT, créez un nouveau document vierge, sélectionnez toutes les zones de texte et supprimez-les. 2. Exécutez la commande Insérer une forme, faites glisser un rectangle dans le document et remplissez la forme de noir. 3. Faites glisser le rectangle pour l'allonger, exécutez la commande Insérer-Forme, faites glisser le petit carré et définissez la couleur de remplissage sur blanc. 4. Copiez et collez les petits carrés un par un afin que le haut et le bas soient répartis uniformément des deux côtés du film. Après les avoir tous sélectionnés avec ctrl+a, faites un clic droit et sélectionnez Groupe. 5. Exécutez la commande Insérer une image, recherchez l'image à insérer dans la boîte de dialogue contextuelle, cliquez pour l'ouvrir et ajustez la taille et la position de l'image. 6. Répétez l'étape 5 pour insérer et définir les images restantes afin de former une image de film. 7. Sélectionnez le film, exécutez la commande animation-ajouter une animation

Comment faire une couverture de roman sur la tomate Comment faire une couverture de roman sur la tomate Feb 23, 2024 pm 01:55 PM

Comment faire la couverture du roman Tomato ? Vous pouvez créer une couverture de roman exclusive dans le roman Tomato, mais la plupart des amis ne savent pas comment faire la couverture du roman Tomato. Voici ensuite l'image de la façon de faire la couverture du roman Tomato apportée par. l'éditeur aux joueurs Tutoriel, les joueurs intéressés viennent y jeter un oeil ! Tutoriel d'utilisation de Tomato Novel Comment créer une couverture de Tomato Novel 1. Ouvrez d'abord l'application Tomato Novel, entrez dans la page de gestion du travail pour créer un nouveau livre et sélectionnez le [Modèle de couverture] comme indiqué par la flèche ci-dessous. 2. Entrez ensuite le ; page de modèle de couverture et sélectionnez votre modèle de couverture préféré ; 3. Après avoir finalement sélectionné la couverture, cliquez sur [Confirmer] dans le coin supérieur droit.

Guide d'utilisation pour la création de tableaux Excel mobiles Guide d'utilisation pour la création de tableaux Excel mobiles Feb 18, 2024 pm 02:41 PM

Tutoriel de création de tableaux Excel mobiles Avec la popularité des appareils mobiles et les progrès continus de la technologie, les téléphones mobiles sont devenus l'un des outils indispensables dans notre vie quotidienne et notre travail. L'utilisation de feuilles de calcul Excel sur votre téléphone mobile peut facilement enregistrer, calculer et analyser des données et améliorer l'efficacité du travail. Cet article partagera avec vous les opérations et techniques de base pour créer des tableaux Excel mobiles. 1. Choisissez la bonne application Il existe de nombreuses applications Excel mobiles sur le marché, telles que GoogleSheets, Micro.

Que dois-je faire si l'écran de mon téléphone portable a du mal à glisser et à sécher ? Que dois-je faire si l'écran de mon téléphone portable a du mal à glisser et à sécher ? Dec 04, 2023 pm 03:51 PM

Solutions pour les écrans de téléphones portables difficiles à glisser et à sécher : 1. Humidifiez l'écran ; 2. Nettoyez l'écran régulièrement ; 3. Augmentez la force de glissement de vos doigts ; 4. Utilisez des protecteurs d'écran de téléphone portable ; 6. Gardez les mains humides ; 7. , manipulez-le proprement lors de l'application du film ; 8. Utilisez du lubrifiant 9. Utilisez des gants 10. Réglez la luminosité de l'écran ; Introduction détaillée : 1. Humidifiez l'écran, placez un humidificateur à côté de l'écran ou vaporisez de l'eau pour augmenter l'humidité de l'air, réduisant ainsi la sécheresse de l'écran ; 2. Nettoyez régulièrement l'écran, utilisez un nettoyant pour écran professionnel, etc.

Comment utiliser CSS pour créer un effet de compte à rebours Comment utiliser CSS pour créer un effet de compte à rebours Oct 26, 2023 am 10:36 AM

Comment utiliser CSS pour créer un effet de compte à rebours. L'effet de compte à rebours est une fonction courante dans le développement Web. Il peut fournir aux utilisateurs un effet de compte à rebours dynamique et donner aux gens un sentiment d'urgence et d'attente. Cet article expliquera comment utiliser CSS pour obtenir l'effet de compte à rebours et donnera des étapes de mise en œuvre détaillées et des exemples de code. Les étapes d'implémentation sont les suivantes : Étape 1 : construction de la structure HTML Tout d'abord, créez un conteneur div en HTML pour envelopper le contenu du compte à rebours. Par exemple : &lt;divclass="countd

Laissez-moi vous apprendre ! Comment créer des effets d'animation en PPT ! Laissez-moi vous apprendre ! Comment créer des effets d'animation en PPT ! Mar 20, 2024 pm 06:40 PM

Lors de la création d'un PPT, l'utilisation de certains effets d'animation le rendra plus vivant et plus mignon que sans l'utilisation d'effets d'animation. Avec l'ajout d'effets d'animation, les gens aimeront peut-être regarder ce PPT, nous devons donc apprendre à créer des effets d'animation pour PPT. Ensuite, je présenterai en détail comment ajouter des effets d'animation à PPT. Veuillez continuer à lire et étudier attentivement ces étapes, je pense qu’elles vous seront utiles ! Tout d'abord, ouvrez le PPT que nous avons créé nous-mêmes. Vous remarquerez que ce PPT n'a actuellement aucun effet d'animation (comme le montre la flèche rouge dans la figure ci-dessous). 2. Ensuite, nous devons ajouter des effets d'animation à l'image. Nous sélectionnons d'abord l'image, puis cliquons sur le bouton [Animation] en haut de la barre de menu (comme indiqué dans le cercle rouge dans la figure ci-dessous). 3. Ensuite, nous cliquons à l'intérieur de l'animation

Comment faire une couverture de mot Comment faire une couverture de mot Mar 19, 2024 pm 06:50 PM

Un mémoire de fin d’études doit avoir une couverture, une table des matières, une fin, etc. Ce n’est qu’alors que le mémoire peut être complet. Dans le dernier numéro, l'éditeur a partagé avec des amis comment créer une table des matières dans Word. Dans ce numéro, je partagerai avec vous comment créer une couverture de mot. Si vous ne savez pas comment la créer, dépêchez-vous. ! 1. Tout d'abord, nous ouvrons le document Word dont nous voulons faire une couverture, comme le montre la figure ci-dessous : 2. Ensuite, nous cliquons sur le bouton [Chapitre] dans la barre de menu et sélectionnons la page de couverture. Cette fonction est équivalente à une page de couverture. bibliothèque de couvertures, et vous pouvez choisir vous-même une couverture appropriée et belle, comme indiqué dans le cercle rouge dans la figure ci-dessous : 3. Après avoir cliqué, vous pouvez voir différents types de couvertures, tels que le type d'entreprise, adaptées aux contrats et documents d'entreprise. ; type de CV, adapté à la recherche d'emploi et à la soumission de CV Amis, attendez, d'accord ?

Comment utiliser JavaScript pour obtenir l'effet de commutation coulissante de haut en bas des images et ajouter des animations de fondu d'entrée et de sortie ? Comment utiliser JavaScript pour obtenir l'effet de commutation coulissante de haut en bas des images et ajouter des animations de fondu d'entrée et de sortie ? Oct 20, 2023 am 11:19 AM

Comment JavaScript peut-il obtenir l'effet de commutation coulissante de haut en bas des images et ajouter des animations de fondu d'entrée et de sortie ? Dans le développement Web, il est souvent nécessaire d'obtenir des effets de commutation d'image. Vous pouvez utiliser JavaScript pour réaliser une commutation coulissante de haut en bas et ajouter des effets d'animation de fondu d'entrée et de sortie. Tout d’abord, nous avons besoin d’un conteneur contenant plusieurs images. Nous pouvons utiliser des balises div en HTML pour héberger des images. Par exemple, nous créons un div avec l'identifiant "image-container" pour

See all articles