Touchmove data is not transmitted constantly to Node.js

ぐ巨炮叔叔 提交于 2019-12-13 22:18:36

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!