之前用做了一台树莓派小车,然后写了个简易的遥控器,现在觉得太蹩脚,不能调整转速,特来做一个手机端的小车遥控器:


接下来摆在我面前的问题就是选择什么语言进行编写咯,我首先考虑了JAVA,首先我从来没写过JAVA的程序,而且IDE装起来很麻烦,而且还是英文的,那更加完全不懂了。然后是C#,很多人都不知道C#可以写Android应用。其实是可以的,但是Android Studio我上次用着卡卡的,印象不是很好,不想用。那还剩下什么选择呢?还有一个:HTML5。
好了我去装了个Hbuilder:

中文的,很好用,问题在于我也从来没用过javascript,不过这是小问题啦。
打开Hbuilder,设置一些护眼什么的,然后点左上角[文件]-[新建]-[移动APP]。然后我选了个模板:

嗯,这就是这个程序在手机上执行的时候的样子。然后我模仿着加了一个列表项到index.html里面去:

<li id="plus/controller.html" onclick="clicked(this.id);"><span class="item">Controller<div class="chs">小车遥控器</div></span>
</li>

好的,于是这个列表就加了一个选项了。:

继续,在plus文件夹里边添加一个controller.html,这就是我们的摇杆所存在的页面。在这个页面上,我们需要一个canvas标签和一个js脚本共同来绘制摇杆:

<!DOCTYPE html>
<html><head><meta charset="UTF-8"><meta name="viewport" content="initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /><meta name="HandheldFriendly" content="true" /><meta name="apple-mobile-web-app-capable" content="yes" /><!--<meta name="MobileOptimized" content="320" />--><title>小车遥控器</title><script type="text/javascript" src="../js/common.js"></script></head><body><div class="leftjoystick"><canvas id="joystick" width="120" height="120"></canvas><script src="../js/Joystick.js"></script></div></body>
</html>

好了,开始写代码绘制摇杆之前,我先做了两幅图,这样绘制摇杆时候就比较省力气了,效果也比较好。。


【此处省略一整天】
然后经过了一整天来熟悉javascript。我把控制摇杆的js代码捣鼓出来了。放代码咯:

var ji = new Image(); //内摇杆图片
var jo = new Image(); //外摇杆图片
var joystick = document.getElementById('joystick'); //画板
var josize = joystick.height; //外摇杆大小
var jisize = josize * 0.6; //内摇杆大小
var centerX = josize / 2; //摇杆中心x坐标
var centerY = josize / 2; //摇杆中心y坐标
window.addEventListener('load', load, false);
var jc = joystick.getContext('2d'); //画布//摇杆头应当移动到的位置
var jx = 0,jy = 0;//图片加载完成时执行这俩函数
ji.onload = function() {jc.drawImage(ji, centerX - jisize / 2, centerY - jisize / 2, jisize, jisize); //首次绘制内摇杆
}
jo.onload = function() {jc.drawImage(jo, centerX - josize / 2, centerY - josize / 2, josize, josize);
}//绘图函数(绘制图形的时候就是用户观察到摇杆动了,所以取名是move)
function move() {jc.clearRect(centerX - josize / 2, centerY - josize / 2, josize, josize);//清空画板jc.drawImage(jo, centerX - josize / 2, centerY - josize / 2, josize, josize);//画底座jc.drawImage(ji, centerX - jisize / 2 + jx, centerY - jisize / 2 + jy, jisize, jisize);//画摇杆头requestAnimationFrame(move); //下一次绘图
}
ji.src = '../img/joystickin.png';//加载图片
jo.src = '../img/joystickout.png';//加载图片//页面加载时执行该函数
function load() {document.addEventListener('touchstart', touch, false);document.addEventListener('touchmove', touch, false);document.addEventListener('touchend', touch, false);//加载的时候先把摇杆绘制出来再说move();//var effectiveFinger = 0; //当前有效手指//触摸事件触发函数function touch(event) {var event = event || window.event;var oInp = document.getElementById("inp");switch(event.type) {case "touchstart"://              //判断是否击中摇杆头//              if(Math.abs(event.touches[event.identifier].clientX - 100 - jx) <= 40 &&//                  Math.abs(event.touches[event.identifier].clientY - 100 - jy) <= 40) {//                  effectiveFinger = event.identifier; //若是,则将此手指设为有效手指//              }//这个不知道为啥不能起作用,获取不到event.identifier。break;case "touchend"://手指离开的时候//若手指离开,那就把内摇杆放中间jx = 0;jy = 0;break;case "touchmove"://手指移动的时候://是否触摸点在摇杆上if(Math.sqrt(Math.pow(event.touches[effectiveFinger].clientX - centerX, 2) +Math.pow(event.touches[effectiveFinger].clientY - centerY, 2)) <=josize / 2 - jisize / 2) {jx = event.touches[effectiveFinger].clientX - centerX;jy = event.touches[effectiveFinger].clientY - centerY;} else//否则计算摇杆最接近的位置{var x = event.touches[effectiveFinger].clientX,y = event.touches[effectiveFinger].clientY,r = josize / 2-jisize/2;var ans=GetPoint(centerX,centerY,r,centerX,centerY,x,y);//圆与直线有两个交点,计算出离手指最近的交点if(Math.sqrt((ans[0]-x)*(ans[0]-x)+(ans[1]-y)*(ans[1]-y))<Math.sqrt((ans[2]-x)*(ans[2]-x)+(ans[3]-y)*(ans[3]-y))){jx=ans[0]-centerX;jy=ans[1]-centerY;}else{jx=ans[2]-centerX;jy=ans[3]-centerY;}}//move();event.preventDefault();//防止页面滑动,取消掉默认的事件break;}}requestAnimationFrame(move);//开始绘图
}//计算圆于直线的交点(这一块好难啊)
function GetPoint(cx, cy, r, stx, sty, edx, edy) {//(x-cx)^2+(y-cy)^2=r^2//y=k*x+bvar k = (edy - sty) / (edx - stx);var b = edy - k * edx;//(1 + k^2)*x^2 - x*(2*cx -2*k*(b -cy) ) + cx*cx + ( b - cy)*(b - cy) - r*r = 0var x1, y1, x2, y2;var c = cx * cx + (b - cy) * (b - cy) - r * r;var a = (1 + k * k);var b1 = (2 * cx - 2 * k * (b - cy));var tmp = Math.sqrt(b1 * b1 - 4 * a * c);x1 = (b1 + tmp) / (2 * a);y1 = k * x1 + b;x2 = (b1 - tmp) / (2 * a);y2 = k * x2 + b;return [x1,y1,x2,y2];
}

这个代码的思路就是,如果手指在底座上,那么就把摇杆头移动到手指下方,如果手指在底座外,那就把摇杆移动到底座离手指最近的部分。嗯,就是这样。
这整个的遥控器我会上传到Github供大家学习参考,名字就叫做H5RRC。(Html5 RaspberryPi Remote Controller)目前如大家所见我只做出了摇杆,如有错误的欢迎指正,有什么不懂的也可以加入我们的群来咨询(见GitHub),我们的群有问必答(答案质量不能保证),而且没有老司机乱开车(不像某群)。

遥控小车之:HTML5+ 虚拟摇杆相关推荐

  1. STM32F103+NRF2401+游戏摇杆ADC双单片机通信遥控小车

    STM32F103+NRF2401+游戏摇杆ADC双单片机通信遥控小车 文章目录 STM32F103+NRF2401+游戏摇杆ADC双单片机通信遥控小车 前言 一.实现的功能? 二.主要代码及模块讲解 ...

  2. 开源免费代码_02_单摇杆远程遥控小车,基于Arduino的ESP-NOW,ESP32发送指令、ESP32接收指令,实现小车毫秒级完美控制_公羽兴

    发文希望能够帮忙物联网爱好者少走弯路,少被割韭菜.如果觉得此文对您有帮助的话帮忙点个赞,感谢!!! 哔哩哔哩网址:开源免费代码_02_单摇杆远程遥控小车,基于Arduino的ESP-NOW,ESP32 ...

  3. 蓝牙遥控小车2.0版发布啦

    蓝牙遥控小车2.0版发布啦! 蓝牙模块的主从机模式 1.主从机模式 2.设置主从机模式 蓝牙遥控器 1.硬件接线 2.程序设计 蓝牙小车 1.硬件接线 2.程序设计 今天要跟大家分享的是两个蓝牙模块之 ...

  4. 基于树莓派的遥控小车

    一.引言 最近在准备一个计算机类比赛,需要用树莓派做成一个智能乒乓球捡球车,做过一些人工智能项目的也知道,所谓人工智能,只有人工,没有智能(实力吐槽),只要你知道实现的原理,做很多人工智能的东西都能得 ...

  5. 360度虚拟摇杆控制机器人前进后退转弯(一)

    项目需求 最近做一个项目,要求使用虚拟摇杆控制机器人设备前进后退转弯,整个过程的思路不算复杂,写篇文章记录下大致思路 (1)黄色圆不动时候 小车速度为0 (2)拖动摇杆 拖动距离越大 小车速度越大 距 ...

  6. 二丶Android如何自定义一个可移动的飞行虚拟摇杆?

    摘要: 上次我们自定义了一个固定位置摇杆,此摇杆无法调整杆量,且位置固定,这次我们就来定义一个可以自由调整杆量和变换位置的虚拟摇杆. 下面就写一下需要实现此虚拟摇杆的步骤: 一丶初始化资源 我们需要美 ...

  7. Android蓝牙遥控小车软件

    PS:不需写一行Android代码哦~~~                    很多热衷于玩单片机小车.机器人的童靴,往往也向往着有天能自己编写一个Android手机的遥控程序,通过自己的手机遥控小 ...

  8. Unity用UGUI做虚拟摇杆

    一.首先点击UI创建两个Image,将Image的Source Image改成自己想要的Texture即可,然后在Canvas下创建一空物体,将两个Image放在空物体下作为他的子对象: 然后为可以拖 ...

  9. android控制手机强制手机横竖方向,使用android IOIO和安卓手机制作视频遥控小车(控制灯的开关、实时视频传输、方向控制)...

    android IOIO是通过安卓手机的USB接口控制的电路板,通过android IOIO可以不需要太多的硬件知识,通过安卓手机转接的IOIO板控制外围设备,配件有纸盒.L298N电机驱动模块.旧手 ...

最新文章

  1. 解决 E: Unable to correct problems, you have held broken packages. 问题
  2. POJ 3104 Drying [二分 有坑点 好题]
  3. chrome浏览器开发模式实现跨域
  4. (转)使用CGLIB实现AOP功能与AOP概念解释
  5. java 进程 cpu占用_JAVA进程CPU占用高的故障排查 – 运维那些事
  6. 一分钟看懂mysql_冬天发财树“最怕”它,遇上就烂根,一分钟看懂就能养好
  7. sql server 利用 For Xml Path('') 多行数据拼接成一个字符串
  8. CentOS 7 安装OpenOffice并实现WordToPDF(Java调用)
  9. office visio 替代_10个Linux中受欢迎的开源Visio替代品
  10. 网上好用的大数据支持的舆情分析系统工具整合
  11. 博途v14电脑要求_博途v15对电脑配置要求
  12. 计算机人文英语1形考答案,国开《人文英语1》形考任务(单元自测1至8)试题及答案...
  13. ubuntu linux崩溃,ubuntu linux qq崩溃问题的解决方法以及原因
  14. python五笔输入法_centos下安装五笔输入法的教程
  15. 字节游戏测试开发面试题
  16. 3500 vocabulary
  17. 开源的视频编解码器介绍
  18. 原形网络(Prototypical Networks)基于PyTorch的实现
  19. 叮当健康明日港股上市:拟募资3.4亿港元 单季期内亏损4亿
  20. lcy mysql爆破_mysql

热门文章

  1. Endian 的由来
  2. python游戏编程书_Python游戏编程快速上手 第4版 (斯维加特著) 中文pdf扫描版[41MB]...
  3. 开发微信小程序的作用
  4. 维谛技术(Vertiv)隆重举行“笃行——数据中心基础设施智能化管理研讨会”...
  5. 通达信上涨回调选股公式,选出二次走强的标的
  6. 怎么连接云服务器共享文件夹,如何设置局域网共享文件夹
  7. AddMvcCore,AddControllers,AddControllersWithViews,AddRazorPages的区别
  8. 飞凌国产芯片系列经验分享|A40i开发板应用笔记-PWM 的应用
  9. Android设置WIFI静态IP
  10. lambda表达式最全总结