The browser CSS animation is not loaded immediately, only when the mouse moves.

my goal is to generate a page flip component for stacking cards, using translate3d to produce a stacking effect, but the stacked part is always hidden in the browser.

later I found that the browser didn"t load the CSS animation at first. But when I move the mouse over the target element, the CSS animation is loaded, and then the stack is displayed by the hidden section.

js adds animation when loading. I added judgment outside the JS logic code and console printing in the code block. The data is printed when it is loaded, but not when it is moved. Adding animation is true from the very beginning, but moving the mouse over the target element does not perform css, which is amazing for me

slidecard.vue:

  • is primarily a draggable page flip component that mimics what others do.
<ul
    class="stack column"
    ref="mySlideStack"
    @touchstart.stop.prevent="stop"
    @touchmove.stop.prevent="stop"
    @touchend.stop.prevent="stop"
    @touchcancel.stop.prevent="stop"
    @mousedown.stop.prevent="stop"
    @mouseup.stop.prevent="stop"
    @mousemove.stop.prevent="stop"
    @mouseout.stop.prevent="stop">
    <li
      class="stack-item"
      v-for="(item, index) in pages"
      :key="index"
      :style="transform(index)"
      @touchstart.capture.prevent="touchstart"
      @touchmove.capture.prevent="touchmove"
      @touchend.capture.prevent="touchend"
      @touchcancel.capture.prevent="touchend"
      @mousedown.capture.prevent="touchstart"
      @mouseup.capture.prevent="touchend"
      @mousemove.capture.prevent="touchmove"
      @mouseout.capture.prevent="touchend"
      @webkit-transition-end="onTransitionEnd"
      @transitionend="onTransitionEnd">
      <img :src="item">
    </li>
  </ul>

css code (using scss)

  • use perspective and translate3d to achieve stacking effects
   .stack {
    position: relative;
    perspective: 1000px; //
    touch-action: none;
    perspective-origin: 50% 150%; //
    transform: translate3d(0px, 0px, 0px);
  }

  .stack-item {
    position: absolute;
    height: 100%;
    width: 100%;
    border-radius: 4px;
    text-align: center;
    overflow: hidden;
    user-select: none;
    opacity: 0;
    // 
    img {
      width: 100%;
      height: 100%;
      // display: block;
      pointer-events: none;
    }
  }

js code (most of them are dragged and dragged, but you don"t have to pay too much attention to it)

The value of
  • translate3d is calculated based on the drag distance, so how to calculate it is not the point and there is no need to struggle with it.
// style
transform (index) {
  let tempdata = this.tempdata
  let currentPage = tempdata.currentPage
  let length = this.pages.length
  // 
  let lastPage = currentPage === 0 ? length - 1 : currentPage - 1
  let style = {}
  let visible = tempdata.visible // 
  let transform = tempdata.prefixes.transform
  let transition = tempdata.prefixes.transition
  if (index === currentPage) { // 
    style[transform] = `translate3d(${tempdata.poswidth}px, ${tempdata.posheight}px, 0px) rotate(${tempdata.rotate}deg)`
    style["opacity"] = tempdata.opacity
    style["zIndex"] = 10
    if (tempdata.animation) {
      style[transition + "TimingFunction"] = "ease"
      style[transition + "Duration"] = tempdata.animation ? "300ms" : "0ms"
    }
  } else if (this.findStack(index, currentPage)) { // 
    let perIndex = index - currentPage > 0 ? index - currentPage : index - currentPage + length // 
    style["opacity"] = "1"
    // 
    style[transform] = `translate3d(0, 0, ${-1 * 60 * (perIndex - this.offsetRatio) / this.px2rem}rem)`
    style["zIndex"] = visible - perIndex
    if (!tempdata.tracking) {
      // 
      style[transition + "TimingFunction"] = "ease"
      style[transition + "Duration"] = "300ms"
    }
  } else if (index === lastPage) { // 
    style[transform] = `translate3d(${tempdata.lastPosWidth}px, ${tempdata.lastPosHeight}px, 0px) rotate(${tempdata.lastRotate}deg)`
    style["opacity"] = tempdata.lastOpacity
    style["zIndex"] = tempdata.lastZindex
    style[transition + "TimingFunction"] = "ease"
    style[transition + "Duration"] = "300ms"
  } else {
    style["zIndex"] = "-1"
    style[transform] = `translate3d(0, 0, ${-1 * visible * 60 / this.px2rem}rem)`
  }
    return style
},
    
// 
touchmove (e) {
  // 
  if (this.tempdata.tracking && !this.tempdata.animation) {
    if (e.type === "touchmove") { // 
      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.tempdata.poswidth = this.basicdata.end.x - this.basicdata.start.x
    this.tempdata.posheight = this.basicdata.end.y - this.basicdata.start.y
    // 
    let rotateDirection = this.rotateDirection()
    let angleRatio = this.angleRatio()
    this.tempdata.rotate = rotateDirection * this.offsetWidthRatio * 15 * angleRatio
  }
}

when actually calling slidecard.vue

  • when slide-wrapper removes overflow:hidden, the stack is also displayed?
<div id="slide-wrapper" class="column">
   <slide-card class="slide"></slide-card>
</div>

-sharpslide-wrapper {
    width: 100%;
    height: 450px;
    overflow: hidden;
    justify-content: center;
    background-color: -sharp565f77;
}
.slide {
    width: 320px;
    height: 320px;
}

it depends on how you write the js. Maybe you are writing about moving the mouse over the target element to load the animation.

Menu