修复无法连接小车无线wifi功能

This commit is contained in:
myperworld committed 2025-08-13 18:17:58 +08:00
1 parent 3113d5ac91
commit 067af8f2cc
9 files changed
+2283 -502

No files matched your search

+442
View File
@@ -0,0 +1,442 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>控制器</title>
<style>
*{box-sizing:border-box;margin:0;padding:0}
body{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;background-color:#fff;font-family:'Segoe UI',Arial,sans-serif;padding:20px}
.page-title{color:#333;margin-bottom:40px;text-align:center;font-weight:600}
.joysticks-container{display:flex;gap:60px;align-items:center;justify-content:center;flex-wrap:wrap;width:100%;max-width:1200px}
.joystick-item{display:flex;flex-direction:column;align-items:center;gap:15px}
.joystick-label{color:#333;font-weight:500;font-size:16px;text-align:center;padding:5px 10px;border-radius:4px;background-color:rgba(255,255,255,.8)}
.joystick-wrapper{display:flex;position:relative}
.joystick-wrapper.vertical{flex-direction:column;align-items:center}
.joystick-wrapper.horizontal{flex-direction:row;align-items:center}
.joystick-track{position:relative;box-shadow:0 4px 12px rgba(0,0,0,.1);background-color:#e0e0e0;border-radius:30px;overflow:hidden;transition:box-shadow .2s ease}
.joystick-track:hover{box-shadow:0 6px 16px rgba(0,0,0,.15)}
.joystick-track.vertical{width:60px;height:300px}
.joystick-track.horizontal{width:300px;height:60px}
.joystick-handle{position:absolute;width:50px;height:50px;background-color:#4a90e2;border-radius:50%;box-shadow:0 3px 8px rgba(0,0,0,.25);cursor:grab;transition:transform .1s ease-out,background-color .2s ease;user-select:none;-webkit-user-select:none;border:2px solid rgba(255,255,255,.7)}
.joystick-handle:active{cursor:grabbing;background-color:#357abd;transform:scale(.95)}
.joystick-wrapper.vertical .joystick-handle{left:5px;top:125px}
.joystick-wrapper.horizontal .joystick-handle{left:125px;top:5px}
.value-display{display:flex;align-items:center;justify-content:center;background-color:#e0e0e0;color:#fff;border-radius:8px;font-weight:600;font-size:18px;width:60px;height:40px;box-shadow:0 2px 5px rgba(0,0,0,.1);transition:background-color .2s ease}
.value-display.active{background-color:#4a90e2}
.joystick-wrapper.vertical .value-display{margin-top:20px}
.joystick-wrapper.horizontal .value-display{margin-left:20px}
.usage-info{margin-top:40px;color:#666;font-size:14px;text-align:center;max-width:600px;line-height:1.5}
@media (max-width:1024px){.joysticks-container{gap:40px}
.joystick-track.vertical{width:50px;height:250px}
.joystick-track.horizontal{width:250px;height:50px}
.joystick-handle{width:40px;height:40px}
.joystick-wrapper.vertical .joystick-handle{left:5px;top:105px}
.joystick-wrapper.horizontal .joystick-handle{left:105px;top:5px}
}
@media (max-width:768px){.joysticks-container{flex-direction:column;gap:60px}}
.button-container {
display: flex;
gap: 50px;
margin-bottom: 20px;
}
.control-btn {
padding: 12px 24px;
background: #fff;
color: #2196F3;
border: 2px solid #2196F3;
border-radius: 6px;
cursor: pointer;
transition: all 0.3s;
}
</style>
</head>
<body onload="javascript:socket_init()">
<h1 class="page-title">控制器</h1>
<div class="button-container">
<button class="control-btn" id="blink">blink</button>
<button class="control-btn" id="dir">jump</button>
</div>
<div class="joysticks-container">
<!-- 1. 水平摇杆 -->
<div class="joystick-item">
<div class="joystick-label">摇摆</div>
<div id="roll" class="joystick-wrapper horizontal"></div>
</div>
<!-- 2. 垂直摇杆 -->
<div class="joystick-item">
<div class="joystick-label">高度</div>
<div id="height" class="joystick-wrapper vertical"></div>
</div>
<!-- 3. 垂直摇杆 -->
<div class="joystick-item">
<div class="joystick-label">前后</div>
<div id="joy_y" class="joystick-wrapper vertical"></div>
</div>
<!-- 4. 水平摇杆 -->
<div class="joystick-item">
<div class="joystick-label">左右</div>
<div id="joy_x" class="joystick-wrapper horizontal"></div>
</div>
</div>
<script>
var socket; // socket通信
function socket_init() {
socket = new WebSocket('ws://' + window.location.hostname + ':81/'); // sta模式
}
// 摇杆控制器类 - 封装所有功能
class Joystick {
/**
* 创建一个新的摇杆实例
* @param {string} containerId - 容器元素的ID
* @param {string} direction - 方向,可选值:'vertical' 或 'horizontal'
*/
constructor(containerId, direction = 'vertical', min = -100, max = 100) {
// 初始化属性
this.container = document.getElementById(containerId);
this.direction = direction;
this.id = containerId;
this.isDragging = false;
this.startPos = 0;
this.currentPos = 0;
this.centerPos = 0;
this.min = min;
this.max = max;
this.range = max - min;
// 创建摇杆元素
this.createElements();
// 获取元素引用
this.handle = this.container.querySelector('.joystick-handle');
this.track = this.container.querySelector('.joystick-track');
this.valueDisplay = this.container.querySelector('.value-display');
// 初始化尺寸和位置
this.initDimensions();
// 绑定事件处理函数
this.bindEvents();
// 设置初始位置
this.setHandlePosition(this.centerPos);
}
/**
* 创建摇杆所需的DOM元素
*/
createElements() {
// 创建轨道元素
const track = document.createElement('div');
track.className = `joystick-track ${this.direction}`;
// 创建把手元素
const handle = document.createElement('div');
handle.className = 'joystick-handle';
// 创建数值显示元素
const valueDisplay = document.createElement('div');
valueDisplay.className = 'value-display';
valueDisplay.textContent = '0';
// 组合元素
track.appendChild(handle);
this.container.appendChild(track);
this.container.appendChild(valueDisplay);
}
/**
* 初始化摇杆尺寸和位置参数
*/
initDimensions() {
if (this.direction === 'vertical') {
// 纵向摇杆尺寸
this.trackSize = this.track.offsetHeight;
this.handleSize = this.handle.offsetHeight;
this.centerPos = (this.trackSize - this.handleSize) / 2;
} else {
// 横向摇杆尺寸
this.trackSize = this.track.offsetWidth;
this.handleSize = this.handle.offsetWidth;
this.centerPos = (this.trackSize - this.handleSize) / 2;
}
}
/**
* 限制值在指定范围内
* @param {number} value - 要限制的值
* @param {number} min - 最小值
* @param {number} max - 最大值
* @returns {number} 限制后的值
*/
clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
/**
* 更新显示的数值
* @param {number} position - 把手的位置
*/
updateValue(position) {
// 计算原始值(-100~100)
const offset = this.direction === 'vertical'
? this.centerPos - position
: position - this.centerPos;
const rawPercentage = (offset / this.centerPos) * 100;
const rawValue = this.clamp(Math.round(rawPercentage), -100, 100);
// 计算映射值
const mappedValue = Math.round(
((rawValue + 100) / 200) * this.range + this.min
);
// 更新显示映射值
this.valueDisplay.textContent = mappedValue;
// 触发事件携带双重值
this.dispatchValueChange({
raw: rawValue,
mapped: mappedValue,
min: this.min,
max: this.max
});
// 活动状态样式
if (mappedValue !== this.min && mappedValue !== this.max) {
this.valueDisplay.classList.add('active');
} else {
this.valueDisplay.classList.remove('active');
}
}
/**
* 触发值变化事件
* @param {number} value - 当前值
*/
dispatchValueChange({raw, mapped}) {
const event = new CustomEvent('valuechange', {
detail: {
rawValue: raw,
mappedValue: mapped,
min: this.min,
max: this.max,
id: this.id,
direction: this.direction,
joystick: this
},
bubbles: true
});
this.container.dispatchEvent(event);
}
/**
* 设置摇杆把手位置
* @param {number} pos - 位置值(纵向是top,横向是left)
*/
setHandlePosition(pos) {
// 限制在轨道范围内
const minPos = 0;
const maxPos = this.trackSize - this.handleSize;
const constrainedPos = this.clamp(pos, minPos, maxPos);
// 设置位置
if (this.direction === 'vertical') {
this.handle.style.top = `${constrainedPos}px`;
} else {
this.handle.style.left = `${constrainedPos}px`;
}
// 更新数值
this.updateValue(constrainedPos);
}
/**
* 回到中心位置(带动画效果)
*/
returnToCenter() {
if (!this.isDragging) {
const currentPosition = parseFloat(
this.direction === 'vertical'
? this.handle.style.top
: this.handle.style.left
) || this.centerPos;
const distance = this.centerPos - currentPosition;
// 如果距离很小,直接回到中心
if (Math.abs(distance) < 1) {
this.setHandlePosition(this.centerPos);
return;
}
// 平滑动画回到中心
const step = distance * 0.5; // 每次移动剩余距离的20%
this.setHandlePosition(currentPosition + step);
// 继续动画
requestAnimationFrame(() => this.returnToCenter());
}
}
/**
* 绑定事件处理函数
*/
bindEvents() {
// 鼠标按下事件
this.handle.addEventListener('mousedown', (e) => {
this.isDragging = true;
this.startPos = this.direction === 'vertical' ? e.clientY : e.clientX;
this.currentPos = parseFloat(
this.direction === 'vertical'
? this.handle.style.top
: this.handle.style.left
) || this.centerPos;
e.preventDefault();
});
// 鼠标移动事件
document.addEventListener('mousemove', (e) => {
if (this.isDragging) {
const delta = (this.direction === 'vertical' ? e.clientY : e.clientX) - this.startPos;
this.setHandlePosition(this.currentPos + delta);
}
});
// 鼠标释放事件
document.addEventListener('mouseup', () => {
if (this.isDragging) {
this.isDragging = false;
this.returnToCenter();
}
});
// 触摸屏开始事件
this.handle.addEventListener('touchstart', (e) => {
this.isDragging = true;
this.startPos = this.direction === 'vertical'
? e.touches[0].clientY
: e.touches[0].clientX;
this.currentPos = parseFloat(
this.direction === 'vertical'
? this.handle.style.top
: this.handle.style.left
) || this.centerPos;
e.preventDefault(); // 防止触摸事件被浏览器默认处理
});
// 触摸屏移动事件 - 修改事件绑定方式,添加passive选项
document.addEventListener('touchmove', (e) => {
if (this.isDragging) {
const delta = (this.direction === 'vertical'
? e.touches[0].clientY
: e.touches[0].clientX) - this.startPos;
this.setHandlePosition(this.currentPos + delta);
e.preventDefault(); // 防止页面滚动
}
}, { passive: false }); // 关键修改:明确指定passive为false
// 触摸屏结束事件
document.addEventListener('touchend', () => {
if (this.isDragging) {
this.isDragging = false;
this.returnToCenter();
}
});
// 窗口大小变化时重新计算尺寸
window.addEventListener('resize', () => {
this.initDimensions();
if (!this.isDragging) {
this.setHandlePosition(this.centerPos);
}
});
}
}
const controlState = {
blink: 0,
dir: "stop", // 4 = stop, 5 = jump
roll: 0,
height: 30,
joy_y: 0,
joy_x: 0
};
// 统一发送函数
function sendAllData() {
const data = {
dir: controlState.dir,
roll: controlState.roll,
height: controlState.height,
joy_y: controlState.joy_y,
joy_x: controlState.joy_x,
blink: controlState.blink,
stable: 1,
'mode': 'basic',
};
console.log(data);
// socket.send(JSON.stringify(data));
// 重置瞬时状态
controlState.blink = 0;
controlState.dir = "stop";
}
// 初始化摇杆实例
document.addEventListener('DOMContentLoaded', () => {
// 创建四个摇杆,按顺序:水平、垂直、垂直、水平
const joysticks = [
new Joystick('roll', 'horizontal', -30, 30),
new Joystick('height', 'vertical', 0, 60),
new Joystick('joy_y', 'vertical'),
new Joystick('joy_x', 'horizontal')
];
// 监听所有摇杆的数值变化事件
document.querySelectorAll('.joystick-wrapper').forEach((wrapper, id) => {
wrapper.addEventListener('valuechange', (e) => {
// console.log(`摇杆 ${e.detail.id} (${e.detail.direction}) 值: ${e.detail.value}`);
// console.log(e.detail);
switch(e.detail.id) {
case 'roll':
controlState.roll = e.detail.mappedValue;
break;
case 'height':
controlState.height = e.detail.mappedValue;
break;
case 'joy_y':
controlState.joy_y = e.detail.mappedValue;
break;
case 'joy_x':
controlState.joy_x = e.detail.mappedValue;
break;
}
sendAllData();
});
});
document.querySelectorAll('.control-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
switch(e.target.id) {
case 'blink':
controlState.blink = 1;
break;
case 'dir':
controlState.dir = "jump";
break;
}
sendAllData();
});
});
});
</script>
</body>
</html>