类似Tinder
和探探
的卡片效果的组件,社区中已经非常多了。我这一版除了可以实现和他们一样的效果外。还增加了飞卡
的效果,就是类似我的女神邱淑贞这样。
可以将卡片朝任意拖拽方向飞出去,必须得帅
是不是!
首先让三个卡片按照近大远小
的原则分别设置设置z-index
,宽和高,比如每一层卡片的宽和高比上一层卡片要缩小20个像素(还有一种做法是通过zoom或者scale来设置远处卡片的缩小级别)。然后加入绝对定位position:absolute
和z-index
就可以将卡片层叠起来了。
因为只有第一张卡片可以拖动,所以我们只要监听第一张卡片的拖动事件。比如touchstart
,touchmove
,touchcancel
,touchend
。
拖动的时候需要注意,在touchstart
的时候记录一下手指按下的位置,在touchmove
时要减去这个位置,看上去就是点哪儿从哪儿拖。
touchStart:function(e){ var curTouch=e.touches[0]; this.startLeft=curTouch.clientX-this.left; this.startTop=curTouch.clientY-this.top; } touchMove:function(e){ var curTouch=e.touches[0]; this.left=curTouch.clientX-this.startLeft; this.top=curTouch.clientY-this.startTop; } 复制代码
要实现超任意拖拽方向飞出去这个效果,需要用到一些数学公式。
计算卡片当前拖拽的坐标和起始坐标的夹角
var angle=Math.atan2((当前坐标.y-起点坐标.y), (当前坐标.x-起点坐标.x)); 复制代码
飞出去的落点x
轴坐标通过计算angle的余弦值再乘以力度得出
this.left=Math.cos(angle)*this.throwDistance; 复制代码
飞出去的落点y
轴坐标通过计算angle的正弦值再乘以力度得出
this.top=Math.sin(angle)*this.throwDistance; 复制代码
这里咱们做得再完善一些,在拖动结束时去判断一下当前拖动的距离是否足够触发飞卡效果。如果不触发飞卡效果,则触发回位效果。这样的话也可以防止用户误操作。
//计算两点之间的直线距离 getDistance:function(x1, y1, x2, y2) { var _x = Math.abs(x1 - x2); var _y = Math.abs(y1 - y2); return Math.sqrt(_x * _x + _y * _y); } var distance=this.getDistance(0,0,this.left,this.top); if(distance>this.throwTriggerDistance){ this.makeCardThrow(); }else{ this.makeCardBack(); } 复制代码
上推其实很简单,一开始的时候,我就定义了四张(不是3张吗?怎么变4张了
)卡片的大小和位置。
当第一张卡飞出去后
第2张卡片变更为原本第1张卡片的位置和大小
this.width2=this.cardWidth; this.height2=this.cardHeight; this.left2=0; this.top2=0; 复制代码
第3张卡片变更为原本第2张卡片的位置和大小
this.width3=(this.cardWidth-this.leftPad*2); this.height3=(this.cardHeight-this.topPad*2); this.left3=this.leftPad; this.top3=(this.topPad*3); 复制代码
第4张卡片原本是透明的,现在变为第3张卡片的位置和大小
this.width4=(this.cardWidth-this.leftPad*4); this.height4=(this.cardHeight-this.topPad*4); this.left4=this.leftPad*2; this.top4=(this.topPad*6); this.opacity4=1; 复制代码
我把阴影效果先去掉,大家观察一下这个细节
底层的卡片上推和第一张卡片的飞出效果是同时进行的,由css的transition
来控制。不过时间是我们设定好的,所以只要在上推和飞出的动画时间结束后,我们重置一下所有4张卡片的大小和位置即可。
this.onThrowStart(); setTimeout(function(){ that.isThrow=false; that.isAnimating=false; that.onThrowDone(); that.resetAllCard(); },400); 复制代码
这里需要注意,所有四张卡片都需要瞬间
完成重置,所以这步之前应该禁用掉transition动画。
为了适应各种使用场景,我们要将这个效果封装一下。
//提供几个事件,分别是拖动时,拖动结束,飞卡结束,飞卡失败(回位) @onDragMove='onCardDragMove' @onDragStop='onCardDragStop' @onThrowDone='onCardThrowDone' @onThrowFail='onCardThrowFail' //参数就不细说了,都能看明白 :cardWidth="200" :cardHeight="200" cardBgColor="#fff" :leftPad="10" :topPad="6" :borderRadius="8" :throwTriggerDistance="100" dragDirection="all" :hasShadow="false" :hasBorder="true" 复制代码
提供三个slot,你可以非常方便的往卡片里塞内容
//firstCard,secondCard,thirdCard <slot name="firstCard">复制代码
@onDragMove='onCardDragMove' @onDragStop='onCardDragStop' @onThrowDone='onCardThrowDone' :cardWidth="300" :cardHeight="120" :throwTriggerDistance="100" dragDirection="horizontal" :hasShadow="true" 复制代码
仅允许水平拖动
由于改变宽高会导致文字换行变化,也许卡片用缩放的话,用户体验会更好一些吧
实现探探效果的核心是监听卡片拖动的位置
onCardDragMove(obj){ if(obj.left10){ this.actionName="不喜欢"; }else if(obj.left>10){ this.actionName="喜欢"; }else{ this.actionName=""; } } 复制代码
156-1688-1988
80931912(售前)2580705673(售后)
地址:湖南省长沙市万科金域华府二期15栋A902
10年建站服务经验
服务27家集团公司
服务超2000家中小企业
B2C营销型网站建设供应商
多项大型项目开发经验
营销型网站建设专家
完备的项目流程管理体系
网页设计与网站开发技术并重
COPYRIGHT © 2013-现在 XIANGQU ALL RIGHTS RESERVED
备案号:湘ICP备19018580号-1