Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SVG Image cropped with fabric.Image.fromURL #5512

Closed
jonathan-roy opened this issue Jan 31, 2019 · 44 comments · Fixed by #5983
Closed

SVG Image cropped with fabric.Image.fromURL #5512

jonathan-roy opened this issue Jan 31, 2019 · 44 comments · Fixed by #5983

Comments

@jonathan-roy
Copy link

Version

2.4.6

Test Case

https://jsfiddle.net/kbcn4mpd/

Information about environment

Tested on Chrome 71.

Steps to reproduce

See fiddle.
I try to add an image to the canvas, using fabric.Image.fromURL() or new fabric.Image(). This image is a SVG file but I don't want to be able to manipulate objects inside this SVG, I just need to manipulate this SVG as a whole image.

Expected Behavior

The canvas should show the entire image (french flag).

Actual Behavior

The image appears, but is cropped: we can only see the upper left corner. I you remove the canvas' height attribute, then it appears correctly but then I am not able to correctly size the canvas.

@jonathan-roy jonathan-roy changed the title Image cropped with fabric.Image.fromURL SVG Image cropped with fabric.Image.fromURL Jan 31, 2019
@RoeyMaor
Copy link

RoeyMaor commented Feb 2, 2019

In fact, this exact cropping issue is relevant starting from 2.4.0 which introduced the breaking change.
My solution was to downgrade to 2.3.6 in the meantime. It appears to affect a large group of SVGs. For example, almost every svg from here: https://github.com/twitter/twemoji

@ikudosi
Copy link

ikudosi commented Feb 8, 2019

@RoeyMaor Thank you for the advise of downgrading to 2.3.6. I was having issues loading SVGs there were converted from .ai files. After downgrading I am no longer having issues and I can finally move on with my life!

@asturur
Copy link
Member

asturur commented Feb 10, 2019

@RoeyMaor in your opinion which is the commit from 2.3.6 to 2.4.0 that introduced the bug?

@asturur asturur added the bug label Feb 10, 2019
@asturur
Copy link
Member

asturur commented Feb 10, 2019

https://jsfiddle.net/6gbq7kfv/ with 2.3.6 behaves same to me.

@RoeyMaor
Copy link

RoeyMaor commented Feb 12, 2019

@asturur This is weird, when I use versions bigger than 2.3.6 many SVGs are messed up like this:
capture
and when using 2.3.6 they are fine:
capture2
I am using the latest chrome. perhaps this is even not the same bug, I assumed it is.

I narrowed the possibilities for the culprit commit to one of the following:
ffe01ab
513233b
2a476e4

@0ro
Copy link

0ro commented Feb 22, 2019

@RoeyMaor If you add width and height attributes to svg then there will be no cropped
https://jsfiddle.net/DenBogdanov/0Luqkm2g/

@0ro
Copy link

0ro commented Feb 22, 2019

What behavior is expected without the SVG object size set?

@RoeyMaor
Copy link

RoeyMaor commented Feb 23, 2019

@0ro Your example uses 2.3.6, so it is not a counter example, Iv'e said that since 2.4.0 the bug was introduced. If adding the width and height attributes to the svg tag itself is the solution as you said, then this in itself is another bug, as the proportions for correct display should be inferred from the viewbox in case the width and the height aren't specified in the svg tag itself. Many svgs do not use these attributes

@0ro
Copy link

0ro commented Feb 27, 2019

The latest version in which the test case in issue runs correctly is 1.7.22
https://jsfiddle.net/DenBogdanov/qr67an39/
Since version 2.0.0, svg images are cropped
https://jsfiddle.net/DenBogdanov/qr67an39/1/

@asturur
Copy link
Member

asturur commented Mar 2, 2019

image

so this is a bug ^^^ and i think it can be fixed.

@asturur
Copy link
Member

asturur commented Mar 2, 2019

image

this way seems working, i wonder how to detect this beahviour by code. i have to apply to the clipPath the transformation of parent groups.

@asturur
Copy link
Member

asturur commented Mar 2, 2019

to solve this properly we need an overhauled parser.
Or we need to note down the partial transformation of an element when the clipPath is declared.
This is a note for me as soon as i have a couple of hours to dedicate to this fix.

Maybe is better to invest them in a new svg parser that maints groups

@RoeyMaor
Copy link

@asturur, If this is caused by not applying transformations to clipPath, then as I said the bug was introduced by one of these commits: (before them it did not exist, tested with the same svg as you showed here):
ffe01ab
513233b
2a476e4

@tiptronic
Copy link

Will there be a fix for this? (or a new svg parser?? 😉 )

It works fine in Fabric 2.7.0 using Safari on the Mac, but not in Chrome (if that is important)

@tiptronic
Copy link

tiptronic commented Apr 23, 2019

Sourcefile is:

https://github.com/twitter/twemoji/blob/gh-pages/svg/1f171.svg

Here's what I get on Safari 12.0.1/Mac Fabric 2.7.0:
image

Same code on Chrome 73.0.3683.75/Mac Fabric 2.7.0
image

Please also note, that the second layer ('B') is not showing

If I let Fabric group the elements it looks like this:
image

@asturur
Copy link
Member

asturur commented Apr 27, 2019

svg parser is one of the funny things for me, and one of the things i would like to work on.
Didn't have much time march and april for a series of reasons.
Fabric is still actively developed used and improved, but time is few.

@tiptronic
Copy link

Sounds familiar 😊
Anyway - Fabric is a really cool thing (even if there are some things like the above). ❤️

@asturur
Copy link
Member

asturur commented Apr 27, 2019

Yeah consider that parsing an svg, with all the svg capabilities is a non trivial task. The more functionalities we enable from SVG the more weird combination arrives.
I'm very happy with the current state of svg parsing.

@tiptronic
Copy link

tiptronic commented Apr 27, 2019

Me too! And - interestingly - the above results show fine in Safari, but wrong in Chrome; so it seems that (besides parsing svg) more things are involved

@asturur
Copy link
Member

asturur commented Apr 27, 2019

for me is broken in the latest safari too
image

@TeslaFreak
Copy link

Has there been any progress on this? Looks like its been about 8 months since this was reported and seems like a pretty major issue thats still going on

@asturur
Copy link
Member

asturur commented Aug 19, 2019

if i remember correctly this requires a full new svg parser logic.

@satendra02
Copy link

Getting the same issue with version 2.4.6 when trying to load SVG using fabric.Image.fromURL

Is there any workaround?

Here is the fiddle
https://jsfiddle.net/satendra02nov/3p0uvsjr/6/

@TeslaFreak
Copy link

TeslaFreak commented Sep 20, 2019

@satendra you can use fabric.loadsvgfromurl but that will give you a path object instead of an image. If you dont need it to be an image object, then this will at least load the full picture on canvas for you. Unfortunately all we can do right now.

@TeslaFreak
Copy link

I dont know why one parser works and the other doesnt, but would it be possible to use the loadsvgfromurl to get the path object and then convert it to an image after that? Or is that basically what image.fromurl is doing already? I havent looked at the parser code myself to see

@asturur
Copy link
Member

asturur commented Sep 24, 2019

image.fromUrl shoud draw the svg as an image, with no details loss on zoom and 0 compatibility issues.

The other creates a group of objects.

If you do not need to let someone else ungroup the group and manipulate every single path on the canvas, loading it as an image is a solution

@asturur
Copy link
Member

asturur commented Nov 18, 2019

i think this has been partially fixed.
Anyone has the SVG files that have been used in the screenshot in the thread?

@tiptronic
Copy link

@asturur
Copy link
Member

asturur commented Nov 18, 2019

yes this one is one of them. also the jester i need.

@asturur asturur added this to the 3.5.2 milestone Nov 18, 2019
@tiptronic
Copy link

Sorry - I was off for a couple of days...
Here's the other one:
https://github.com/twitter/twemoji/blob/gh-pages/svg/1f0cf.svg

@asturur
Copy link
Member

asturur commented Nov 22, 2019

i think this problem has been solved in current master!

@ikudosi
Copy link

ikudosi commented Dec 20, 2019

Still having issues with version latest version 3.5.1. The SVG below renders properly on 2.3.6 which is what I've been using for quite some time. The difference between the two photos are on the right side of the image.

Test SVG Logo
Rendered fabric on 2.3.6
Rendered fabric on 3.5.1

@asturur
Copy link
Member

asturur commented Dec 21, 2019

Not sure what is wrong because the images you provide are really small and i can't understand if something is rendered bad.

this is how latest fabric renders the object:
image

this is how the browser renders it:
image

The images looks very similar to me.

@ikudosi
Copy link

ikudosi commented Dec 22, 2019

Hmm interesting - this is what I did even for a simple test and still came to same conclusion:

  1. Go to http://fabricjs.com/kitchensink.
  2. Click on "Clear Canvas"
  3. Go to "Load SVG"
  4. Copy & Paste entireSVG content
  5. Click on "Load as Group"

This is what I got as a result:
maui_fabric 3 5 0_site_kitchensink

@asturur
Copy link
Member

asturur commented Dec 22, 2019

the website could not include last commits

@simoroma
Copy link

Any news on this? Still having similar issues.

@ikudosi
Copy link

ikudosi commented Jan 14, 2021

Any news on this? Still having similar issues.

Try version 2.3.6. I had issues as well but tried someone's recommendation above and problem got resolved. I haven't tried any newer version since then as if it ain't broke... don't fix.

@simoroma
Copy link

Try version 2.3.6. I had issues as well but tried someone's recommendation above and problem got resolved. I haven't tried any newer version since then as if it ain't broke... don't fix.

Thanks.

I am using 4.3 "with gestures". I am actually using Twemojis. Adding width and height to the svg actually works. I am going to modify all Twemojis I use with a script then.

@asturur
Copy link
Member

asturur commented Jan 14, 2021

what are twemojis? are they free to use set of emojis?
I had the same problem with notoemoji and i ended up adding a width and height using SVGO

@simoroma
Copy link

Yes, it is a free set of emojis. Someone was mentioning it a the beginning of this thread.

It appears to affect a large group of SVGs. For example, almost every svg from here: https://github.com/twitter/twemoji

@Saqib92
Copy link

Saqib92 commented Sep 14, 2023

Sourcefile is:

https://github.com/twitter/twemoji/blob/gh-pages/svg/1f171.svg

Here's what I get on Safari 12.0.1/Mac Fabric 2.7.0: image

Same code on Chrome 73.0.3683.75/Mac Fabric 2.7.0 image

Please also note, that the second layer ('B') is not showing

If I let Fabric group the elements it looks like this: image

fabricjs v5.2.1 (custom build from website for Eraser tool).

Facing same issue but in Latest Safari MAC and IPhone.

SVG are cropped when load from JSON.

@asturur
Copy link
Member

asturur commented Sep 20, 2023

i went on fabricjs.com/kitchensink where there is still fabricjs 5.2.1

i loaded that svg and json saved and restored it without issue

{
  "version": "5.2.1",
  "objects": [
    {
      "type": "group",
      "version": "5.2.1",
      "left": 60.25,
      "top": 54.25,
      "width": 47.5,
      "height": 47.5,
      "scaleX": 3.25,
      "scaleY": 3.25,
      "objects": [
        {
          "type": "path",
          "version": "5.2.1",
          "left": -23.13,
          "top": -23.13,
          "width": 36,
          "height": 36,
          "fill": "rgba(221,46,68,1)",
          "stroke": "",
          "scaleX": 1.25,
          "scaleY": 1.25,
          "flipY": true,
          "clipPath": {
            "type": "path",
            "version": "5.2.1",
            "originX": "left",
            "originY": "top",
            "left": -19.5,
            "top": -19.5,
            "width": 38,
            "height": 38,
            "fill": "rgb(0,0,0)",
            "stroke": null,
            "strokeWidth": 1,
            "strokeDashArray": null,
            "strokeLineCap": "butt",
            "strokeDashOffset": 0,
            "strokeLineJoin": "miter",
            "strokeUniform": false,
            "strokeMiterLimit": 4,
            "scaleX": 1,
            "scaleY": 1,
            "angle": 0,
            "flipX": false,
            "flipY": false,
            "opacity": 1,
            "shadow": null,
            "visible": true,
            "backgroundColor": "",
            "paintFirst": "fill",
            "globalCompositeOperation": "source-over",
            "skewX": 0,
            "skewY": 0,
            "path": [
              [
                "M",
                0,
                38
              ],
              [
                "L",
                38,
                38
              ],
              [
                "L",
                38,
                0
              ],
              [
                "L",
                0,
                0
              ],
              [
                "L",
                0,
                38
              ],
              [
                "Z"
              ]
            ],
            "inverted": false,
            "absolutePositioned": false
          },
          "path": [
            [
              "M",
              0,
              0
            ],
            [
              "C",
              0,
              -2.209,
              -1.791,
              -4,
              -4,
              -4
            ],
            [
              "L",
              -32,
              -4
            ],
            [
              "C",
              -34.209,
              -4,
              -36,
              -2.209,
              -36,
              0
            ],
            [
              "L",
              -36,
              28
            ],
            [
              "C",
              -36,
              30.209,
              -34.209,
              32,
              -32,
              32
            ],
            [
              "L",
              -4,
              32
            ],
            [
              "C",
              -1.791,
              32,
              0,
              30.209,
              0,
              28
            ],
            [
              "L",
              0,
              0
            ],
            [
              "Z"
            ]
          ]
        },
        {
          "type": "path",
          "version": "5.2.1",
          "left": -10,
          "top": -14.47,
          "width": 16.06,
          "height": 22.08,
          "fill": "rgba(255,255,255,1)",
          "stroke": "",
          "scaleX": 1.25,
          "scaleY": 1.25,
          "flipY": true,
          "clipPath": {
            "type": "path",
            "version": "5.2.1",
            "originX": "left",
            "originY": "top",
            "left": -20.03,
            "top": -19.54,
            "width": 38,
            "height": 38,
            "fill": "rgb(0,0,0)",
            "stroke": null,
            "strokeWidth": 1,
            "strokeDashArray": null,
            "strokeLineCap": "butt",
            "strokeDashOffset": 0,
            "strokeLineJoin": "miter",
            "strokeUniform": false,
            "strokeMiterLimit": 4,
            "scaleX": 1,
            "scaleY": 1,
            "angle": 0,
            "flipX": false,
            "flipY": false,
            "opacity": 1,
            "shadow": null,
            "visible": true,
            "backgroundColor": "",
            "paintFirst": "fill",
            "globalCompositeOperation": "source-over",
            "skewX": 0,
            "skewY": 0,
            "path": [
              [
                "M",
                0,
                38
              ],
              [
                "L",
                38,
                38
              ],
              [
                "L",
                38,
                0
              ],
              [
                "L",
                0,
                0
              ],
              [
                "L",
                0,
                38
              ],
              [
                "Z"
              ]
            ],
            "inverted": false,
            "absolutePositioned": false
          },
          "path": [
            [
              "M",
              0,
              0
            ],
            [
              "L",
              3.659,
              0
            ],
            [
              "C",
              5.333,
              0,
              6.574,
              0.961,
              6.574,
              2.697
            ],
            [
              "C",
              6.574,
              4.155,
              5.457,
              5.147,
              3.287,
              5.147
            ],
            [
              "L",
              0,
              5.147
            ],
            [
              "L",
              0,
              0
            ],
            [
              "Z"
            ],
            [
              "M",
              0,
              9.24
            ],
            [
              "L",
              2.419,
              9.24
            ],
            [
              "C",
              3.9379999999999997,
              9.24,
              4.93,
              10.139,
              4.93,
              11.689
            ],
            [
              "C",
              4.93,
              13.146,
              3.7829999999999995,
              13.891,
              2.4189999999999996,
              13.891
            ],
            [
              "L",
              0,
              13.891
            ],
            [
              "L",
              0,
              9.24
            ],
            [
              "Z"
            ],
            [
              "M",
              -4.65,
              15.658000000000001
            ],
            [
              "C",
              -4.65,
              17.146,
              -3.6270000000000007,
              17.983,
              -2.2010000000000005,
              17.983
            ],
            [
              "L",
              3.752,
              17.983
            ],
            [
              "C",
              6.976,
              17.983,
              9.582,
              15.813,
              9.582,
              12.526
            ],
            [
              "C",
              9.582,
              10.356,
              8.681000000000001,
              8.898,
              6.697000000000001,
              7.968999999999999
            ],
            [
              "L",
              6.697000000000001,
              7.906
            ],
            [
              "C",
              9.333000000000002,
              7.534,
              11.41,
              5.333,
              11.41,
              2.636
            ],
            [
              "C",
              11.41,
              -1.7359999999999998,
              8.496,
              -4.093,
              4.216,
              -4.093
            ],
            [
              "L",
              -2.17,
              -4.093
            ],
            [
              "C",
              -3.597,
              -4.093,
              -4.65,
              -3.193,
              -4.65,
              -1.7359999999999998
            ],
            [
              "L",
              -4.65,
              15.657999999999998
            ],
            [
              "z"
            ]
          ]
        }
      ]
    }
  ]
}

@Saqib92
Copy link

Saqib92 commented Sep 20, 2023

i went on fabricjs.com/kitchensink where there is still fabricjs 5.2.1

i loaded that svg and json saved and restored it without issue

{
  "version": "5.2.1",
  "objects": [
    {
      "type": "group",
      "version": "5.2.1",
      "left": 60.25,
      "top": 54.25,
      "width": 47.5,
      "height": 47.5,
      "scaleX": 3.25,
      "scaleY": 3.25,
      "objects": [
        {
          "type": "path",
          "version": "5.2.1",
          "left": -23.13,
          "top": -23.13,
          "width": 36,
          "height": 36,
          "fill": "rgba(221,46,68,1)",
          "stroke": "",
          "scaleX": 1.25,
          "scaleY": 1.25,
          "flipY": true,
          "clipPath": {
            "type": "path",
            "version": "5.2.1",
            "originX": "left",
            "originY": "top",
            "left": -19.5,
            "top": -19.5,
            "width": 38,
            "height": 38,
            "fill": "rgb(0,0,0)",
            "stroke": null,
            "strokeWidth": 1,
            "strokeDashArray": null,
            "strokeLineCap": "butt",
            "strokeDashOffset": 0,
            "strokeLineJoin": "miter",
            "strokeUniform": false,
            "strokeMiterLimit": 4,
            "scaleX": 1,
            "scaleY": 1,
            "angle": 0,
            "flipX": false,
            "flipY": false,
            "opacity": 1,
            "shadow": null,
            "visible": true,
            "backgroundColor": "",
            "paintFirst": "fill",
            "globalCompositeOperation": "source-over",
            "skewX": 0,
            "skewY": 0,
            "path": [
              [
                "M",
                0,
                38
              ],
              [
                "L",
                38,
                38
              ],
              [
                "L",
                38,
                0
              ],
              [
                "L",
                0,
                0
              ],
              [
                "L",
                0,
                38
              ],
              [
                "Z"
              ]
            ],
            "inverted": false,
            "absolutePositioned": false
          },
          "path": [
            [
              "M",
              0,
              0
            ],
            [
              "C",
              0,
              -2.209,
              -1.791,
              -4,
              -4,
              -4
            ],
            [
              "L",
              -32,
              -4
            ],
            [
              "C",
              -34.209,
              -4,
              -36,
              -2.209,
              -36,
              0
            ],
            [
              "L",
              -36,
              28
            ],
            [
              "C",
              -36,
              30.209,
              -34.209,
              32,
              -32,
              32
            ],
            [
              "L",
              -4,
              32
            ],
            [
              "C",
              -1.791,
              32,
              0,
              30.209,
              0,
              28
            ],
            [
              "L",
              0,
              0
            ],
            [
              "Z"
            ]
          ]
        },
        {
          "type": "path",
          "version": "5.2.1",
          "left": -10,
          "top": -14.47,
          "width": 16.06,
          "height": 22.08,
          "fill": "rgba(255,255,255,1)",
          "stroke": "",
          "scaleX": 1.25,
          "scaleY": 1.25,
          "flipY": true,
          "clipPath": {
            "type": "path",
            "version": "5.2.1",
            "originX": "left",
            "originY": "top",
            "left": -20.03,
            "top": -19.54,
            "width": 38,
            "height": 38,
            "fill": "rgb(0,0,0)",
            "stroke": null,
            "strokeWidth": 1,
            "strokeDashArray": null,
            "strokeLineCap": "butt",
            "strokeDashOffset": 0,
            "strokeLineJoin": "miter",
            "strokeUniform": false,
            "strokeMiterLimit": 4,
            "scaleX": 1,
            "scaleY": 1,
            "angle": 0,
            "flipX": false,
            "flipY": false,
            "opacity": 1,
            "shadow": null,
            "visible": true,
            "backgroundColor": "",
            "paintFirst": "fill",
            "globalCompositeOperation": "source-over",
            "skewX": 0,
            "skewY": 0,
            "path": [
              [
                "M",
                0,
                38
              ],
              [
                "L",
                38,
                38
              ],
              [
                "L",
                38,
                0
              ],
              [
                "L",
                0,
                0
              ],
              [
                "L",
                0,
                38
              ],
              [
                "Z"
              ]
            ],
            "inverted": false,
            "absolutePositioned": false
          },
          "path": [
            [
              "M",
              0,
              0
            ],
            [
              "L",
              3.659,
              0
            ],
            [
              "C",
              5.333,
              0,
              6.574,
              0.961,
              6.574,
              2.697
            ],
            [
              "C",
              6.574,
              4.155,
              5.457,
              5.147,
              3.287,
              5.147
            ],
            [
              "L",
              0,
              5.147
            ],
            [
              "L",
              0,
              0
            ],
            [
              "Z"
            ],
            [
              "M",
              0,
              9.24
            ],
            [
              "L",
              2.419,
              9.24
            ],
            [
              "C",
              3.9379999999999997,
              9.24,
              4.93,
              10.139,
              4.93,
              11.689
            ],
            [
              "C",
              4.93,
              13.146,
              3.7829999999999995,
              13.891,
              2.4189999999999996,
              13.891
            ],
            [
              "L",
              0,
              13.891
            ],
            [
              "L",
              0,
              9.24
            ],
            [
              "Z"
            ],
            [
              "M",
              -4.65,
              15.658000000000001
            ],
            [
              "C",
              -4.65,
              17.146,
              -3.6270000000000007,
              17.983,
              -2.2010000000000005,
              17.983
            ],
            [
              "L",
              3.752,
              17.983
            ],
            [
              "C",
              6.976,
              17.983,
              9.582,
              15.813,
              9.582,
              12.526
            ],
            [
              "C",
              9.582,
              10.356,
              8.681000000000001,
              8.898,
              6.697000000000001,
              7.968999999999999
            ],
            [
              "L",
              6.697000000000001,
              7.906
            ],
            [
              "C",
              9.333000000000002,
              7.534,
              11.41,
              5.333,
              11.41,
              2.636
            ],
            [
              "C",
              11.41,
              -1.7359999999999998,
              8.496,
              -4.093,
              4.216,
              -4.093
            ],
            [
              "L",
              -2.17,
              -4.093
            ],
            [
              "C",
              -3.597,
              -4.093,
              -4.65,
              -3.193,
              -4.65,
              -1.7359999999999998
            ],
            [
              "L",
              -4.65,
              15.657999999999998
            ],
            [
              "z"
            ]
          ]
        }
      ]
    }
  ]
}

I made another Image from current image then it is working now:

let asImg = new Image();
asImg.src = imag.src; // new image element from old image src. and then save it as json and re load it is working. 
asImg.onload = ()=>{
  img = new fabric.Image(asImg, {
    top: e.layerY - 10 || y - 5,
    left: e.layerX - 10 || x - 5,
    hasControls:  true,
    erasable: false
  });
}

@alwalxed
Copy link

Hey folks, any updates?

{
    "fabric": "^5.3.0",
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.