大家好,欢迎来到IT知识分享网。
前言
最早实现这个效果,是2011年用Objective-C在iOS里实现的。原仓库地址:code.google.com/archive/p/c…
在Vue里实现这个东西没啥用处,毕竟Vue也不是一个游戏框架,但是谁叫Vue
这个话题的热度最高呢😁,写文章还是希望被更多人看到嘛…
印象里我在不同时期曾经用三种语言分别实现过这个案例。所以无论用什么框架、语言,只要你了解背后的原理,都很容易实现。
本文有部分知识点和上周那篇在Vue里实现探探拖拽卡片的效果是一样的,这里是Vue3的版本 备战2021,仿探探拖拽卡片效果Vue3实现
三层UI
全部UI分为三层
- 第一层是杆头,尺寸不会变化,拖拽的
视觉效果
区。 - 第二层是杆体,高度可拉伸,用于
拟物流
模仿真实感。 - 第三层是底,只是放在画面中,为了让视觉感受更完整。
当然没有第二层和第三层是不影响摇杆功能的,但谁叫我是一个拟物流
的前端偏执狂
呢?
把这三个层通过绝对定位
+z-index
叠起来,通过设置touch
事件让杆头可以拖动。为了让大家看得清楚层级,我们先把杆头变透明。
圆形的拖拽区
摇杆嘛,圆形的洞里有根杆(不要污
呀),所以我们必须把拖拽限制在一个圆形区域里
onTouchMove(e){
var curTouch=e.touches[0];
var tleft=curTouch.clientX-startLeft;
var ttop=curTouch.clientY-startTop;
//获取点击位置和起点的直线距离,也就是半径
var distance = getDistance(tleft,ttop,0,0);
//如果这个距离是否大于圆形可移动区域的半径,则强行变更
if(distance>=this.ballMoveRadius)distance = this.ballMoveRadius;
//最后通过夹角,正弦,余弦,半径还原x,y坐标
var angle = Math.atan2((ttop-0), (tleft-0));
this.left=Math.cos(angle)*distance;
this.top=Math.sin(angle)*distance;
}
IT知识分享网
代码中比较核心的部分是:我们先通过所在点
和原点
位置求出半径distance
,以及之间的夹角角度angle
。然后通过限定半径和夹角角度还原出x
,y
的坐标。就可以达到控制拖动在圆形区域内的效果了。
IT知识分享网//获取两点间直线距离的算法
var 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);
}
羞涩的杆体
杆体是这里面最麻烦的一块,需要通过摇杆的拖拽的距离变化长度
,同时根据摇杆的位置旋转角度。
<view class='stick' :class="{animation:inDraging===false&&transition}" :style="{height: stickHeight+'px',transform:'translateX(-50%)'}">
<view :style="{transform:'rotate('+(angle/(3.14159/180)-90)+'deg)'}" style="transform-origin: 50% 0%;width: 100%;height: 100%;">
<slot name="stick">
</slot>
</view>
</view>
这里我用了两层dom来完成这个杆体,一层用height
进行高度变化,一层用transfrom
设置旋转角度和旋转中心点。大家有更好的实现方法吗,在评论区告诉我吧。
夹角转为旋转角度算法angle/(3.14159/180)
,减去90是为了让度数起点在12点钟
的位置。
IT知识分享网onTouchMove(e){
var curTouch=e.touches[0];
var tleft=curTouch.clientX-startLeft;
var ttop=curTouch.clientY-startTop;
var distance = getDistance(tleft,ttop,0,0);
if(distance>=this.ballMoveRadius)distance = this.ballMoveRadius;
var angle = Math.atan2((ttop-0), (tleft-0));
this.left=Math.cos(angle)*distance;
this.top=Math.sin(angle)*distance;
//同步杆体的高度,旋转角度
this.stickHeight = distance;
this.angle = angle;
}
现在摇杆UE基本就完成了,接下来我们要输出一些数值,毕竟摇杆不能光自己摇
,得用来控制其他的元素进行运动。
摇杆数值
- 方向
方向我们在杆体运动的时候,已经写完了,就是那个角度
angle
。
- 力度
power = 当前半径/最大半径;
摇杆力度这件事在拳皇里是不存在的,但是在很多游戏中分
轻推
和重推
(其实就是摇杆当前距离和最大距离的比),比如轻推
是走,重推
是跑。
gif有点掉帧,大家能看出来运动的快慢吗?
组件化
现在把上面的成果封装成一个vue组件,方便复用。
<ezjoystick :touchRadius="100" :ballMoveRadius="50" :transition="true" @onJoyStickUpdate="onBeetleJoystickUpdate" >
<view slot="ball">
</view>
<view slot="stick">
</view>
<view slot="bottom">
</view>
</ezjoystick>
- 三个属性
- touchRadius 触摸检测的实际半径
- ballMoveRadius 杆头的最大移动范围半径
- transition 是否开启缓动回位
- 三个slot
-
ball 杆头
-
stick 杆体
-
bottom 底
三个slot都是非必须的,不填的话,该部分就是空dom。具体可参考源码。
-
- 两个事件
- onJoystickUpdate 有数值变化就会触发
- onJoystickCancel 停止触摸时触发
实现经典UI
组件封装好了,接下来用咱们这个组件实现几个经典的界面吧
- 街机摇杆
- 十字键
模拟十字键,核心是把角度转成4个方向,这里我随手写了一下,应该有更优雅的实现。
onCrossJoyStickUpdate(obj){
this.crossupPressed=false;
this.crossrightPressed=false;
this.crossdownPressed=false;
this.crossleftPressed=false;
if(obj.angle>-2.35&&obj.angle<-0.75){
this.crossupPressed=true;
}else if(obj.angle>-0.75&&obj.angle<0.75){
this.crossrightPressed=true;
}else if(obj.angle>0.75&&obj.angle<2.35){
this.crossdownPressed=true;
}else{
this.crossleftPressed=true;
}
}
- 王者荣耀的摇杆
在外层关联旋转一个箭头而已…
源码仓库
github.com/ezshine/ezj…
clone源码后使用HBuilerX打开可以快速看到实例,或将components复制到vuecli项目中导入使用
后话,怎么实现搓招
什么是搓招?就是在一定时间内按顺序完成几个方向+按键即可触发招式。比如此图里不知火舞的这招需要我们按顺序完成 ←↙↓↘→
+轻
或重
脚。
看到此刻的你想到如何实现了吗?
期待看到你们的文章
写完请AT我来帮你点赞哟
如果没有人写这个话题的话,那我再来专门写一篇搓招
的实现吧
关注大帅搞全栈
近期文章(感谢掘友的鼓励与支持🌹🌹🌹)
- 🔥做了一夜动画,就为让大家更好的理解Vue3的Composition Api 854赞
- 🔥2020更新,Vue仿探探拖拽卡片的效果 866赞
- 🔥2020,疫情重创了我的第三次创业 | 掘金年度征文 136赞
- 🔥如何用JS做一个老虎机抽奖,由服务端控制得奖几率 48赞
欢迎拍砖,一起探讨更优雅的实现
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/9446.html