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

can fabricJS read SVG files with Linear Gradient? #2390

Closed
orihadar opened this issue Aug 6, 2015 · 11 comments · Fixed by #2364
Closed

can fabricJS read SVG files with Linear Gradient? #2390

orihadar opened this issue Aug 6, 2015 · 11 comments · Fixed by #2364
Labels

Comments

@orihadar
Copy link

orihadar commented Aug 6, 2015

Here is my code for adding SVG file:

   fabric.loadSVGFromURL(stampURL, function (objects, options) {
var obj = fabric.util.groupSVGElements(objects, options);
obj.set({
    fill: stampColor,
    left: stampX,
    top: stampY,
    scaleY: stampScale,
    scaleX: stampScale,
    originX: 'center',
    originY: 'center',
    hasControls: false,
    hasBorders: true,
    selectable: false,
    perPixelTargetFind: true
});
Fcanvas.add(obj).renderAll();   });

the following specific file cause errors in the console (other files works perfect):

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 14.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 43363)  -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"            "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
 width="90px" height="90px" viewBox="0 0 90 90" enable-background="new 0 0 90 90" xml:space="preserve">
<g>
<linearGradient id="SVGID_1_" gradientUnits="userSpaceOnUse" x1="-351.3892" y1="-681.873" x2="-351.3892" y2="-655.4012" gradientTransform="matrix(1.4838 0 0 1.4838 558.5508 1038.5566)">
    <stop  offset="0" style="stop-color:#72C5EE"/>
    <stop  offset="0.2578" style="stop-color:#6EBEE6"/>
    <stop  offset="0.6475" style="stop-color:#61ACD2"/>
    <stop  offset="1" style="stop-color:#5396B9"/>
</linearGradient>
<path fill="url(#SVGID_1_)" stroke="#29AAE1" stroke-width="0.9549" stroke-linecap="round" stroke-linejoin="round" d="
    M42.422,31.788h-0.889c1.879-1.359,3.111-3.555,3.111-6.051c0-4.135-3.348-7.485-7.48-7.485c-4.135,0-7.485,3.351-7.485,7.485
    c0,2.496,1.233,4.691,3.112,6.051h-0.893c-2.418,0-4.381,2.157-4.381,4.817v29.855c0,0.373,4.738,2.292,9.417,2.292
    c4.733,0,9.757-1.21,9.757-1.21c0.07-0.346,0.111-0.709,0.111-1.082V36.605C46.803,33.944,44.843,31.788,42.422,31.788z"/>

    <linearGradient id="SVGID_2_" gradientUnits="userSpaceOnUse" x1="-335.3667" y1="-684.248" x2="-335.3667" y2="-654.8643" gradientTransform="matrix(1.4838 0 0 1.4838 558.5508 1038.5566)">
    <stop  offset="0" style="stop-color:#F05856"/>
    <stop  offset="0.3137" style="stop-color:#F0544E"/>
    <stop  offset="0.7879" style="stop-color:#EF483A"/>
    <stop  offset="1" style="stop-color:#EE422E"/>
</linearGradient>
<path fill="url(#SVGID_2_)" stroke="#EE422E" stroke-width="0.9549" stroke-linecap="round" stroke-linejoin="round" d="
    M65.733,34.999h-1.101c1.662-1.169,2.753-3.092,2.753-5.276c0-3.564-2.888-6.453-6.452-6.453s-6.455,2.889-6.455,6.453
    c0,2.185,1.093,4.107,2.754,5.276h-1.098c-2.21,0-3.997,2.007-3.997,4.481V65.42c0,0,4.332,1.449,9.723,1.449
    c4.183,0,7.87-2.173,7.87-2.173V39.48C69.73,37.006,67.942,34.999,65.733,34.999z"/>

    <linearGradient id="SVGID_3_" gradientUnits="userSpaceOnUse" x1="-343.6499" y1="-672.3726" x2="-343.6499" y2="-656.6719" gradientTransform="matrix(1.4838 0 0 1.4838 558.5508 1038.5566)">
    <stop  offset="0" style="stop-color:#B3D234"/>
    <stop  offset="0.2935" style="stop-color:#ABCB36"/>
    <stop  offset="0.7372" style="stop-color:#97B83A"/>
    <stop  offset="1" style="stop-color:#87AA3E"/>
</linearGradient>
<path fill="url(#SVGID_3_)" stroke="#87AA3E" stroke-width="0.9549" stroke-linecap="round" stroke-linejoin="round" d="
    M53.5,45.788h-1.957c1.786-1.083,2.991-3.029,2.991-5.271c0-3.411-2.769-6.18-6.183-6.18s-6.182,2.769-6.182,6.182
    c0,2.24,1.205,4.187,2.99,5.27l-1.371,0.002c-2.236,0-4.044,1.81-4.044,4.042v19.027c0,0,3.899,1.621,9.291,1.621
    c5.067,0,8.507-1.131,8.507-1.131V49.831C57.543,47.6,55.735,45.788,53.5,45.788z"/>

    <linearGradient id="SVGID_4_" gradientUnits="userSpaceOnUse" x1="-357.6011" y1="-672.7729" x2="-357.6011" y2="-652.2373" gradientTransform="matrix(1.4838 0 0 1.4838 558.5508 1038.5566)">
    <stop  offset="0" style="stop-color:#FFCC05"/>
    <stop  offset="0.2578" style="stop-color:#FEC408"/>
    <stop  offset="0.6475" style="stop-color:#FBB012"/>
    <stop  offset="1" style="stop-color:#F7971D"/>
</linearGradient>
<path fill="url(#SVGID_4_)" stroke="#FAAF3B" stroke-width="0.9549" stroke-linecap="round" stroke-linejoin="round" d="
    M31.272,50.715c1.459-1.042,2.417-2.739,2.417-4.67c0-3.176-2.576-5.749-5.748-5.749s-5.744,2.573-5.744,5.749
    c0,1.931,0.959,3.628,2.418,4.67c-2.238,0.22-3.992,2.044-3.992,4.287v14.213c0,0,3.713,1.552,7.806,1.552
    c3.378,0,6.835-1.552,6.835-1.552V55.002C35.264,52.759,33.51,50.935,31.272,50.715z"/>

This file cause the following errors:

fabric1_5dev.js:4264 TypeError: (this.getObjects(...)[0].get(...) || "").toLowerCase is not a function
at klass.fabric.PathGroup.fabric.util.createClass.isSameColor (..../js/fabric1_5dev.js:17008:68)
at klass.fabric.PathGroup.fabric.util.createClass._set (..../js/fabric1_5dev.js:16928:44)
at klass._set (..../js/fabric1_5dev.js:3499:52)
at klass.fabric.Object.fabric.util.createClass._setObject (..../js/fabric1_5dev.js:12368:14)
at klass.fabric.Object.fabric.util.createClass.set (..../js/fabric1_5dev.js:12381:14)
at ..../js/FCanvasFunc.js:143:13
at ..../js/fabric1_5dev.js:5202:11
at null.callback (..../js/fabric1_5dev.js:4832:11)
at fabric.ElementsParser.checkIfDone (..../js/fabric1_5dev.js:5373:10)
at ..../js/fabric1_5dev.js:5351:11

I belive the problem is with the LinearGradient.

Any solution?

@asturur
Copy link
Member

asturur commented Aug 6, 2015

image

Your svg gets loaded fine in kitchensink. ( i added final ) that where missing.

what version of fabric are you using?

@orihadar
Copy link
Author

orihadar commented Aug 7, 2015

I use 1.5.0
regarding the endings yes I just saw that :

were missing.
I just now tested and saw that it is loading in kitchensink. This is encouraging.
Still I have a problem that I couldn't trace the loading code being used in kitchensink, to compare it with mine.
any idea what can be wrong with my code?

@asturur
Copy link
Member

asturur commented Aug 7, 2015

can you provide stampurl?

@orihadar
Copy link
Author

orihadar commented Aug 8, 2015

what is a stampurl?

@asturur
Copy link
Member

asturur commented Aug 8, 2015

`fabric.loadSVGFromURL(stampURL, function (objects, options) {``

the url where you are loading the svg.

@orihadar
Copy link
Author

orihadar commented Aug 8, 2015

you probably meant sampleURL.
Ok!! Found it.
FabricJS fail if you load SVG which has color definitions (like gradient linear, don't know which else) and still try to set a fill color.
FabricJS fail (according to the error messages) in function: isSameColor

Do you know were can I find the code for this function? it is not in the fabric js file

@asturur
Copy link
Member

asturur commented Aug 8, 2015

you wrote stampUrl in your first post. i just copied it.
The function isSameColor is in the path_group.class.js
The function fails because the fill definition is not a string, so toLowerCase is not a method of that object.
The problem is that is completely wrong to try to set the color of a svg from the pathgroup.
it will not have effects most of the time.
When you set fill to pathgroup, the set method check if all object filling is same and then if it is, it change colors for all the shapes.
But if the fill is a gradient a bug is triggered.

This behaviour should be eliminated or at least duplicated for stroke and checked for fill.toLive() so it can guard against patterns and gradients.

@asturur
Copy link
Member

asturur commented Aug 8, 2015

changing isSameColor like this fix the issue:

fabric.PathGroup.prototype.isSameColor = function() {
  var firstPathFill = this.getObjects()[0].get('fill') || '';
      if (typeof firstPathFill !== 'string') {
        return false;
      }
      firstPathFill = firstPathFill.toLowerCase();
      return this.getObjects().every(function(path) {
        var pathFill = path.get('fill') || '';
        return typeof pathFill === 'string' && (pathFill).toLowerCase() === firstPathFill;
       });
     };

@orihadar
Copy link
Author

orihadar commented Aug 8, 2015

First of all your fix, fixes it perfectly.
second even if I changed the color to valid: "#266DB8" the function still crash without your fix.
anyhow thank you very much.

@asturur
Copy link
Member

asturur commented Aug 8, 2015

The problem is that in this particular SVG sometimes the fill is a gradient.
And gradient.toLowerCase() does not exist and make the function crash.

@orihadar
Copy link
Author

I don’t know who to turn to, I tried the google group and Stack overflow but got no response. therefore I try on this channel although I know it is not the common way, hopefully someone will see my question.

I am straggling to use the fabricjs on a hand held device.

The demo of touch event is working on tablets with touch events and is perfect for me but for some reason I cann’t get it to work.

I assumed my library does not include the touch support so in http://fabricjs.com/build/ I created another build which includes all options. This didn’t work. I tried using the build which is used in the demo, taken from: http://fabricjs.com/lib/fabric_with_gestures.js but no success too.

I will really appreciate any assistance.

I have a jsfiddle http://jsfiddle.net/orihadar/F6UU4/48/. And here is my code:

<!DOCTYPE html>
<meta charset="utf-8" />

<meta name="viewport" content="initial-scale=1, width=device-width, user-scalable=true" />

<script src="js/jquery-1.9.1.min.js"></script>

<script type="text/javascript" src="js/fabric_with_gestures.js"></script>

<script type="text/javascript" >





    $(document).ready



    (

        function () {



            var canvas = new fabric.Canvas('c');





            // Do some initializing stuff

            fabric.Object.prototype.set({

                transparentCorners: false,

                cornerColor: 'rgba(102,153,255,0.5)',

                cornerSize: 12,

                padding: 5

            });



            alert('fabric.isTouchSupported=' + fabric.isTouchSupported);

            var info = document.getElementById('info');

            canvas.on({

                'touch:gesture': function () {

                    var text = document.createTextNode(' Gesture ');

                    info.insertBefore(text, info.firstChild);

                },

                'touch:drag': function () {

                    var text = document.createTextNode(' Dragging ');

                    info.insertBefore(text, info.firstChild);

                },

                'touch:orientation': function () {

                    var text = document.createTextNode(' Orientation ');

                    info.insertBefore(text, info.firstChild);

                },

                'touch:shake': function () {

                    var text = document.createTextNode(' Shaking ');

                    info.insertBefore(text, info.firstChild);

                },

                'touch:longpress': function () {

                    var text = document.createTextNode(' Longpress ');

                    info.insertBefore(text, info.firstChild);

                }

            });





            fabric.Image.fromURL('http://fabricjs.com/assets/pug_small.jpg', function (img) {

                img.scale(0.5).set({

                    left: 150,

                    top: 150,

                    angle: -15

                });

                canvas.add(img);

            });



            canvas.add(new fabric.Rect({

                left: 50,

                top: 50,

                fill: '#269926',

                width: 100,

                height: 100,

                originX: 'left',

                originY: 'top',

                hasControls: true,

                hasBorders: true,

                selectable: true

            }));



            var obj = new fabric.Rect({

                left: 20,

                top: 20,

                fill: '#555555',

                width: 100,

                height: 100,

                originX: 'left',

                originY: 'top',

                hasControls: true,

                hasBorders: true,

                selectable: true

            });

            canvas.add(obj).renderAll();

            canvas.setActiveObject(obj)

            //canvas.sendToBack(obj)

        }



    );

</script>

<title></title>

<style>

    canvas {

border: 1px solid #999;

}

</style>
<canvas id="c" width="200" height="200" style='z-index:-1'></canvas>

<p id='info' style='background: #eef; width: 583px; padding: 10px; overflow: scroll; height: 80px'></p>

Best regards

Ori hadar

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

Successfully merging a pull request may close this issue.

2 participants