1

I need to download the created pixel drawing from this Phaser example as a .png image via FilesSaver.js but the canvas returns null.

Error:

Uncaught TypeError: Cannot read properties of null (reading 'toBlob')

This is the save function:

function save() { 
var canvasX = document.getElementById("canvas");
canvasX.toBlob(function(blob) { saveAs(blob, "image.png"); }); }

drawingArea: (PhaserJS 2)

function createDrawingArea() {

    game.create.grid('drawingGrid', 16 * canvasZoom, 16 * canvasZoom, canvasZoom, canvasZoom, 'rgba(0,191,243,0.8)');

    canvas = game.make.bitmapData(spriteWidth * canvasZoom, spriteHeight * canvasZoom);
    canvasBG = game.make.bitmapData(canvas.width + 2, canvas.height + 2);

    canvasBG.rect(0, 0, canvasBG.width, canvasBG.height, '#fff');
    canvasBG.rect(1, 1, canvasBG.width - 2, canvasBG.height - 2, '#3f5c67');

    var x = 10;
    var y = 64;

    canvasBG.addToWorld(x, y);
    canvasSprite = canvas.addToWorld(x + 1, y + 1);
    canvasGrid = game.add.sprite(x + 1, y + 1, 'drawingGrid');
    canvasGrid.crop(new Phaser.Rectangle(0, 0, spriteWidth * canvasZoom, spriteHeight * canvasZoom));

}

How to get the data of the drawing to create a .png out of it?

Tom
  • 5,588
  • 20
  • 77
  • 129
  • 2
    Are you sure `canvasX` is a dom element and not A `null` ? (What I mean is, is there any `` element exist in a dom having `id="canvas"`) – Jimish Fotariya Sep 27 '21 at 18:15
  • I would agree with @JimishFotariya that you should make sure the element you are selecting has `id="canvas"`. If you've confirmed at least that, check that the variable `canvasX` is actually referencing the intended DOM element. You need that to be accurate first (I have no way to confirm based on the code you provided). Beside that, add more details to your question with a [minimum reproducible example](https://stackoverflow.com/help/minimal-reproducible-example). – phentnil Sep 27 '21 at 19:54
  • 1
    @phentnil Thanks for your comments. If I set "this.game.canvas.id = 'canvas'" the PNG will be the whole stage. How to download jsut the drawing without the UI? – Tom Sep 27 '21 at 21:01
  • So, it's safe to assume that you are getting a PNG file when running your code? If so, be sure to modify your question. It's difficult to determine how to best answer your question of getting just the drawing since you mention [FileSaver.js](https://github.com/eligrey/FileSaver.js). Using vanilla JavaScript, you can use `var ctx = canvasX.getContext("2d")` to get the [CanvasRenderingContext2D](https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D) interface, then use `var imgData = ctx.getImageData(sx, sy, sw, sh)` to pull the image data and save to a file. – phentnil Sep 27 '21 at 21:37
  • 2
    I am not sure if you aware of the `save` button in your example that converts the image into 2d hexa array. example: ```var frame0 = [ '.2222...', '.2......', '.2.33333', '.2.38883', '.2.38883', '.2.33333', '...33AA3', '...33AA3' ]; game.create.texture('yourKey', frame0, 6, 6, 0);``` – user16930239 Sep 27 '21 at 23:29
  • 1
    @Tom did my Solution help, or is it missing something? – winner_joiner Oct 03 '21 at 04:31

1 Answers1

1

Well I don't think the canvas has the ID canvas. That's why, I asume that is the reason for the null Error. In any case I took the original example code, as a basis for this working solution.

Disclaimer: This Code will only create a image from the "drawn-image", not the whole UI.

Main idea, On Save:

  1. create a new canvas
  2. draw the target area into the new canvas
  3. create the image, with filesave.js

Info: I'm getting information/values from the the globally defined variables canvasGrid and canvas, if your code, doesn't contain them, this code will not work.

I hope this helps.

    function saveImage() { 
        // I assume there will be only one canvas on the page
        let realCanvas = document.querySelector('canvas');
        let ouputCanvas = document.createElement('canvas');
        let ctx = ouputCanvas.getContext('2d');

        // Get the target area (Details are from example code)
        let xOfGrid = canvasGrid.x - 1; // Info from Linie 267 from example
        let yOfGrid = canvasGrid.y - 1; // Info from Linie 267 from example

        // Info: this "canvas" is not a HTML Canvas Element
        let width = canvas.width;   // Info from Linie 256 from example
        let height = canvas.height; // Info from Linie 256 from example

        // Set initial Canvas Size
        ouputCanvas.width = width;
        ouputCanvas.height = height;

        // draw Image onto new Canvas
        ctx.drawImage(realCanvas, xOfGrid, yOfGrid, width, height, 0, 0, width, height);

        // Output Image, with filesaver.js
        ouputCanvas.toBlob(function onDone(blob) {
            saveAs(blob, "image.png");
        });
    }

    // An extra "Save Button", for testing
    window.addEventListener('DOMContentLoaded', function(){
        let btn = document.createElement('button');
        btn.innerText = 'SAVE FILE';
        btn.addEventListener('click', saveImage);
        document.body.prepend( btn );
    });
       
winner_joiner
  • 12,173
  • 4
  • 36
  • 61