欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

js实现拖动缓动效果

程序员文章站 2024-01-05 17:49:28
话不多说,先上效果,一个体验非常好的拖拽缓动的效果,让页面提升一个档次。 这个效果看似很简单,到也困惑了很长时间,为什么别人写出来的拖拽体验为什么这么好? 直到我自己实现了以后...

话不多说,先上效果,一个体验非常好的拖拽缓动的效果,让页面提升一个档次。

js实现拖动缓动效果

这个效果看似很简单,到也困惑了很长时间,为什么别人写出来的拖拽体验为什么这么好?
直到我自己实现了以后,才发现,原来我想的实现方式不对。接下来,我通过简短的几句话,来提供这个功能的实现思路。

首先,我们要明白,我们鼠标拖拽是在一个2d平面上拖拽
2d平面只有x轴和y轴,而且获取的拖拽值也是基于平面的像素获取的。所以,我们第一步,先通过鼠标事件来获取到当前的拖拽的长度像素。

首先,绑定鼠标按下事件,来获取到鼠标基于浏览器窗口左上角的xy平面二维坐标。

然后,绑定move事件,在move事件回调内获取到鼠标拖拽的坐标,和按下坐标相减,求出拖拽的距离。

然后,我们需要通过一定比例,将拖拽的像素转换为旋转角度
我这里设置的比例是,
鼠标横向拖拽10像素,那模型沿3d的y轴坐标就旋转5度,
鼠标纵向拖拽10像素,模型沿3d世界的x轴坐标旋转1度,并且还设置了范围,即沿x轴旋转再-45度到45度之间

function ondocumentmousemove(event) {
    mousex = event.clientx;
    mousey = event.clienty;
    targetrotationx = targetrotationonmousedownx + (mousex - mousexonmousedownx) * 0.5;
    targetrotationy = math.min(math.max((targetrotationonmousedowny - (mousey - mousexonmousedowny) * 0.1), -45), 45); //拖拽后的目标位置
  }

上面获取到目标角度,重点来了,如何实现惰性旋转呢?

通过上面思路,我们知道了目标角度,那么直接设置目标角度,肯定就没有这种想要的效果了,那么如何实现这种惰性效果呢?

接下来,我们需要一个专门实现动画的requestanimationframe方法,这个方法是闲时运行,最大根据性能能够达到60帧每秒,有好多小伙伴感觉一直递归运行会不会卡顿,或者影响性能。那是你多虑了,这个方法会根据当前页面性能进行减帧,保证页面流畅运行。

我们有了这个以后,然后做什么呢,就是用来实现缓动,在每一帧里面,获取到目标角度和当前角度的角度差,然后每一次只选择总进度的百分之10 ,然后你会发现选择离目标角度越近,越慢,体验效果也是非常的棒。

而且在运行中,角度也会无限制的接近目标角度,当前demo是通过css3d来实现的:

function animate() {
    requestanimationframe(animate);
    rotatey += (targetrotationx - rotatey) * 0.1;
    rotatex += (targetrotationy - rotatex) * 0.1;
    box.style.transform = 'rotatey(' + rotatey + 'deg)';
    item.style.transform = 'rotatex(' + rotatex + 'deg)';
  }

案例全部代码

<!doctype html>
<html lang="zh">

<head>
  <meta charset="utf-8">
  <title>css3d翻转</title>
  <style>
    * {
      padding: 0;
      margin: 0;
    }

    body {
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
      overflow: hidden;
      perspective: 1000px;
    }

    .item {
      width: 50vw;
      height: 50vh;
      transform: rotatex(-50deg);
      perspective: 5000px;
      transform-style: preserve-3d;
    }

    .box {
      background: #abb9c5;
      width: 100%;
      height: 100%;
      transform-style: preserve-3d;
      position: relative;
    }

    .font,
    .back {
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      text-align: center;
      line-height: 50vh;

      background: #4cae4c;

      backface-visibility: hidden;
    }

    .back {
      background: #62ebff;
      transform: rotatey(180deg);
    }
  </style>
</head>

<body>
  <!--item 可以触发翻转的区域-->
  <div class="item">
    <!--box 可以翻转的容器-->
    <div class="box">
      <!--font 默认显示的正面-->
      <div class="font">正面</div>
      <!--back 背面-->
      <div class="back">背面</div>
    </div>
  </div>
</body>
<script>
  var targetrotationx = 0;
  var targetrotationy = 0;
  var targetrotationonmousedownx = 0;
  var targetrotationonmousedowny = 0;
  var mousex = 0;
  var mousey = 0;
  var mousexonmousedownx = 0;
  var mousexonmousedowny = 0;
  var box = document.queryselector('.box');
  var item = document.queryselector('.item');

  var rotatey = 0;
  var rotatex = 0;

  init();
  animate();

  function init() {
    // events
    document.addeventlistener('mousedown', ondocumentmousedown, false);
    document.addeventlistener('touchstart', ondocumenttouchstart, false);
    document.addeventlistener('touchmove', ondocumenttouchmove, false);
  }

  function ondocumentmousedown(event) {
    event.preventdefault();
    document.addeventlistener('mousemove', ondocumentmousemove, false);
    document.addeventlistener('mouseup', ondocumentmouseup, false);
    mousexonmousedownx = event.clientx;
    mousexonmousedowny = event.clienty;
    targetrotationonmousedownx = targetrotationx;
    targetrotationonmousedowny = targetrotationy;
  }

  function ondocumentmousemove(event) {
    mousex = event.clientx;
    mousey = event.clienty;
    targetrotationx = targetrotationonmousedownx + (mousex - mousexonmousedownx) * 0.5;
    targetrotationy = math.min(math.max((targetrotationonmousedowny - (mousey - mousexonmousedowny) * 0.1), -45), 45); //拖拽后的目标位置
  }

  function ondocumentmouseup() {
    document.removeeventlistener('mousemove', ondocumentmousemove, false);
    document.removeeventlistener('mouseup', ondocumentmouseup, false);
  }

  function ondocumenttouchstart(event) {
    event.preventdefault();
    if (event.touches.length === 1) {
      mousexonmousedownx = event.touches[0].pagex;
      mousexonmousedowny = event.touches[0].pagey;
      targetrotationonmousedownx = targetrotationx;
      targetrotationonmousedowny = targetrotationy;
    }
  }

  function ondocumenttouchmove(event) {
    event.preventdefault();
    if (event.touches.length === 1) {
      mousex = event.touches[0].pagex;
      mousey = event.touches[0].pagey;
      targetrotationx = targetrotationonmousedownx + (mousex - mousexonmousedownx) * 0.5;
      targetrotationy = math.min(math.max((targetrotationonmousedowny - (mousey - mousexonmousedowny) * 0.1), -45), 45); //拖拽后的目标位置
    }
  }

  function animate() {
    requestanimationframe(animate);
    rotatey += (targetrotationx - rotatey) * 0.1;
    rotatex += (targetrotationy - rotatex) * 0.1;
    box.style.transform = 'rotatey(' + rotatey + 'deg)';
    item.style.transform = 'rotatex(' + rotatex + 'deg)';
  }
</script>

</html>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。

上一篇:

下一篇: