Javascript 使用“CanvasRenderingContext2D.putImageData()”时出现白色屏幕,即使数据似乎包含图像

Javascript 使用“CanvasRenderingContext2D.putImageData()”时出现白色屏幕,即使数据似乎包含图像,javascript,node.js,html5-canvas,Javascript,Node.js,Html5 Canvas,我正在尝试在节点服务器上托管一个NES模拟器()。我知道可以将JSNE嵌入带有unpkg的网页中,但我希望它在服务器上运行,因为我希望多个客户端共享相同的状态。我编写了复制的代码,以便在服务器上运行emulator(有效),并将帧缓冲区作为响应发送到客户端以获取请求(有效),最后在画布中显示该帧缓冲区。我可以console.log记录图像数据,它看起来是正确的,(所谓“looks correct”,我的意思是它大部分包含黑色像素,图像中间有一些特征),但我得到的只是一个白色屏幕。谁能看出我做错了

我正在尝试在节点服务器上托管一个NES模拟器()。我知道可以将JSNE嵌入带有unpkg的网页中,但我希望它在服务器上运行,因为我希望多个客户端共享相同的状态。我编写了复制的代码,以便在服务器上运行emulator(有效),并将帧缓冲区作为响应发送到客户端以获取请求(有效),最后在画布中显示该帧缓冲区。我可以
console.log
记录图像数据,它看起来是正确的,(所谓“looks correct”,我的意思是它大部分包含黑色像素,图像中间有一些特征),但我得到的只是一个白色屏幕。谁能看出我做错了什么

index.html:

<!DOCTYPE html>

<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <title>Example</title>

    </head>
    <body>
        <div style="">
            <canvas id="canvas" width="256" height="240" style="border: 1px solid black;"/>
        </div>
        <script type="text/javascript" src="game.js"></script>
    </body>
</html>
server.js

const fs = require('fs');
var express = require('express');
var jsnes = require('jsnes');
var path = require('path');

var app = express();

var SCREEN_WIDTH = 256;
var SCREEN_HEIGHT = 240;
var FRAMEBUFFER_SIZE = SCREEN_WIDTH * SCREEN_HEIGHT;
var buffer = new ArrayBuffer(FRAMEBUFFER_SIZE);
var framebuffer_u8 = new Uint8ClampedArray(buffer);
var framebuffer_u32 = new Uint32Array(buffer);

var nes = new jsnes.NES({
    onFrame: function(framebuffer_24) {
        for (var i = 0; i < FRAMEBUFFER_SIZE; i++) framebuffer_u32[i] = 0xFF000000 | framebuffer_24[i];
    },
});

var romData = fs.readFileSync('InterglacticTransmissing.nes', {
    encoding: 'binary'
});

nes.loadROM(romData);

app.get('/', function(request, response) {
    response.sendFile(path.join(__dirname, 'index.html'));
    console.log('/');
});

app.get('/game.js', function(request, response) {
    response.sendFile(path.join(__dirname, 'game.js'));
    console.log('/game');
});

app.get('/data', function(request, response) {
    response.setHeader('Content-Type', 'application/json');
    response.send(JSON.stringify(framebuffer_u8));
    console.log('/data');
});

setInterval(function() {
    nes.frame();
}, 1000 / 60);

app.listen(3000);

当您在服务器端的
uint8clampedaray
实例上调用
JSON.stringify()
时,它将被序列化为JS对象,即使您希望它是一个数组

const data = new Uint8ClampedArray(3);
data.set([1,2,3]);

const json = JSON.stringify(data);
JSON

当您在客户端使用
JSON.parse()
对其进行反序列化时,您将获得JS对象并尝试将其传递给
ImageData.data.set()

ImageData.data
是,它期望一个数组被传递给它的
set()
方法,但是当你传递一个对象时,它会自动忽略它

你也可以

  • 使用将帧缓冲区转换为服务器端的阵列,然后将其序列化:

    const data = new Uint8ClampedArray(3);
    data.set([1,2,3]);
    
    const dataArray = Array.from(data);
    
    const json = JSON.stringify(dataArray);
    
    // response.send(json);
    
    JSON

  • 或者在客户端将反序列化对象转换为数组

    const dataArray = Object.values(response);
    image.data.set(dataArray);
    
  • {
      "0":1,
      "1":2,
      "2":3
    }
    
    const data = new Uint8ClampedArray(3);
    data.set([1,2,3]);
    
    const dataArray = Array.from(data);
    
    const json = JSON.stringify(dataArray);
    
    // response.send(json);
    
    [1,2,3]
    
    const dataArray = Object.values(response);
    image.data.set(dataArray);