0

Anytime I try to do Konva.Node.create, I get an error: "Uncaught TypeError: Cannot set property 'container' of undefined". As far as I can tell, the data I am using is properly formatted JSON, saved to and then retrieved from a file after using toJSON on an initial stage. I would greatly appreciate any help in solving this. I have posted the console log of the data below, thanks!:

{
    "attrs[width]": "754",
    "attrs[height]": "647",
    "className": "Stage",
    "children[0][className]": "Layer",
    "children[0][children][0][attrs][rotateEnabled]": "false",
    "children[0][children][0][attrs][enabledAnchors][]": [
        "top-left",
        "top-right",
        "bottom-left",
        "bottom-right",
    ],
    "children[0][children][0][className]": "Transformer",
    "children[0][children][1][attrs][draggable]": "true",
    "children[0][children][1][attrs][id]": "square1",
    "children[0][children][1][className]": "Group",
    "children[0][children][1][children][0][attrs][x]": "559",
    "children[0][children][1][children][0][attrs][y]": "342.5",
    "children[0][children][1][children][0][attrs][name]": "Square",
    "children[0][children][1][children][0][attrs][width]": "100",
    "children[0][children][1][children][0][attrs][height]": "100",
    "children[0][children][1][children][0][attrs][fill]": "white",
    "children[0][children][1][children][0][attrs][stroke]": "black",
    "children[0][children][1][children][0][className]": "Rect",
    "children[0][children][1][children][1][attrs][name]": "text",
    "children[0][children][1][children][1][attrs][text]": "Storage",
    "children[0][children][1][children][1][attrs][align]": "center",
    "children[0][children][1][children][1][attrs][verticalAlign]": "middle",
    "children[0][children][1][children][1][attrs][x]": "559",
    "children[0][children][1][children][1][attrs][y]": "382.5",
    "children[0][children][1][children][1][attrs][fontSize]": "15",
    "children[0][children][1][children][1][attrs][width]": "100",
    "children[0][children][1][children][1][attrs][fill]": "black",
    "children[0][children][1][children][1][className]": "Text",
}

Here is the method loadStage that throws the error. I save the code to a JSON file, and retrieve it using node. It is then passed to the function here:

function loadStage(stage) {
    $.ajax({
        type: 'GET',
        //contentType: 'application/json',
        url: '/getstage',
        success: function (data) {
            console.log("'"+data+"'");
            if(data !== "")
            {
                stage = Konva.Node.create(data, 'canvas');
            }
        }
    });
}

Here is the method that saves the code on update (when I add a new shape):

function saveStage() {
    var json = stage.toJSON();
    $.ajax({
        type: 'POST',
        //contentType: 'application/json',
        data: JSON.parse(json),
        url: '/savestage',
        success: function (data) {
            
        }
    });
}

And the error message:

Uncaught TypeError: Cannot set property 'container' of undefined
    at Function.ct._createNode (konva.min.js:12)
    at Function.ct.create (konva.min.js:12)
    at Object.success (facilitytracker.js:46)
    at c (jquery.min.js:2)
    at Object.fireWith [as resolveWith] (jquery.min.js:2)
    at l (jquery.min.js:2)
    at XMLHttpRequest.<anonymous> (jquery.min.js:2)
ct._createNode @ konva.min.js:12
ct.create @ konva.min.js:12
success @ facilitytracker.js:46
c @ jquery.min.js:2
fireWith @ jquery.min.js:2
l @ jquery.min.js:2
(anonymous) @ jquery.min.js:2
load (async)
send @ jquery.min.js:2
ajax @ jquery.min.js:2
loadStage @ facilitytracker.js:38
(anonymous) @ facilitytracker.js:9
e @ jquery.min.js:2
t @ jquery.min.js:2
setTimeout (async)
(anonymous) @ jquery.min.js:2
c @ jquery.min.js:2
fireWith @ jquery.min.js:2
fire @ jquery.min.js:2
c @ jquery.min.js:2
fireWith @ jquery.min.js:2
ready @ jquery.min.js:2
B @ jquery.min.js:2
  • Hi Sam and welcome. You may get a faster answer if you make it easier for the rest of us by setting up a working snippet that illustrates the issue. See my answer to this question for a sample of how to do that https://stackoverflow.com/questions/47395110/selecting-by-drawing-a-box-around-objects-in-konva/47419716#47419716, it is quite easy to set up. I'll keep my eye on this question and dive in when you've done that. – Vanquished Wombat Jun 28 '20 at 10:32
  • Thanks for the suggestion! As you can tell, I'm very new to this. I added some code snippets to hopefully make this clearer, but I can definitely post my code in its entirety if needed. Any help would be absolutely appreciated! – Sam Mortinger Jun 28 '20 at 14:31
  • Hi Sam - getting better. Check out the explanation of how to make a good question https://stackoverflow.com/help/minimal-reproducible-example – Vanquished Wombat Jun 28 '20 at 16:16

2 Answers2

0

Here is a cut down example of save and restore from one stage to another. This is about as simple as I could get for the save and restore step. I suggest you walk through your code your code and confirm that the stage variable is defined, and the 'container' element exists. You will probably discover a simple bug.

// Set up the canvas and shapes
var s1 = new Konva.Stage({container: 'container1', width: 300, height: 200});
var layer1 = new Konva.Layer({draggable: false});
s1.add(layer1);

// draw a rect so we have something to save and load.
var r1 = new Konva.Rect({x: 30, y: 20, width: 200, height: 100, fill: 'cyan' })    
layer1.add(r1);

 var oval = new Konva.Ellipse({
    x: s1.width() / 2,
    y: s1.height() / 2,
    radiusX: 100,
    radiusY: 50,
    fill: 'yellow',
    stroke: 'black',
    strokeWidth: 4,
  });
  
layer1.add(oval);
      
s1.draw() // First draw of canvas.

// List for the go button to be clicked, then save the stage and load it into container 2.
$('#go').on('click', function(){
  
  $('#container2').css('visibility', 'visible');

  // save stage as a json string
  var json = s1.toJSON();


  var s2 = Konva.Node.create(json, 'container2');
  s2.draw();
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">
<script src="https://cdn.rawgit.com/konvajs/konva/1.6.5/konva.min.js"></script>
<p>Click the Save & Load button to save the left hand stage to a serialized string and have that string laoded into a new stage on the right.

</p>

<p>
<button id='go'>Save & load</button>
</p>
<div id='container1' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; border: 4px solid cyan;"></div>
<div id='container2' style="display: inline-block; width: 300px, height: 200px; background-color: silver; overflow: hidden; border: 4px solid magenta; visibility: hidden;"></div>
Vanquished Wombat
  • 9,075
  • 5
  • 28
  • 67
0

Turns out it's an issue with the way fs.readfile and fs.writefile format JSON. I ended up figuring out a workaround, although I'm not fully happy with it. I turned the JSON into a string, and used the substring and split methods to remove superfluous characters. It's annoying because it was valid JSON, but not in a format that Konva would accept.