2016-09-26 100 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

工作就像一個魅力!我正在使這種方式比它所需要的更復雜。感謝徹底的迴應,並提供兩種解決方案! –