paperjs / paper.js

The Swiss Army Knife of Vector Graphics Scripting – Scriptographer ported to JavaScript and the browser, using HTML5 Canvas. Created by @lehni & @puckey
http://paperjs.org
Other
14.53k stars 1.23k forks source link

Importing JSON leaves object invisible #822

Closed ghost closed 8 years ago

ghost commented 9 years ago

I've called project.exportJSON to get the following JSON. When I import it with importJSON later, the first object (Circle) is not visible, but the second object (PointText) is visible. Why is that? There have been no opacity changes, and I tried setting visible = true on the circle, but that doesn't work either. What's interesting is that I can set selected = true on the circle and see the bounding box, but the circle itself is still invisible.

screen shot 2015-11-05 at 9 12 17 am
[
   [
      "Layer",
      {
         "applyMatrix":true,
         "children":[
            [
               "Shape",
               {
                  "applyMatrix":false,
                  "data":{
                     "duration":5,
                     "startTime":0
                  },
                  "fillColor":[
                     0,
                     0,
                     1
                  ],
                  "matrix":[
                     1,
                     0,
                     0,
                     1,
                     54,
                     51
                  ],
                  "radius":29.73214,
                  "shadowBlur":12,
                  "shadowColor":[
                     0,
                     0,
                     0
                  ],
                  "size":[
                     59.46427,
                     59.46427
                  ],
                  "strokeColor":[
                     1,
                     0,
                     0
                  ],
                  "type":"circle"
               }
            ],
            [
               "PointText",
               {
                  "applyMatrix":false,
                  "content":"sweet text bro",
                  "data":{
                     "duration":5,
                     "startTime":0
                  },
                  "fillColor":[
                     1,
                     0,
                     0
                  ],
                  "fontSize":20,
                  "leading":24,
                  "matrix":[
                     1,
                     0,
                     0,
                     1,
                     75.3291,
                     108.6
                  ],
                  "shadowBlur":12,
                  "shadowColor":[
                     0,
                     0,
                     0
                  ]
               }
            ]
         ]
      }
   ]
]
sapics commented 9 years ago

@winduptoy Thank you for reporting! I guess that you could get true result with JSON written in below, isn't it? This JSON change just a order of hash object in Shape from your JSON. If my JSON works well, it might come from the order of keys in https://github.com/paperjs/paper.js/blob/develop/src/core/Base.js#L84.

[
   [
      "Layer",
      {
         "applyMatrix":true,
         "children":[
            [
               "Shape",
               {
                  "applyMatrix":false,
                  "matrix":[
                     1,
                     0,
                     0,
                     1,
                     54,
                     51
                  ],
                  "data":{
                     "duration":5,
                     "startTime":0
                  },
                  "type":"circle",
                  "size":[
                     59.46427,
                     59.46427
                  ],
                  "radius":29.73214,
                  "fillColor":[
                     0,
                     0,
                     1
                  ],
                  "shadowBlur":12,
                  "shadowColor":[
                     0,
                     0,
                     0
                  ],
                  "strokeColor":[
                     1,
                     0,
                     0
                  ]
               }
            ],
            [
               "PointText",
               {
                  "applyMatrix":false,
                  "content":"sweet text bro",
                  "data":{
                     "duration":5,
                     "startTime":0
                  },
                  "fillColor":[
                     1,
                     0,
                     0
                  ],
                  "fontSize":20,
                  "leading":24,
                  "matrix":[
                     1,
                     0,
                     0,
                     1,
                     75.3291,
                     108.6
                  ],
                  "shadowBlur":12,
                  "shadowColor":[
                     0,
                     0,
                     0
                  ]
               }
            ]
         ]
      }
   ]
]
ghost commented 9 years ago

@sapics yes, your JSON works just fine.

  1. Why does the of keys matter?
  2. How can we fix this?
sapics commented 9 years ago

That's good!

I guess as below.

  1. In initialization process, var item = new Shape(); item._set(hash); would be done.
  2. keys sort might depend on hash order.
  3. For example, if type is set later, shape.radius = 29.73214 is done without shape.type = "circle"
  4. Thus, the circle was not displayed.

To fix this, [Sorry, I have not checked yet following example works well or not, just a example :)]

if (keys.indexOf('type') > 0) {
  keys.unshift(keys.splice(keys.indexOf('type'), 1)[0]);
}
lehni commented 9 years ago

That's curious! Could you tell me what browser and version you are on? Thanks!

lehni commented 9 years ago

Also, what's the output of this on your system:

console.log(Object.keys({d: 1, c: 2, b: 3, a: 4 }));

http://sketch.paperjs.org/#S/q1bKS8xNVbJSCs5OLUnOUNJRSs5PAfGT8/OK83NS9XLy0zX8k7JSk0v0slMrizWqU6wUDHUUkq0UjHQUkqwUjHUUEq0UTBRqNTWtgbqTilITswvyM/NKipWsomNrAQ==

lehni commented 9 years ago

The sequence of the keys in the exported JSON is important due to the way the objects are deserialized automatically through getter / setter mappings. @winduptoy for some reason, your JSON has the keys in the wrong sequence, it looks like it is alphabetically sorted. This shouldn't happen, and I can't reproduce it here with your corrected JSON (exporting it again does not produce a wrong sequence). So we have to find the source of this wrong sorting.

sapics commented 9 years ago

@lehni Thanks for help! I guess that some of the program or database do not preserve hash sequesnce like ruby <= 1.8. If @winduptoy use such system, saving json by string with JSON.stringify(json) would be recommended method? (not saving by object)

lehni commented 9 years ago

Yes just convert it to a string and you should be fine. I don't think it makes sense to store it as objects anyway, since you probably don't need to have the data searchable.

ghost commented 8 years ago

This ended up being caused by running the output of Paper through JSON.parse and JSON.stringify. This issue does not happen if I respect the string output from Paper and just don't touch it. Thanks for your help guys.