我正在尝试获得一个不错的旋钮/转盘,可以旋转该旋钮/转盘以通过websockets将值发送回服务器。
基本前提很好,我从网上获得了代码。
我正在尝试修改代码,以便获得更漂亮的旋钮。我成功地将画布放置在显示静态图像的div内,而画布根据鼠标/触摸事件旋转了半透明图像。
我对代码进行的添加在台式机上运行良好(我正在运行Firefox 45.0.2),但在iPad(Safari,iOS 9.3.5)上根本无法运行,而在iPhone(iOS 10.2)上则完全无法运行。 1)
在iPhone上,旋钮的旋转方向与预期的相反,通常只有水平移动才能使旋钮旋转。
我没有使用(也不希望使用)诸如jquery之类的任何库。
下面的代码将按原样工作。但是,删除正文部分的注释标记会导致我指出的问题。
(哦,为了阻止所有评论,黑色背景和奇数文字的颜色就在那里,以便您可以看到不带静态背景的半透明元素)
我完全没有jscript的经验,只能设法遵循当前代码的作用。 (我不想使用其他库的原因之一)
我怀疑问题在于如何解释触摸事件坐标,但我无法进行任何测试。
任何帮助或建议,将不胜感激。
HTML代码:
<!DOCTYPE html>
<html>
<head>
<title>Stepper example</title>
<meta name="viewport" content="width=device-width, initial-scale=0.7">
<style>
body {
text-align: center; background-color: black;
color: red
}
.container{
position: relative;
background: url(step_background.png);
width: 480px;
height: 480px;
margin: auto;
z-index:1;
}
.knob{
position: relative;
top: 59px;
background: url(knob_bg.png);
width: 362px;
height:362px;
margin:auto;
z-index:2;
}
#stepper{
position: relative;
}
</style>
<script>
var MIN_TOUCH_RADIUS = 20;
var MAX_TOUCH_RADIUS = 200;
var CANVAS_WIDTH = 362, CANVAS_HEIGHT = 362;
var PIVOT_X = 181, PIVOT_Y = 181;
var plate_angle = 0;
var plate_img = new Image();
var click_state = 0;
var last_angle_pos = 0;
var mouse_xyra = {x:0, y:0, r:0.0, a:0.0};
var ws;
plate_img.src = "knob_fg.png";
function init() {
var stepper = document.getElementById("stepper");
var ctx = stepper.getContext("2d");
stepper.width = CANVAS_WIDTH;
stepper.height = CANVAS_HEIGHT;
stepper.addEventListener("touchstart", mouse_down);
stepper.addEventListener("touchend", mouse_up);
stepper.addEventListener("touchmove", mouse_move);
stepper.addEventListener("mousedown", mouse_down);
stepper.addEventListener("mouseup", mouse_up);
stepper.addEventListener("mousemove", mouse_move);
ctx.translate(PIVOT_X, PIVOT_Y);
rotate_plate(plate_angle);
}
function connect_onclick() {
if(ws == null) {
ws = new WebSocket('ws://'+ window.location.hostname + ':81/', ['arduino']);
document.getElementById("ws_state").innerHTML = "CONNECTING";
ws.onopen = ws_onopen;
ws.onclose = ws_onclose;
ws.onmessage = ws_onmessage;
ws.onerror = function(){ alert("websocket error " + this.url) };
}
else
ws.close();
}
function ws_onopen() {
document.getElementById("ws_state").innerHTML = "<font color='blue'>CONNECTED</font>";
document.getElementById("bt_connect").innerHTML = "Disconnect";
rotate_plate(plate_angle);
}
function ws_onclose() {
document.getElementById("ws_state").innerHTML = "<font color='gray'>CLOSED</font>";
document.getElementById("bt_connect").innerHTML = "Connect";
ws.onopen = null;
ws.onclose = null;
ws.onmessage = null;
ws = null;
rotate_plate(plate_angle);
}
function ws_onmessage(e_msg) {
e_msg = e_msg || window.event; // MessageEvent
plate_angle = Number(e_msg.data);
rotate_plate(plate_angle);
//alert("msg : " + e_msg.data);
}
function rotate_plate(angle) {
var stepper = document.getElementById("stepper");
var ctx = stepper.getContext("2d");
ctx.clearRect(-PIVOT_X, -PIVOT_Y, CANVAS_WIDTH, CANVAS_HEIGHT);
ctx.rotate(-angle / 180 * Math.PI);
ctx.drawImage(plate_img, -PIVOT_X, -PIVOT_Y);
ctx.rotate(angle / 180 * Math.PI);
/*
Currently, the angle displayed and sent as a message appears to be set such that movement in a clockwise direction
reports a negative number. Needs to be looked at, probably by changing "angle.toFixed" to "-angle.toFixed"
*/
if(ws && (ws.readyState == 1))
ws.send(plate_angle.toFixed(4) + "\r\n");
ws_angle = document.getElementById("ws_angle");
ws_angle.innerHTML = angle.toFixed(1);
}
function check_update_xyra(event, mouse_xyra) {
var x, y, r, a;
var min_r, max_r, width;
if(event.touches) {
var touches = event.touches;
x = (touches[0].pageX - touches[0].target.offsetLeft) - PIVOT_X;
y = PIVOT_Y - (touches[0].pageY - touches[0].target.offsetTop);
}
else {
x = event.offsetX - PIVOT_X;
y = PIVOT_Y - event.offsetY;
}
/* cartesian to polar coordinate conversion */
r = Math.sqrt(x * x + y * y);
a = Math.atan2(y, x);
mouse_xyra.x = x;
mouse_xyra.y = y;
mouse_xyra.r = r;
mouse_xyra.a = a;
if((r >= MIN_TOUCH_RADIUS) && (r <= MAX_TOUCH_RADIUS))
return true;
else
return false;
}
function mouse_down(event) {
if(event.target == stepper)
event.preventDefault();
if(event.touches && (event.touches.length > 1))
click_state = event.touches.length;
if(click_state > 1)
return;
if(check_update_xyra(event, mouse_xyra)) {
click_state = 1;
last_angle_pos = mouse_xyra.a / Math.PI * 180.0;
}
}
function mouse_up() {
click_state = 0;
}
function mouse_move(event) {
var angle_pos, angle_offset;
if(event.touches && (event.touches.length > 1))
click_state = event.touches.length;
if(!click_state || (click_state > 1))
return;
if(!check_update_xyra(event, mouse_xyra)) {
click_state = 0;
return;
}
event.preventDefault();
angle_pos = mouse_xyra.a / Math.PI * 180.0;
if(angle_pos < 0.0)
angle_pos = angle_pos + 360.0;
angle_offset = angle_pos - last_angle_pos;
last_angle_pos = angle_pos;
if(angle_offset > 180.0)
angle_offset = -360.0 + angle_offset;
else
if(angle_offset < -180.0)
angle_offset = 360 + angle_offset;
plate_angle += angle_offset;
rotate_plate(plate_angle);
}
window.onload = init;
</script>
</head>
<body>
<h2>
Smart Expansion / Stepper Motor<br><br>
Angle <font id="ws_angle" color="blue">0</font><br><br>
<!--
<div class="container">
<div class="knob">
-->
<canvas id="stepper"></canvas>
<!--
</div>
</div>
-->
<br><br>
WebSocket <font id="ws_state" color="gray">CLOSED</font>
</h2>
<p><button id="bt_connect" type="button" onclick="connect_onclick();">Connect</button></p>
</body>
</html>
我可能需要添加其他注释,以提供指向背景图片的链接
答案 0 :(得分:0)
因此,在设法找出如何通过Windows上的firefox在ios设备上调试html之后,我设法找出了导致我的代码失败的原因。
问题出在检查函数check_update_xyra(event,mouse_xyra)
具体来说,行:
x = (touches[0].pageX - touches[0].target.offsetLeft) - PIVOT_X;
y = PIVOT_Y - (touches[0].pageY - touches[0].target.offsetTop);
target.offsetxxx返回的值为0。这使弧度值(r)超出范围,从而导致函数返回false,或者在iPhone的情况下,导致触摸事件的行为异常。
偏移量返回为0的原因是因为我没有考虑到它们仅提供与目标父对象的偏移量,而不是整个文档的事实。
我设法通过添加一些代码为所有父元素添加偏移量来解决此问题,然后使用该总和来计算新的x和y坐标。
我的代码更改如下。
但是,如果有人有一种更优雅的计算偏移量的方法,我将不胜感激。
干杯...
function check_update_xyra(event, mouse_xyra) {
var x, y, r, a;
var tgtoffleft = 0;
var tgtofftop = 0;
var min_r, max_r, width;
if(event.touches) {
var touches = event.touches;
// Bit of code to calculate the actual Left and Top offsets by adding offsets
// of each parent back through the hierarchy
var tgt = event.touches[0].target;
while (tgt) {
tgtoffleft = tgtoffleft + tgt.offsetLeft;
tgtofftop = tgtofftop + tgt.offsetTop;
tgt = tgt.offsetParent;
}
// x = (touches[0].pageX - touches[0].target.offsetLeft) - PIVOT_X;
// y = PIVOT_Y - (touches[0].pageY - touches[0].target.offsetTop);
x = (touches[0].pageX - tgtoffleft) - PIVOT_X;
y = PIVOT_Y - (touches[0].pageY - tgtofftop);
}
else {
x = event.offsetX - PIVOT_X;
y = PIVOT_Y - event.offsetY;
}
/* cartesian to polar coordinate conversion */
r = Math.sqrt(x * x + y * y);
a = Math.atan2(y, x);
mouse_xyra.x = x;
mouse_xyra.y = y;
mouse_xyra.r = r;
mouse_xyra.a = a;
if((r >= MIN_TOUCH_RADIUS) && (r <= MAX_TOUCH_RADIUS))
return true;
else
return false;
}