使用nodeJS的跨浏览器canvas没有find函数的签名
我试图在页面上创build一个canvas,每当用户在上面画一些东西时就会自动更新。 但是,看起来好像下面的一段代码(来自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")
这是我的canvas在我的HTML:
<canvas id="myCanvas" width="200" height="100" style="border:1px solid #000000;"> </canvas>
这里是完整的节点JS:
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); }); });
当用户在我的canvas中按住并移动鼠标时,绘图将被消除:
这里是代码:
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脚本:
<script> window.onload = function(){ var socket = io.connect("http://localhost:1337"); socket.on("drawn_complete",function(data){ ctx.putImageData(data.image,0,0); console.log("Everthing worked technically"); }); var c = document.getElementById("myCanvas"); var moving = false; console.log(c); var ctx = c.getContext("2d"); var rect = c.getBoundingClientRect(); 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; }; }; </script>
更新由于Palanikbuild议我发现它之前序列化图像:
var stringfy = JSON.stringify(ctx.getImageData(0,0,200,100)); socket.emit("drawing",{"image": stringfy});
看起来好像控制台仍然抛出相同的错误
更新(2)作为@Palanikbuild议我试图序列化的对象。 我知道下面的代码并不是他推荐的,但我只想强调一些非常奇特的东西:
发件人:
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?
这里的解决scheme是使用canvas.toDataURL();
。
这将返回一个Base64编码的图像string(在MIMEtypes和编码的头)。
var canvas = getMyCanvas(), ctx = canvas.getContext("2d"), encodedImageData = canvas.toDataURL(), image = new Image(); image.src = encodedImageData; ctx.drawImage(image, x, y, w, h...);
您可以愉快地将这些编码的string传递给服务器和从服务器传递。
您也可以在普通的HTML <img src="data:image/png;base64,...">
使用它们。
另外,你可以传递给toDataURL
几个参数:
canvas.toDataURL("image/jpeg", 0.5);`
其中,第一个参数是请求的文件types,第二个参数是请求的图像质量级别(介于0和1之间)。
不过,不能保证任何浏览器都能支持你所要求的东西,不pipe怎么说,无论如何你可能只会得到一个.png文件(无论如何,这可能是你想要的一个游戏,透明度)。
此外,Android 2.2浏览器和更低,和IE9,我觉得移动Safari 5.1(原来的iPad),不支持.toDataURL
。
我可能是iPad的错,但他们不支持其他有用的HTML5 API。
ImageData可能不可移植。 尝试在发送和反序列化之前序列化imagedata,并在接收端创buildimagedata。
===更新===
就像是 :
寄件人
canvasData = ctx.getImageData(0,0,200,100)} myData = { height : canvasData.height, width : canvasData.width, raw : canvasData.data }; socket.emit("drawing",{"image": myData});
接收器
imgData = ctx.getImageData(myData.width, myData.height); for (var i = 0; i < myData.raw.length) { imgData.data[i] = myData.raw[i]; } ctx.putImageData(imgData, 0, 0);
这是未经testing的代码。 只是一个想法让你尝试一下。