我正在尝试在页面上构建一个画布,只要用户在其上绘制内容就会自动更新.但是看起来好像下面的一段代码(来自index.html)导致错误
socket.on("drawn_complete",function(data){ ctx.putImageData(data.image,0,0); console.log("Everthing worked technically"); });
这是在我的控制台中输出的错误:
Uncaught TypeError: Failed to execute 'putImageData' on 'CanvasRenderingContext2D': No function was found that matched the signature provided
我的data.image是从以下代码返回的内容:
ctx.getImageData(0,0,200,100); // ctx is canvas.getContext("2d")
这是我的html中的画布:
这是完整的nodeJS:
var http = require("http") var server = http.createServer(handler).listen(1337); console.log("Server created at 127.0.0.1:1337"); var io = require("socket.io").listen(server); function handler(req,res) { console.log("Client Connected"); res.writeHead(200,{"Content-type": "text/plain"}); res.end("Hello World"); } io.sockets.on("connection",function(socket){ socket.on("drawing",function(data){ var image = data["image"]; io.sockets.emit("drawn_complete",image); }); });
当用户握住并在我的画布中移动鼠标时,绘图就会被触发:
这是代码:
c.onmousedown = function(evt){ moving = true }; c.onmousemove = function(evt){ if(moving == true) { console.log("holding and moving"); var x = evt.clientX - rect.left; var y = evt.clientY - rect.top; console.log("X: " + x + " Y: " + y); ctx.fillRect(x,y,1,1); socket.emit("drawing",{"image": ctx.getImageData(0,0,200,100)}); } }; c.onmouseup = function(evt){ moving = false; };
UPDATE
这是enitre脚本:
更新 正如Palanik建议我在发射图像之前将其序列化为序列化:
var stringfy = JSON.stringify(ctx.getImageData(0,0,200,100)); socket.emit("drawing",{"image": stringfy});
看起来控制台仍然会抛出相同的错误
更新(2) 正如@Palanik建议我尝试序列化对象.我知道下面的代码并不完全是他推荐的,但我只是想强调一些非常特殊的东西:
发件人:
var stringfy = ctx.getImageData(0,0,200,100); console.log(stringfy) var sent = JSON.stringify(stringfy); socket.emit("drawing",{"image": sent});
Reciever
socket.on("drawn_complete",function(data){ imageData = JSON.parse(data.image); console.log(imageData); ctx.putImageData(imageData,0,0); console.log("Everthing worked technically");
});
这里有趣的是,imageData的console.log打印出一个具有与ImageData相同的确切属性的对象.高度,宽度和原始.看看这里:
{"height":100,"width":200,"data":{"0":0,"1":0,"2":0,"3":0,"4":0,"5 etc... }
因此,从这里我可以看到,我能够得到对象.如果我在java中,演员就足够了;
ImageData object = (ImageData) imageData // Is there a way to do this?
Norguard.. 9
这里的解决方案是使用canvas.toDataURL();
.
这将返回Base64编码的图像字符串(在头部具有MIME类型和编码).
var canvas = getMyCanvas(), ctx = canvas.getContext("2d"), encodedImageData = canvas.toDataURL(), image = new Image(); image.src = encodedImageData; ctx.drawImage(image, x, y, w, h...);
您可以愉快地将这些编码的字符串传递给服务器或从服务器传出.
您也可以在常规HTML中使用它们.
此外,您可以传递toDataURL
几个参数:
canvas.toDataURL("image/jpeg", 0.5);`
其中,第一个参数是请求的文件类型,第二个参数是请求的图像质量级别(介于0和1之间).
但是,无法保证任何浏览器都能支持您所要求的内容,无论如何您可能只会获得一个.png文件(这可能是您想要的游戏,透明胶片,无论如何).
另外,Android 2.2浏览器和IE9,以及我认为Mobile Safari 5.1(原版iPad)不支持.toDataURL
.
我可能错误的是iPad,但它们不支持其他HTML5 API,它们可以结合使用.