本文介绍了Web工作者和Canvas数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看过很多关于网络工作者和< canvas> 数据传递的线程,我不知道我的场景是否可以实现。

I have seen a lot of threads about web workers and <canvas> data passing, and I'm not sure if my scenario is implementable.

我想创建一个小网站,让用户学习Javascript代码。当用户单击按钮时,代码在Web worker中运行。为了帮助他们,我还创建了打印的方法(基本上只是添加文本到< pre> 元素。

I want to create a small site for users to learn to code in Javascript. When users click a button, the code is run in a web worker. To help them, I have also created methods for "printing" (which basically just adds text to a <pre> element.

// get code from user and prepend helper "functions"
var userCode = editor.getValue();
var codeWithMessages = "\n\
    function print(data) { postMessage(\"\"+data); } \n\
    function println(data) { postMessage(\"\"+data+\'\\n\'); } \n\
    function alert(data) { postMessage('ALERT'+data); }  \n\
    \n" + userCode;
var codeWithMessagesAndExit = codeWithMessages + "\npostMessage('exit()');";
var blob = new Blob([codeWithMessagesAndExit], {type: 'application/javascript'});
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
outer.worker = new Worker(blobURL);

...
// handle messages by "printing" to the run-output element, or display
// a success message when finishing
outer.worker.addEventListener('message', function (event) {

        if (event.data == "exit()") {
            outer.worker.terminate();
            outer.worker = null;

            outer.codeRunStatus = outer.CODE_RUN_SUCCESS;
            outer.errorMessage = null;
            outer.outputFromLatestRun = $("#run-output").text();
            $("#run-output").append("<span class='code-run-success'>\nKörning klar</span>");
            enableButtons();
        }
        else if (event.data.indexOf("ALERT") == 0) {
            alert(event.data.substring(5));
        }
        else {
            $("#run-output").append(event.data);
        }
    }, false);
// start the worker
outer.worker.postMessage();

现在我想为页面添加一个画布,所以用户可以编写代码来绘制。

Now I want to add a canvas to the page, so users could write code to draw on it.

var canvas = document.getElementById("user-canvas");
var ctx = canvas.getContext("2d");
var imgData = ctx.getImageData(0,0,canvas.width,canvas.height);
// rest same as above
outer.worker.postMessage(imgData);

我不知道如何从这里继续。理想情况下,用户可以编写

I don't know how to proceed from here. Ideally the users could write something like

myCanvas.fillStyle = "rgb(200,0,0)";
myCanvas.fillRect (10, 10, 55, 50);

,然后由事件监听器处理,就像我用 ()函数。这是否可能?

and then have this processed by the event listener like I did with my print() functions. Is this possible?

推荐答案

无法从WebWorker访问DOM。

DOM can't be accessed from a WebWorker.

我可以看到的最好的方法是在webworker中重新定义这个对象,并定义一个协议来发送每个调用到一个方法。

The best way I can see is to re-define this object in the webworker, and define a protocol to transmit each call to a method. But it won't work when you need other objects like images.

工人端:

var CanvasRenderingContext2D = function() {
    this.fillStyle = "black";
    this.strokeStyle = "black";
    ...
    this.lineWidth = 1.0;
};

["fillRect", "strokeRect", "beginPath", ... "rotate", "stroke"].forEach(function(methodName) {
    CanvasRenderingContext2D.prototype[methodName] = function() {
        postMessage({called: methodName, args: arguments, currentObjectAttributes: this});
    };
});

...

var myCanvas = new CanvasRenderingContext2D();
myCanvas.fillStyle = "rgb(200,0,0)";
myCanvas.fillRect(10, 10, 55, 50);

主页侧:

var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");
var worker = new Worker( ... );
worker.onMessage = function(event) {
    var data = event.data;

    // Refreshing context attributes
    var attributes = data.currentObjectAttributes;
    for(var k in attributes) {
        context[k] = attributes[k];
    }

    // Calling method
    var method = context[data.called];
    method.apply(context, data.args);
};

编辑:

它与您的代码(未测试)。要整合它,我不得不改变工作者发送的消息的结构。

I tried to integrate it with your code (not tested). To integrate it, I had to change the structure of the messages sent by the worker.

// get code from user and prepend helper "functions"
var userCode = editor.getValue();
var codeWithMessages = '\n\
function print  (data) { postMessage(["print", data.toString()]); } \n\
function println(data) { postMessage(["print", data.toString() + "\\n"]); } \n\
function alert  (data) { postMessage(["alert", data.toString()]); } \n\
var CanvasRenderingContext2D = function() { \n\
    this.fillStyle   = "black"; \n\
    this.strokeStyle = "black"; \n\
    /* ... */ \n\
    this.lineWidth = 1.0; \n\
}; \n\
["fillRect", "strokeRect", "beginPath", /* ... */ "rotate", "stroke"].forEach(function(methodName) { \n\
    CanvasRenderingContext2D.prototype[methodName] = function() { \n\
        postMessage(["canvas", {called: methodName, args: Array.prototype.slice.call(arguments), currentObjectAttributes: this}]); \n\
    }; \n\
});\n' + userCode;
var codeWithMessagesAndExit = codeWithMessages + "\npostMessage(['exit']);";
var blob = new Blob([codeWithMessagesAndExit], {type: 'application/javascript'});
// Obtain a blob URL reference to our worker 'file'.
var blobURL = window.URL.createObjectURL(blob);
outer.worker = new Worker(blobURL);

...

// Define your canvas ...
var canvas = document.createElement("canvas");
var context = canvas.getContext("2d");

// handle messages by "printing" to the run-output element, or display
// a success message when finishing
outer.worker.addEventListener('message', function (event) {
    var method = event.data[0] || null;
    var data   = event.data[1] || null;

    if(method == "canvas") {
        // Refreshing context attributes
        var attributes = data.currentObjectAttributes;
        for(var k in attributes) {
            context[k] = attributes[k];
        }

        // Calling method
        var method = context[data.called];
        method.apply(context, data.args);
    } else if(method == "exit") {
        outer.worker.terminate();
        outer.worker = null;

        outer.codeRunStatus = outer.CODE_RUN_SUCCESS;
        outer.errorMessage = null;
        outer.outputFromLatestRun = $("#run-output").text();
        $("#run-output").append("<span class='code-run-success'>\nKörning klar</span>");
        enableButtons();
    } else if(method == "alert") {
        alert(data);
    } else if(method == "print") {
        $("#run-output").append(data);
    } else {
        $("#run-output").append(event.data);
    }
}, false);
// start the worker
outer.worker.postMessage();

这篇关于Web工作者和Canvas数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-01 20:40