2016-09-26 84 views
0

上下文:我正在创建一个Web应用程序,我可以在画布上绘画,将其保存为图像,并通过节点将其发送给另一个客户端。如何通过节点js发送div?

什么工作:(无论是客户端上它是实时更新)

  • 绘图。
  • 保存帆布作为Uint8Array
  • 保存帆布作为IMG DIV W/base64编码图像

如果我坚持:

我似乎无法管道完成的图像给其他客户。我可以用各种方式保存画布,但不知道如何穿过画布。

如何,我将它发送到节点服务器作为一个div:

byId('sendHTML').onclick = SendImageHTML; 
    function SendImageHTML() {  
     var imageHTML = convertCanvasToImage(canvas); 
     socket.emit('SendImageHTML', imageHTML); 
     // EMITS: <img src="data:image/png;base64, iVB9023423523345346....." 
    } 

发送的Uint8Array:

/** 
    * Converts canvas to bytes & emits web socket message 
    * @return {Uint8Array} Bytes from canvas 
    */  
    byId('defImgBinary').onclick = DefineImageBinary; 
    function DefineImageBinary() { 
     var image = context.getImageData(0, 0, canvas.width, canvas.height); 
     var buffer = new ArrayBuffer(image.data.length); 
     var bytes = new Uint8Array(buffer); 

     for (var i=0; i<bytes.length; i++) { 
      bytes[i] = image.data[i]; 
     } 

     socket.emit('defImgBinary', bytes); 
     // EMITS: [24, 24, 29, 255, 24, 24, 29, 255, 24, 24.......] 

    } 

这里是我的服务器代码:

socket.on('SendImageHTML', function (html) { 
    console.log("SendImageHTML called: "); 
    log(html); 
    // RETURNS: 
    // SendImageHTML called: 
    // {} 
}); 




socket.on('defImgBinary', function (bytes) { 
    log("defImgBinary called: "); 
    log(bytes); 
    // RETURNS: 
    // defImgBinary called: 
    // '53721': 220, 
    // '53722': 219, 
    // '53723': 255, 
    // '53724': 229, 
}); 

我需要什么帮助:

我该怎么做它从那里?我如何在其他客户端上实际显示此图像?

+1

只是'socket.broadcast.emit'数据从服务器。它会将它发送到[除了发送图像数据的所有连接的套接字上](http://socket.io/docs/#broadcasting-messages)。由于您发送的是''html,因此客户端可以将其添加到DOM,并且它将显示在下一个呈现中。 – nem035

回答

3

如果您使用Canvas API中的getDataURL(),然后发送base64编码图像或渲染的DOM元素,那么您会满意吗?

在客户端:

您可以通过HTMLCanvasElement.toDataURL获得你的画布base64编码数据。这将导致以data:image/png;base64...开头的字符串,就像在您的代码示例中一样。

当您获得的字符串,您可以直接发送到服务器作为字符串,或将其呈现的图像元素:

var image = new Image(width, height); 
image.src = myBase64String; 

image.addEventListener('load', function() { /* NOTE On image loaded */ }); 

如果你想发送呈现的DOM元素添加到服务器,您可能会发现Element.outerHTML非常有用 - 此属性将返回元素的精确字符串表示(例如,"<img src="data:image/png;base64..." width="256" height="256" />")。

在服务器端:

在这两种情况下,你可以简单地经由各自的插槽中的数据发送到其他客户端。

另客户端:

如果你发送一个简单的base64编码字符串,它可以很容易地使用Image元素显示:

var image = new Image(256, 256); 
image.src = receivedBase64String; 

image.addEventListener('load', function() { 
    document.appendChild(image); 
}); 

如果您发送的已绘制元素,你可使用document.createElement放入DOM结构:

var image = document.createElement('div'); // NOTE Create a 'host' element 
image.innerHTML = receivedRenderedElementString; 

document.appendChild(image); 

实施例:

请参阅下面的代码以获取工作示例。

客户端:

<title> 
    Canvas Sample 
</title> 
<p> 
    <canvas id="sample-canvas" width="256" height="256"></canvas> 
</p> 
<p> 
    <button id="send-canvas"> 
    Send canvas 
    </button> 
    <label for="send-as-div"> 
    <input type="checkbox" id="send-as-div"> 
     Send as div 
    </input> 
    </label> 
</p> 
<p id="output-console"></p> 

<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script> 
<script> 
    // NOTE Simple IO console element for socket communication 
    let outputConsole = document.querySelector('#output-console'); 
    let printToConsole = (text = '') => { 
    outputConsole.innerHTML += text + '<br/>'; 
    }; 
    let renderToConsole = (element) => { 
    outputConsole.appendChild(element); 
    outputConsole.innerHTML += '<br/>'; 
    }; 

    // NOTE Load image (random cat image) 
    let image = new Image(250, 250); 
    image.src = 'http://thecatapi.com/api/images/get?format=src&size=small'; 
    printToConsole('Image loading.'); 

    // NOTE Setup canvas 
    // Render the cat image when it is loaded. 
    let canvas = document.querySelector('#sample-canvas'); 
    let context = canvas.getContext('2d'); 

    image.addEventListener('load',() => { 
    context.drawImage(image, 0, 0); 
    printToConsole('Image loaded.'); 
    }); 

    image.addEventListener('error', (error) => { 
    printToConsole('Image error.' + JSON.strinfify(error)); 
    }); 

    // NOTE Setup a websocket 
    // Socket will allow to send 'img' message with either a base64 encoded 
    // image data, or a rendered HTML Image element. 
    let socket = io('ws://localhost:8080/'); 

    socket.on('error', (error) => { 
    printToConsole('Socket error.' + JSON.stringify(error)); 
    }); 

    socket.on('img', (image) => { 
    let renderedImage = null; 

    if (image.indexOf('data:image/') === 0) { 

     // NOTE If we receive a base64 image, we render it as an Image 
     renderedImage = new Image(250, 250); 
     renderedImage.src = image; 
    } else { 

     // NOTE If we receive a rendered <img> element, we render it directly 
     // via document.createElement 
     renderedImage = document.createElement('div'); 
     renderedImage.innerHTML = image; 
    } 

    printToConsole('Received image.'); 
    renderToConsole(renderedImage); 
    }); 

    // NOTE Setup button 
    let sendButton = document.querySelector('#send-canvas'); 

    sendButton.addEventListener('click',() => { 
    let encodedCanvas = canvas.toDataURL(); 
    let sendAsDiv = document.querySelector('#send-as-div').checked; 
    let payload = null; 

    if (sendAsDiv) { 
     let imageElement = new Image(250, 250); 
     imageElement.src = encodedCanvas; 

     payload = imageElement.outerHTML; 
    } else { 
     payload = encodedCanvas; 
    } 

    socket.emit('img', payload); 

    printToConsole('Image sent.'); 
    }); 
</script> 

服务器端(需要npm install -D express socket.io):

'use strict'; 

let express = require('express'); 
let http = require('http'); 
let socketIo = require('socket.io'); 

// NOTE Setup server 
let httpServer = http.createServer(express()); 
let socketServer = socketIo(httpServer); 
let sockets = []; 
let port = 8080; 

httpServer.listen(port); 

// NOTE Setup socket listener 

socketServer.on('connection', (socket) => { 
    sockets.push(socket); 

    let socketId = sockets.length; 

    socket.on('img', (payload) => { 
    socket.broadcast.emit('img', payload); 
    }); 
}); 

让我知道是否能解决您的问题

+1

Upvoted用于提及要连接的客户端使用的映像的base64表示形式。 – Alex

+0

工作就像一个魅力!我正在使这种方式比它所需要的更复杂。感谢彻底的回应,并提供两种解决方案! –