uni-app:游戏摇杆,遥控控制4方向 常用于移动端组件
一、效果图
二、编写步骤及原理
1.方法一:利用css三角形原理, 缺点:不能准确控制盒子大小 (建议使用 方法二)
代码如下(示例):
<template><view class="rocker"><view style="width: 390rpx;height: 390rpx;position: relative;"><view class="content_trangle" v-if="dirtion === ''"></view><view class="content_trangle" style="border-top-color: #79F6BC;" v-if="dirtion === '上'"></view><view class="content_trangle" style="border-bottom-color: #79F6BC;" v-if="dirtion === '下'"></view><view class="content_trangle" style="border-left-color: #79F6BC;" v-if="dirtion === '左'" ></view><view class="content_trangle" style="border-right-color: #79F6BC;" v-if="dirtion === '右'"></view><view class="core"><view><image src="../../../static/img/image/rocker-left.png" mode=""></image></view><view><image src="../../../static/img/image/rocker-left.png" mode=""></image></view><view><image src="../../../static/img/image/rocker-left.png" mode=""></image></view><view><image src="../../../static/img/image/rocker-left.png" mode=""></image></view></view><view class="curise" @touchmove="move" @touchstart="start" @touchcancel="cancelAndEnd" @touchend="cancelAndEnd":style="{left:left+'rpx',top:top+'rpx'}"></view></view></view></view>
</template><script>export default {data() {return {left: 0,top: 0,startx: 0, //x坐标starty: 0, //y坐标dirtion: ''}},onLoad() {},methods: {//将方法暴露给父组件,并传值do(direct) {this.$emit('remote', direct);},// 移动时move(e) {// 向上移,Y轴的值减小,向下移,Y轴的值增大 | 向左移,X轴的值在减小,向右移X轴的值在增大// console.log('eX',e.touches[0].clientX,'eY',e.touches[0].clientY);const templeft = (e.touches[0].clientX - this.startx) * 1const temptop = (e.touches[0].clientY - this.starty) * 1if (Math.sqrt(Math.pow(templeft, 2) + Math.pow(temptop, 2)) >= 110) {let angle = Math.atan(Math.abs(templeft) / Math.abs(temptop))let rad = (180 * angle / Math.PI)let cx = 0let cy = 0let r = 140//第一象限(右上)if (this.startx < e.touches[0].clientX && this.starty > e.touches[0].clientY) {cx = Math.cos(angle) * -r;cy = Math.sin(angle) * r;}//第三象限(左下)if (this.startx > e.touches[0].clientX && this.starty < e.touches[0].clientY) {cx = Math.cos(angle) * r;cy = Math.sin(angle) * -r;}//第四象限(右下)if (this.startx < e.touches[0].clientX && this.starty < e.touches[0].clientY) {cx = Math.cos(angle) * r;cy = Math.sin(angle) * r;}//第二象限(左上)if (this.startx >= e.touches[0].clientX && this.starty >= e.touches[0].clientY) {cx = Math.cos(angle) * -r;cy = Math.sin(angle) * -r;}//上if (e.touches[0].clientY - this.starty < 0 && rad < 45) {// console.log("上")this.dirtion = '上'this.do('上');}//右if (e.touches[0].clientX - this.startx > 0 && rad >= 45) {// console.log("右")this.dirtion = '右'this.do('右');}//下if (e.touches[0].clientY - this.starty > 0 && rad < 45) {// console.log("下")this.dirtion = '下'this.do('下');}//左if (e.touches[0].clientX - this.startx < 0 && rad >= 45) {// console.log("左")this.dirtion = '左'this.do('左');}this.left = cy * 2this.top = cx * 2} else {this.left = templeft * 2this.top = temptop * 2}},// 开始时start(e) {this.startx = e.touches[0].clientXthis.starty = e.touches[0].clientY// console.log('X轴', this.startx, 'Y轴', this.starty);},// 意外取消时与完成时cancelAndEnd(e) {this.left = 0this.top = 0this.dirtion = ''this.$emit('remoteCancelAndEnd')}}}
</script><style lang="scss" scoped>.rocker{width: 450rpx;height: 450rpx;border-radius: 50%;background-color: #F4F4F4;display: flex;justify-content: center;align-items: center;}.content_trangle {width: 110rpx;height: 110rpx;border: 150rpx solid #000;// border-top-color: red;// border-bottom-color: yellow;// border-left-color: skyblue;// border-right-color: green;border-color: #fff;border-radius: 50%;margin-top: -10rpx;margin-left: -10rpx;}.curise {position: absolute;top: 0rpx;left: 0rpx;bottom: 0rpx;right: 0rpx;margin: auto;width: 105rpx;height: 105rpx;background-color: #5ABF78;// background-color: #fff;border-radius: 50%;}.core {width: 400rpx;height: 400rpx;position: absolute;top: 0;left: 0;display: flex;flex-wrap: wrap;transform: rotate(45deg);>view:nth-child(-n+4) {width: 200rpx;height: 200rpx;display: flex;justify-content: center;align-items: center;image {width: 30rpx;height: 50rpx;}}>view:nth-child(1)>image {transform: rotate(45deg);margin-right: 20rpx;}>view:nth-child(2)>image {transform: rotate(135deg);margin-right: 20rpx;}>view:nth-child(3)>image {transform: rotate(-45deg);margin-right: 20rpx;}>view:nth-child(4)>image {transform: rotate(-135deg);margin-right: 20rpx;}}
</style>
2.方法二:利用相对定位与绝对定位控制盒子,可拓展性强
代码如下(示例):
<template><view style="width: 100%;height: 800rpx;display: flex;justify-content: center;align-items: center;"><view class="container" :style="{width:containerWH+'rpx',height:containerWH+'rpx'}"><view class="core" :style="{width:controlWH+'rpx',height:controlWH+'rpx'}"><view class="core_fourview"><!-- <view><image src="../../static/img/image/nav-arrow-left.png" mode=""></image></view> --><view :style="dirtion === '上' ? viewActiveStyle:''"><image src="../../static/img/image/nav-arrow-left-fff.png" mode="" v-if="dirtion === '上'"></image><image src="../../static/img/image/nav-arrow-left.png" mode="" v-else></image></view><view :style="dirtion === '右' ? viewActiveStyle:''"><image src="../../static/img/image/nav-arrow-left-fff.png" mode="" v-if="dirtion === '右'"></image><image src="../../static/img/image/nav-arrow-left.png" mode="" v-else></image></view><view :style="dirtion === '左' ? viewActiveStyle:''"><image src="../../static/img/image/nav-arrow-left-fff.png" mode="" v-if="dirtion === '左'"></image><image src="../../static/img/image/nav-arrow-left.png" mode="" v-else></image></view><view :style="dirtion === '下' ? viewActiveStyle:''"><image src="../../static/img/image/nav-arrow-left-fff.png" mode="" v-if="dirtion === '下'"></image><image src="../../static/img/image/nav-arrow-left.png" mode="" v-else></image></view></view><!-- 控制的小球 --><view class="curise" @touchmove="move" @touchstart="start" @touchcancel="cancelAndEnd"@touchend="cancelAndEnd" :style="{left:left+'rpx',top:top+'rpx',width:circleWH+'rpx',height:circleWH+'rpx',backgroundColor:circleBgColor}"></view><!-- 白底小球 --><view class="curise_fff" :style="{width:colorcircleWH+'rpx',height:colorcircleWH+'rpx',backgroundColor:colorCircleStyle}"></view></view></view></view>
</template><script>export default {props:{// 主容器宽高,可以用来扩展阴影containerWH:{type:Number,default:450},// 整个控制容器的宽高controlWH:{type:Number,default:400},//判断小球移动多少大于值,开始计算方向与顶边comparenum: {type: Number,default: 100},//手指超出外圆的范围顶点是哪comparewidth: {type: Number,default: 140},// 可移动小球的宽高circleWH:{type:Number,default:100},//可移动小球的背景颜色circleBgColor:{type:String,default:'#5ABF78'},// 方向盒子确认方向后活动的样式viewActiveStyle:{type:String,default:`background-color:#79F6BC;`},// 小球移动后原先的小球占点,宽度与高度比移动小球小colorcircleWH:{type:Number,default:95},//小球移动后原先的小球占点背景颜色colorCircleStyle:{type:String,default:`#fff`},// 箭头图片宽高大小imgWH:{type:String,default:50},// 箭头图片margin-right值大小imgMarRight{type:Number,default:20}},data() {return {left: 0,top: 0,startx: 0, //x坐标starty: 0, //y坐标dirtion:'',}},onLoad() {},methods: {do(direct) {this.$emit('remote', direct);// this.dirtion = direct},// 移动时move(e) {// 向上移,Y轴的值减小,向下移,Y轴的值增大 | 向左移,X轴的值在减小,向右移X轴的值在增大// console.log('eX',e.touches[0].clientX,'eY',e.touches[0].clientY);const templeft = (e.touches[0].clientX - this.startx) * 1const temptop = (e.touches[0].clientY - this.starty) * 1if (Math.sqrt(Math.pow(templeft, 2) + Math.pow(temptop, 2)) >= this.comparenum) {let angle = Math.atan(Math.abs(templeft) / Math.abs(temptop))let rad = (180 * angle / Math.PI)let cx = 0let cy = 0let r = this.comparewidth//第一象限(右上)if (this.startx < e.touches[0].clientX && this.starty > e.touches[0].clientY) {cx = Math.cos(angle) * -r;cy = Math.sin(angle) * r;}//第三象限(左下)if (this.startx > e.touches[0].clientX && this.starty < e.touches[0].clientY) {cx = Math.cos(angle) * r;cy = Math.sin(angle) * -r;}//第四象限(右下)if (this.startx < e.touches[0].clientX && this.starty < e.touches[0].clientY) {cx = Math.cos(angle) * r;cy = Math.sin(angle) * r;}//第二象限(左上)if (this.startx >= e.touches[0].clientX && this.starty >= e.touches[0].clientY) {cx = Math.cos(angle) * -r;cy = Math.sin(angle) * -r;}//上if (e.touches[0].clientY - this.starty < 0 && rad < 45) {// console.log("上")this.dirtion = '上'this.do('上');}//右if (e.touches[0].clientX - this.startx > 0 && rad >= 45) {// console.log("右")this.dirtion = '右'this.do('右');}//下if (e.touches[0].clientY - this.starty > 0 && rad < 45) {// console.log("下")this.dirtion = '下'this.do('下');}//左if (e.touches[0].clientX - this.startx < 0 && rad >= 45) {// console.log("左")this.dirtion = '左'this.do('左');}this.left = cy*2this.top = cx*2} else {this.left = templeft*2this.top = temptop*2}},// 开始时start(e) {this.startx = e.touches[0].clientXthis.starty = e.touches[0].clientY// console.log('X轴', this.startx, 'Y轴', this.starty);},// 意外取消时与完成时cancelAndEnd(e) {this.left = 0this.top = 0this.dirtion = ''this.$emit('remoteCancelAndEnd')}}}
</script><style lang="scss" scoped>.container{// width: 450rpx;// height: 450rpx;border-radius: 50%;background-color: #F4F4F4;display: flex;justify-content: center;align-items: center;.core{width: 400rpx;height: 400rpx;border-radius: 50%;background-color: #FFF;overflow: hidden;position: relative;.core_fourview{width: 100%;height: 100%;display: flex;flex-wrap: wrap;transform: rotate(45deg);>view:nth-child(-n+4) {width: 200rpx;height: 200rpx;display: flex;justify-content: center;align-items: center;image{width: 50rpx;height: 50rpx;}}>view:nth-child(1)>image{transform: rotate(45deg);margin-right: 20rpx;}>view:nth-child(2)>image{transform: rotate(135deg);margin-right: 20rpx;}>view:nth-child(3)>image{transform: rotate(-45deg);margin-right: 20rpx;}>view:nth-child(4)>image{transform: rotate(-135deg);margin-right: 20rpx;}}}.curise {position: absolute;top: 0rpx;left: 0rpx;bottom: 0rpx;right: 0rpx;margin: auto;width: 100rpx;height: 100rpx;background-color: #808080;border-radius: 50%;z-index: 9;}.curise_fff{position: absolute;top: 0rpx;left: 0rpx;bottom: 0rpx;right: 0rpx;margin: auto;// width: 96rpx;// height: 96rpx;// background-color: #fff; border-radius: 50%;z-index: 8;}}</style>
3.使用组件 —import—
<remotesense @remote="thisremote" @remoteCancel="remoteClose" @remoteEnd="remoteClose"></remotesense>//引入注册组件
import remotesense from "组件文件名"export default {components: {remotesense},
data(){return{requestStatus: false, //摇杆防抖directtion: '', //方向,可加可不加timesset: null //控制定时器有无}},methods:{// 遥控thisremote(e) {if (this.requestStatus) {// 利用 return 终止函数继续运行return false;}clearInterval(this.timesset)let timeCount = 0this.timesset = setInterval(() => {if (timeCount >= 2) { //2是每1秒继续发送请求timeCount = 0this.thisremote(e) //利用重复调用函数监测方向}timeCount += 1 //增长速度},500)// 执行逻辑console.log('发送请求','方向:',e);// 发送请求,1.5s发送一次请求this.requestStatus = truesetTimeout(() => {// 改变 requestStatusthis.requestStatus = false;}, 1000); //1s捕抓一次方向},// 摇杆取消,手指离开,此方法由remotesense组件传递过来的remoteClose(){clearInterval(this.timesset)},}}
总结
提示:这里对文章进行总结:
送自己和大家一句话吧:乾坤未定,你我皆是黑马!!!加油
uni-app:游戏摇杆,遥控控制4方向 常用于移动端组件相关推荐
- 360°平滑游戏摇杆(触屏方向导航)
Android游戏开发二十四]360°平滑游戏摇杆(触屏方向导航) 本站文章均为 李华明Himi 原创,转载务必在明显处注明:(作者新浪微博: @李华明Himi ) 转载自[黑米GameDev街区]原 ...
- Unity3D 游戏引擎之IOS自定义游戏摇杆与飞机平滑的移动(十一)
Unity3D 游戏引擎之IOS自定义游戏摇杆与飞机平滑的移动 雨松MOMO原创文章如转载,请注明:转载至我的独立域名博客雨松MOMO程序研究院,原文地址:http://www.xuanyusong. ...
- vue插槽solt ,uni.app
一.什么是插槽? 插槽就是子组件提供给父组件使用的一个占位符,用<slot></solt>表示父组件可以在这个占位符中填充任何模板代码. 二.插槽的用法 1.创建一个子组件,在 ...
- 手机游戏摇杆控制人物移动解决方案
手机游戏摇杆控制人物移动解决方案 https://zhuanlan.zhihu.com/p/358614239 完成之后的演示 一.摇杆的UI搭建 Panel里主要是一个摇杆的背景(圆环)和摇杆头(红 ...
- STM32F103+NRF2401+游戏摇杆ADC双单片机通信遥控小车
STM32F103+NRF2401+游戏摇杆ADC双单片机通信遥控小车 文章目录 STM32F103+NRF2401+游戏摇杆ADC双单片机通信遥控小车 前言 一.实现的功能? 二.主要代码及模块讲解 ...
- Unity UGUI通过摇杆joystick 控制角色移动 标准的第三人称视角手游-左侧控制移动,右侧控制视角和方向
Unity UGUI通过摇杆joystick 控制角色移动 标准的第三人称视角手游-左侧控制移动,右侧控制视角和方向 效果图显示 附上demo下载地址 备注:资源是URP的,普通平台修改资源材质即可 ...
- android 游戏遥感,Android2.2+游戏摇杆 MOPS魅影T800评测
为游戏而生:MOPS魅影T800 Android凭借着自身出色的设计以及丰富的第三方软件应用的支持,目前已经成为了最炙手可热的智能手机系统之一,很多朋友对Android感兴趣是因为其具有非常丰富的软件 ...
- 【Unity插件】游戏摇杆Joystick
文章目录 前言 一.Joystick摇杆类型 二.摇杆基本属性 三.摇杆使用方法 四.其他功能及扩展 总结 前言 最近开发很多游戏Demo中都有用到游戏摇杆Joystick.个人还是挺喜欢用这个插件的 ...
- 自定义View之游戏摇杆键盘实现(二)
前言 去年开发项目,需要实现一个遥感按钮,控制公司机器人行走,于是通过自定义SurfaceView实现了该功能,想了解的话,传送门在这自定义View之游戏摇杆键盘实现,但由于传输指令过程中对时间准确度 ...
最新文章
- spring boot 整合mybatis 无法输出sql的问题
- 2014年百度之星程序设计大赛 - 初赛(第二轮)Chess
- Django中提供的6种缓存方式
- 在Homebrew 发布程序
- 关于vue,angularjs1,react之间的对比
- keil MDK编译器警告和错误详解(不定期更新)
- APACHE OFBIZ XML-RPC 反序列化漏洞 (CVE-2020-9496) 的复现与分析
- 大数据分析系统包含哪些功能板块
- 10.RabbitMQ实战 --- 监控
- 读python学习手册
- python中文版-python有中文版吗
- Windows 7硬盘安装工具 NT6 HDD Installer v3.0(含图文教程)
- android时间轴折线图,echarts时间轴折线图
- 公众号原主体营业执照已注销 如何办理账号迁移和公证书?
- 五险一金真的那么重要吗?为什么很多人宁愿做小时工不要五险一金?
- 墨者学院—Webmin未经身份验证的远程代码执行(简单复习)
- 机智云受邀加入中国智能家居产业联盟智慧酒店小组
- HYBBS2.3轻论坛M-TOUCH模板源码
- JavaScript如何截取字符串的最后一位
- Spring Integration