最近基于ESP32 Arduino 的摄像头例程设计一个网页控制摄像头舵机方向,在网页绘制了一个摇杆并将摇杆坐标发送给esp32。参考了许多网友的资料,终于实现了基础功能,在此记录并分享一下源代码,注释已经尽量详细了。
包括了PC端鼠标坐标的输出,移动端触摸坐标的输出,禁用右键与长按菜单,摄像头视频显示,uri数据发送到esp32等部分。
效果图:
![](https://img-blog.csdnimg.cn/20200601174512593.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2w4NTEyODU4MTI=,size_16,color_FFFFFF,t_70)
源代码:
AIQI-Motor-Demo
* {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
body{
background-color: #282c35;
}
button{
border-radius: 0.9375rem;
border: none;
background-color: #21242d;
box-shadow: 0 8px 16px 0 rgba(0,0,0,0.2), 0 6px 20px 0 rgba(0,0,0,0.19);
border: 2px solid #aaffff;
color: #aaffff;
font-size:1.625rem;
width: 8rem;
}
button:active {
background-color: #282c35;
box-shadow: 0 4px 16px 0 rgba(0,0,0,0.2), 0 3px 20px 0 rgba(0,0,0,0.19);
transform: translateY(4px);
}
#EYE_Button{
border: 2px solid #ff5500;
color: #ff5500;
}
#buttons{
height:auto;
width:auto;
text-align:center;
margin: 2.5rem;
}
#stream-container,#rocker-container{
height:auto;
width:auto;
text-align:center;
margin: 0rem;
}
#rocker-container{
margin: 3rem;
}
#coordiv{
border: 2px solid #aaffff;
border-radius: 0.9375rem;
}
Rotate
Eye-ON
您的浏览器不支持canvas
const view = document.getElementById('stream') //摄像头显示图
const buttons = document.getElementById('buttons') //按钮容器
const rockercontainer = document.getElementById('rocker-container') //摇杆容器
const Rotate_Button = document.getElementById('Rotate_Button') //显示图旋转按钮
const EYE_Button = document.getElementById('EYE_Button') //摄像头开关按钮
var coordiv = document.getElementById('coordiv'); //摇杆画布
var baseHost = document.location.origin //获取URL域名(ip)与端口号
var streamUrl = baseHost + ':81' //esp32 摄像头arduino例程 摄像头流数据端口
//摄像头显示图 角度旋转 每次90°
var ImgRotate = 0;
function RotateButton(){
ImgRotate += 90;
if(ImgRotate >= 360) ImgRotate = 0;
view.style.transform = "rotate("+ImgRotate+"deg)";
if(ImgRotate == 90 || ImgRotate == 270)view.style.margin = "6rem";
else view.style.margin = "0rem"
}
//摄像头开关 通过img src指向控制
function EYEButton(){
const streamEnabled = EYE_Button.innerHTML === 'Eye-ON'
if (streamEnabled) {
view.src = `${streamUrl}/stream`
EYE_Button.style.border = "2px solid #4CAF50";
EYE_Button.style.color = "#4CAF50";
EYE_Button.innerHTML = 'Eye-OFF';
}else{
// view.src = ` `; //清空图片或保持当前图片
window.stop(); //停止页面刷新
EYE_Button.style.border = "2px solid #ff5500";
EYE_Button.style.color = "#ff5500";
EYE_Button.innerHTML = 'Eye-ON';
}
}
//画布尺寸(需要与body内设置相同) 和 摇杆中心坐标(画布尺寸/2)
var coordiv_w = 600;
var coordiv_h = 600;
var center_x = coordiv_w/2;
var center_y = coordiv_h/2;
//摇杆初始化 显示中心坐标和手柄
var loc = "当前位置 x:"+parseInt(center_x/(center_x/5))+",y:"+parseInt(center_y/(center_y/5));
document.getElementById("point-loc").innerHTML = loc;
var ctx=coordiv.getContext("2d"); //画布初始化
new_coordinate(center_x,center_y); //中心位置绘制圆形手柄 并显示坐标
//禁止手机双指缩放 原代码直接复制粘贴
var lastTouchEnd = 0;
document.documentElement.addEventListener('touchend', function (event) {
var now = Date.now();
if (now - lastTouchEnd 1) {
event.preventDefault();
}
}, false);
//移动端浏览器 手指点击相关事件
coordiv.ontouchstart = function(e){//手指头触摸屏幕上的事件
var touch = e.touches[0] //获取第一个触点
var x = this.offsetLeft //e为当前事件 this为当前元素
var y = this.offsetTop //获取当前元素距离页面边界的距离
var NowX = parseInt((touch.pageX - x)) //获取全局点击坐标 计算画布内点击坐标
var NowY = parseInt((touch.pageY - y))
new_coordinate(NowX,NowY) //重绘圆形手柄 并显示当前坐标
document.ontouchmove = function(e){//手指头在屏幕上滑动触发的事件
touch = e.touches[0]; //获取第一个触点
NowX = parseInt((touch.pageX - x)) //计算画布内点击坐标
NowY = parseInt((touch.pageY - y))
new_coordinate(NowX,NowY) //重绘圆形手柄 并显示当前坐标
}
document.ontouchend = function(){//当手指从屏幕上离开的时候触发
//清除事件
new_coordinate(center_x,center_y) //重绘圆形手柄 并显示当前坐标
document.ontouchstart = null //清空点击事件
document.ontouchmove = null
}
}
//PC端浏览器 鼠标点击相关事件
coordiv.onmousedown = function(e){//鼠标按下触发事件
var x = this.offsetLeft
var y = this.offsetTop
var NowX = (e.clientX - x)
var NowY = (e.clientY - y)
new_coordinate(NowX,NowY)
document.onmousemove = function(e){//鼠标按下时持续触发事件
NowX = (e.clientX - x)
NowY = (e.clientY - y)
new_coordinate(NowX,NowY)
}
document.onmouseup = function(){//鼠标抬起触发事件
//清除事件
new_coordinate(center_x,center_y)
document.onmouseup = null
document.onmousemove = null
}
}
var LastX = parseInt(center_x/(center_x/5))
var LastY = parseInt(center_y/(center_y/5))
//绘制摇杆圆形手柄 并显示当前坐标
function new_coordinate(NowX,NowY){
if(NowX>=coordiv_w)NowX=coordiv_w
if(NowY>=coordiv_h)NowY=coordiv_h
if(NowX=coordiv_w)NowX=coordiv_w
if(NowY>=coordiv_h)NowY=coordiv_h
if(NowX=coordiv_h)NowY=coordiv_h
if(NowX |