0

This is an svg image loaded onto the canvas. As you can tell, it looks very much like a raster image. To give a little more context, the light blue box is 1000px by 400px.

Raster image

Notice also the image of the IText object looks like a raster image instead of a vector image.

Raster text

Anyone know what's happening here and how to fix it?

---update---

Sorry, this took so long to get out... I got side tracked, but as requested:

<html>
    <head>
        <title>
            Debug Me
        </title>
        
        <!--jQuery CDN-->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

        <!--Path to fabric.js-->
        <script type='text/javascript' src="./CreekWareJava/fabric.js-3.6.3/dist/fabric.js"></script>

        <!--bootstrap related-->
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.bundle.min.js" integrity="sha384-1CmrxMRARb6aLqgBO7yyAxTOQE2AKb9GfXnEo760AUcUmFx3ibVJJAzGytlQcNXd" crossorigin="anonymous"></script>
        <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>

    </head>

<body>
    <div class="container">
        <div class="row">
            <div class="col" id="canvas_container">
                <canvas id="canvas">
                    Canvas is not supported by this browser! Please upgrade your browser.
                </canvas>
            </div>
        </div>
    </div>

    <style>

#canvas_container
{
    display: flex !important;
    justify-content: center !important;
}
canvas
{
    position: absolute !important;
    height: 100% !important;
    width: 100% !important;

    top: 50% !important;
    left: 50% !important;
    transform: translate(-50%, -50%) !important;
}
.canvas-container
{
    width: 1000px !important;
    height: 400px !important;
    border: 5px solid green !important;
    position: relative !important;
}

    </style>

    <script>

window.onload = function()
{
    canvas = new fabric.Canvas('canvas');

    // – Raman Nikitsenka's proposal
    // it shouldn't hurt to have it in here...
    fabric.Object.prototype.objectCaching = false;

    //Adding some text
    addText("Some text");
    addImage("http://fabricjs.com/assets/1.svg");

}

function addText(text)
{
    var canH = canvas.getHeight() / 2;
    var canW = canvas.getWidth() / 2;
    var text = new fabric.IText(text, { left: canW, top: canH, fill: "Black", textAlign: 'center' });
    text.originX = 'center';
    text.originY = 'center';
    canvas.add(text);
    canvas.bringToFront(text);
    canvas.requestRenderAll();
}

function addImage(source)
{
    fabric.loadSVGFromURL(source ,function(objects,options) {

    var loadedObjects = fabric.util.groupSVGElements(objects, options);

        loadedObjects.set({
            width: 200,
            height: 200
        });

        canvas.add(loadedObjects);
        canvas.renderAll();

    });
}

    </script>

</body>
</html>

This is the simplified code. As you can tell when you load it, both the svg and the text will come out very blurry. When you resize the dragon or the text, you can tell that it is trying to render it but doesn't do so properly.

Some additional observations:

fabric.js takes the initial canvas element and creates 2 new canvases, then wraps them in a div with a class called .canvas-container. I have a wrapper div for that container with id #canvas_container.

-- Update again... --

I added the following code to the window.onload eventlistener directly after the new fabric object...

for (var i = 0; i < 4; i++)
{
    canvas.setHeight(document.getElementById('canvas').height);
    canvas.setWidth(document.getElementById('canvas').width);
    canvas.requestRenderAll();
    console.log(i, "fw", canvas.width, "fh", canvas.height, "cw", document.getElementById("canvas").width, "ch", document.getElementById("canvas").height, "fr", canvas.width / canvas.height, "cr", document.getElementById("canvas").width / document.getElementById("canvas").height);
}

My observations from this are that the more I increase the counter for the loop, the better the image quality and text quality. On the other hand however, it will make the resize boxes and bounding box much thinner and decrease the physical size of the objects. The console will output fabric's canvas's width and height, then the physical html canvas element's width and height, followed by the ratios of each respectively. Thoughts?

Shmack
  • 1,933
  • 2
  • 18
  • 23
  • Post your code. – Phix Jun 18 '20 at 22:36
  • @Phix, that's fair. Let me try to duplicate the issue, because there would be a lot of code to dig through. I think it has to do with the css resizing the canvas... but I will update you when I duplicate it. – Shmack Jun 18 '20 at 22:48
  • @Phix, as per your request. – Shmack Jun 19 '20 at 04:25
  • Has anyone replicated this with my posted code? – Shmack Jun 20 '20 at 02:08
  • Try to set `objectCaching` in `false` http://fabricjs.com/fabric-object-caching#:~:text=How%20does%20it%20works%3F,with%20a%20%60drawImage%60%20operation. – Oro Jun 20 '20 at 11:23
  • @RamanNikitsenka I just tried it. While I can tell there is an improvement, it is still not up to par on what I've had it look like in the past when using fabric. I will update my code to reflect the suggested change and comment your name in the code for others to look at. – Shmack Jun 20 '20 at 18:17
  • @Durga I hate to bother you, but you were so helpful the last time you chimed in. You wouldn't know anything about this issue or how to fix it, would you? – Shmack Jul 29 '20 at 00:36

1 Answers1

0

So the problem is that fabric.js checks the tag for a width and height to initialize the new fabric canvas to, and if you don't include it in the tag, it won't render the canvas properly. To fix it, you can use

canvas.setHeight(document.getElementById("your_canvas_id").style.height);
canvas.requestRenderAll();

and likewise for the width.

Fabric.js changes my canvas size to 300x150 after initialization is another resource for this question.

Shmack
  • 1,933
  • 2
  • 18
  • 23