Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

元素拖动粘滞效果

  看到手机QQ上拖动消息数量的那个元素粘滞效果不错,于是也试着实现一下。目前只做了PC版,基本效果是实现了,不过细节处理不太好,过渡的曲线只是使用二次函数去拟合而已。实现使用了现代浏览器的一些特性,整个效果没有产生额外的元素,不会污染文档。

  我的实现思路大概是这样的。首先,让元素可拖动,这就是处理一些鼠标事件以及元素的坐标。然后创建一排box-shadow,来作为原位置到当前位置的过渡填充。最后,对这个过渡填充使用一个曲线去让效果更逼真。下面是实现的代码: <!DOCTYPE html>
<div>8</div>
<style>
body {
  cursor:default;
  -webkit-user-select:none;
  -moz-user-select:none;
}
div {
  position:absolute;
  left:100px;top:100px;
  width:32px;height:32px;
  border-radius:100%;
  background:red;
  box-shadow:0px 0px 0px red;
  font:bold 18px/32px Monospace;
  text-align:center;
  color:white;
}
</style>
<script>
var div=document.querySelector("div");
div.onmousedown=function(e){
  var px=e.clientX,py=e.clientY;
  var ex=div.offsetLeft,ey=div.offsetTop;
  var broken=false;
  var MAXDES=160;
  var RADIUS=32;
  document.onmousemove=function(e){
    var mx=e.clientX,my=e.clientY;
    var x=mx-px,y=my-py;
    //移动元素
    div.style.left=ex+x+"px";
    div.style.top=ey+y+"px";
    //计算移动了的距离
    var des=Math.sqrt(x*x+y*y);
    //通过距离计算出缩放
    var scale=1/(1+des/MAXDES);
    //如果超出MAXDES的范围则切断
    if(scale<1/2)cutoff();
    //如果已经切断就不计算投影
    if(broken)return;
    //算出x和y方向的增量
    //取相反数是因为我们移动的是元素,投影应该在元素原来的位置
    var dx=-1*x/des,dy=-1*y/des;
    //遍历距离
    var shadows=[];
    for(var i=0;i<=des;i++){
      //计算过渡
      //这里偷了个懒只使用了二次函数来拟合
      var di=i/des*2;
      var dr=(0.5*di*di-di)*(RADIUS/2);
      //将计算出的shadow储存下来
      //这里除以scale是因为scale会影响投影位置,需要除以它抵消掉
      shadows.push(dx*i/scale+"px "+dy*i/scale+"px 0px "+dr+"px red");
    };
    //将样式设置到元素上
    div.style.transform="scale("+scale+","+scale+")";
    div.style.boxShadow=shadows;
  };
  document.onmouseup=function(){
    cutoff();
    document.onmousemove=null;
    document.onmouseup=null;
  };
  function cutoff(){
    div.style.boxShadow="none",
    div.style.transform="none",
    broken=true;
  };
};
</script>
网名:
34.203.213.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^