Code前端首页关于Code前端联系我们

2020更新,Vue模拟探探抽卡效果

terry 2年前 (2023-09-08) 阅读数 145 #Vue

Vue3版本已更新,看这篇文章为2021年做准备,模仿Vue3中探探的抽卡效果


社区中已经有很多类似于

Tinder探探 的卡片效果组件。这个版本的我也能达到和他们一样的效果。还增加了类似我女神邱淑贞的飞卡效果。

您可以将卡片向任何拖动方向飞行。你必须,对吗?

跟着你一步步实现这个效果

绝对原创,如有雷同,纯属对方抄袭?

先对折

其实我第一次实现这个效果是在2018年,当时我在weex上实现了一个版本。原帖见这里:zhuanlan.zhihu.com/p/37482853

这次我们不要求它在 weex 中可用,因此非常容易组装。

首先让三张卡片按照近大远小设置z-index的原则设置宽度和高度,例如每层卡片和高比顶层的宽度要减少20个像素(另一种方法是使用缩放或缩放来设置远程卡的缩放级别)。然后加上绝对位置position:absolutez-index来折叠卡片。

020更新,Vue仿探探拖拽卡片的效果"

拖动第一张卡片

因为只能抽第一张牌,所以只监听第一张抽牌事件。例如 touchstarttouchmovetouchcanceltouchend

020更新,Vue仿探探拖拽卡片的效果"

拉动时要小心。当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;
}
 

飞出

020更新,Vue仿探探拖拽卡片的效果"

需要一些数学公式才能达到超任意拖动方向飞出去的效果。

计算抽出的卡片坐标与初始坐标之间的角度

var angle=Math.atan2((当前坐标.y-起点坐标.y), (当前坐标.x-起点坐标.x));
 

飞行点

的轴向坐标是通过计算角度的余弦值乘以

的幂得到的
this.left=Math.cos(angle)*this.throwDistance;
 

飞行点y的轴向坐标通过计算角度的正弦值并乘以力

得到

这里我们做得比较好一点,在抽牌结束时判断当前抽牌距离是否足以触发飞卡效果。如果飞行卡牌的效果没有触发,则会触发返回效果。这也可以防止用户的错误操作。

020更新,Vue仿探探拖拽卡片的效果"

//计算两点之间的直线距离
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张了)卡的大小和位置。

当第一张卡片

飞出时
  • 第二张卡片更改为原来第一张卡片的位置和大小
this.width2=this.cardWidth;
this.height2=this.cardHeight;
this.left2=0;
this.top2=0;
 
  • 第三张卡片改变原来第二张卡片的位置和大小
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;
 

首先我把阴影效果去掉,大家注意这个细节

020更新,Vue仿探探拖拽卡片的效果"

刷新所有卡片

最底下一张卡的上推效果和第一张卡的飞出效果同时进行,由transition css 控制。不过我们设置了时间,所以我们只需要在打印和飞出动画时间过去后重新调整所有4张卡片的大小和位置即可。

020更新,Vue仿探探拖拽卡片的效果"

this.onThrowStart();
setTimeout(function(){
    that.isThrow=false;
    that.isAnimating=false;
    that.onThrowDone();
    that.resetAllCard();
},400);
 

这里需要注意的是,四张卡都需要重置瞬间,所以在这一步之前要禁用过渡动画。

组件化

为了适应不同的使用场景,我们需要封装这个效果。

//提供几个事件,分别是拖动时,拖动结束,飞卡结束,飞卡失败(回位)
@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"
 

提供三个插槽,您可以轻松将内容插入卡中

//firstCard,secondCard,thirdCard
<slot name="firstCard"></slot>
 

现在我们来模仿一些效果

几个推荐答案

@onDragMove='onCardDragMove'
@onDragStop='onCardDragStop'
@onThrowDone='onCardThrowDone'
:cardWidth="300" 
:cardHeight="120"
:throwTriggerDistance="100"
dragDirection="horizontal"
:hasShadow="true"
 

只允许水平拉动

020更新,Vue仿探探拖拽卡片的效果"

由于更改宽度和高度会改变文本换行,因此如果选项卡变小,可能会带来更好的用户体验

探探效果

实现探探效果的核心是追踪抽到的卡片的位置

onCardDragMove(obj){
    if(obj.left<-10){
        this.actionName="不喜欢";
    }else if(obj.left>10){
        this.actionName="喜欢";
    }else{
        this.actionName="";
    }
}
 

020更新,Vue仿探探拖拽卡片的效果"

源代码存储库

github.com/ezshine/ezf…

这周我会抽时间实现vue3版本~

关注大帅全包

最近文章(谢谢鼓励和支持???)

  • ?我熬了一晚上的动画就是为了让大家更好的理解Composition Api Vue3 836个赞
  • ?2020年,疫情严重损害了我的第三次创业|年度征文比赛掘金122个赞
  • ?我失败的创业史:“温暖”的人文考勤系统15个赞
  • ?如何用JS在机器中创建抽奖,同时服务器检查中奖38个赞的概率
  • ?前端开发中新拟物风格的兴起 56 我喜欢

欢迎拍砖,我们一起讨论更优雅的实现方式

版权声明

本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门