Web workers and Canvas data

前端 未结 1 1578
南旧
南旧 2021-01-27 05:33

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

I want to create a small

相关标签:
1条回答
  • 2021-01-27 05:57

    DOM can't be accessed from a 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.

    Worker-side :

    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);
    

    Main-page side :

    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);
    };
    

    EDIT :

    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();
    
    0 讨论(0)
提交回复
热议问题