问题
I have written a little program, in which you can load an image, select the color at the mouse / finger position on clicking, dragging or touchmoving.
If I drag the mouse on the image (canvas
), the color data is transmitted constantly to a node.js
server via socket.io
. On every connected client, the color gets updated immediately.
See the video.
However, if I touch move on a tablet, the color data won´t get transmitted constantly. I have no idea how to fix this. Do you have an idea?
See the project on Github.
app.js (Server)
var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
// include external data, eg. css, images (public folder)
app.use(express.static(__dirname + '/public'));
// By typing localhost:3000 the browser will load index.html
app.get('/', function (req, res) {
res.redirect('/html/index.html'); // alternative: res.sendfile('./public/html/index.html');
});
// Put the application on port 3000
http.listen(3000, function () {
console.log('listening on port 3000');
});
var currentColor = "000000";
io.on('connection', function (socket) {
// Light Control
socket.emit('updateCurrentColor', currentColor);
socket.on('farbe_ClientToServer', function (data) {
currentColor = data;
io.emit('updateCurrentColor', currentColor);
});
socket.on('test',function(data){
console.log(data);
});
});
index.html (Browser)
<!DOCTYPE HTML>
<html>
<head>
<title> Color Sync </title>
<link rel="shortcut icon" href="../img/favicon.ico">
<script src="../js/jquery-1.11.1.js"></script>
<script src="/socket.io/socket.io.js"></script>
<style>
#canvas, body {
background-color: #000000;
}
#field {
background-color: white;
}
</style>
</head>
<body>
<div id="field">
<div id="touchX">touchX</div>
<div id="touchY">touchY</div>
<div id="color">color</div>
</div>
<canvas id="canvas"></canvas>
</body>
<script type="text/javascript">
var socket = io();
//synchronice current color on every device with information from server
socket.on('updateCurrentColor', function (currentColor) {
$('#canvas').css("background-color", "#" + currentColor);
$('body').css("background-color", "#" + currentColor);
});
// setup image on canvas
var margin = 50;
var leftMButtonDown = false;
var canvas = document.getElementById('canvas');
var context = canvas.getContext('2d');
var img = new Image();
img.src = "../img/farbrad.png";
img.onload = function () {
context.canvas.width = img.width; // apply correct side proportions
context.canvas.height = img.height;
resize();
};
window.addEventListener('resize', function () {
resize();
});
/**
* Scale proportionally: If the width of the canvas > the height, the canvas height
* equals the height of the browser window. Else, the canvas width equals the width of the browser window.
* If the window is resized, the size of the canvas changes dynamically.
*/
function resize() {
var ratio = canvas.width / canvas.height;
var canvas_height = window.innerHeight;
var canvas_width = canvas_height * ratio;
if (canvas_width > window.innerWidth) {
canvas_width = window.innerWidth;
canvas_height = canvas_width / ratio;
}
canvas.width = canvas_width - 2 * margin; // resize canvas
canvas.height = canvas_height - 2 * margin;
context.drawImage(img, 0, 0, canvas.width, canvas.height); // resize image on the canvas
}
// checks if the left mouse button is pressed
$("#canvas").mousedown(function () {
leftMButtonDown = true;
});
$("#canvas").mouseup(function () {
leftMButtonDown = false;
});
// get the color at the mouse position on mouse move, but only if the left mouse button is pressed
$('#canvas').mousemove(function (e) {
if (leftMButtonDown == true) {
getColorAtPos(e.pageX, e.pageY);
}
});
// get the color at mouse position on click
$('#canvas').click(function (e) {
getColorAtPos(e.pageX, e.pageY);
});
// implement touch gesture
$('#canvas').on("touchmove", function (ev) {
var e = ev.originalEvent;
e.preventDefault();
getColorAtPos(e.targetTouches[0].pageX, e.targetTouches[0].pageY);
});
// get canvas position and color at this position (mouse/touch)
function getColorAtPos(pageX, pageY) {
var canvasTopLeft = {
x: canvas.offsetLeft,
y: canvas.offsetTop
}
var x = pageX - canvasTopLeft.x;
var y = pageY - canvasTopLeft.y;
$('#touchX').text('canvasX: ' + x);
$('#touchY').text('canvasY: ' + y);
var c = canvas.getContext('2d');
var p = c.getImageData(x, y, 1, 1).data;
var currentColor = ("000000" + rgbToHex(p[0], p[1], p[2])).slice(-6);
// distribute color information
$('#color').text('color: ' + currentColor);
$('#canvas').css("background-color", "#" + currentColor);
$('body').css("background-color", "#" + currentColor);
//@todo: Touchmove position does not get updated constantly! why?
socket.emit('farbe_ClientToServer', currentColor); // send to server
socket.emit('test', currentColor); // watch console in Terminal
}
function rgbToHex(r, g, b) {
return componentToHex(r) + componentToHex(g) + componentToHex(b);
}
function componentToHex(c) {
var hex = c.toString(16);
return hex.length == 1 ? "0" + hex : hex;
}
// get border around canvas
$('#canvas').css('margin', margin);
</script>
</html>
回答1:
Wild guess, but you should probably do less work in getColorAtPos
. You traverse the DOM at least five times every time touchmove
fires (which is A LOT). Cache your elements, batch your DOM reads and writes etc. Also, you might want to throttle your touchmove
handler. I don't know at what rate it fires, but I bet it can overwhelm a mobile device.
来源:https://stackoverflow.com/questions/34212762/touchmove-data-is-not-transmitted-constantly-to-node-js