Fabric.js object sizes - javascript

I have an issue with sizes of objects. Here is a simple example:
<!doctype html>
<html>
<head>
<script src="js/fabric-0.9.15.min.js"></script>
</head>
<body>
<canvas id="test" width="512" height="512" style="border: 1px solid black;"></canvas>
<div style="width: 512px; background: blue;"> </div>
<script>
var canvas = new fabric.Canvas('test');
var rect = new fabric.Rect({
left: 0,
top: 0,
fill: 'red',
width: 512,
height: 512
});
canvas.add(rect);
</script>
</body>
</html>
As you can see I have a canvas with sizes of 512px and I have a div with width of 512px for testing. Also I created rect object to draw with sizes of 512px.
See screenshot
Fabric draws rect with half sizes. Can you please tell me why or what I do in wrong way?

The Rectangle is actually 512, 512. The problem you are having is the origin of your object.
Which is the middle of the rectangle,thus showing only a quarter of your rectangle.
Try changing your top and left to 256, you will see the difference.

Related

Fabric.js - Why does this svg have such poor quality upon importing into my canvas?

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.
Notice also the image of the IText object looks like a raster image instead of a vector image.
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?
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.

jquery, resize a canvas without scaling

I was trying to put a canvas in a container. I wanted the canvas to have the same size as the container. To do this I used JQuery, however, this turned out to scale my canvas. This was not my intention, especially because I draw after resizing. Doing seemingly the same thing in good old fashion JavaScript gives me the expected result.
I personally did not expect the JQuery result and it took some time before I figured out the problem. Does anybody know why they opted for this implementation and why it gives a different result? I hope by sharing this I can save some people a lot of time!
Thanks for anybody willing to research this further of fix this!
Here is some example code:
<html>
<head>
<title>Canvas resizing</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<style type="text/css">
#container1{
background-color: green;
width: 100px;
height: 100px;
margin: 50px auto;
}
#container2{
background-color: red;
width: 100px;
height: 100px;
margin: 50px auto;
}
</style>
</head>
<body>
<div id="container1">
<canvas></canvas>
</div>
<div id="container2">
<canvas></canvas>
</div>
<script type="text/javascript">
function draw (canvas) {
var context=canvas.getContext("2d");
context.lineWidth = 5;
context.rect(25,25,50,50);
context.stroke();
}
$(document).ready(function () {
//javascript
var container = document.getElementById('container1');
var canvas = container.childNodes[1];
canvas.width = 100;
canvas.height = 100;
draw(canvas);
//jquery
var container = $('#container2');
var canvas = container.children()[0];
$(canvas).width(100);
$(canvas).height(100);
draw(canvas);
});
</script>
</body>
</html>
The jQuery width and height methods are shorthand aliases for setting the CSS width and height properties. Sizing a canvas using CSS causes the scaled, distorted look you're seeing. Your pure javascript version of the code is setting the width and height attributes of the canvas element. To achieve the same in jQuery you can use:
$(canvas).prop('width', 100)
$(canvas).prop('height', 100)
JSFiddle

Canvas element lines aren't straight?

I am trying to draw an element on a canvas but whenever I draw the canvas, the lines turn out faded and not bold. I don't understand why this happening with my code.. whenever I try it with code from W3schools it turns out fine. Here is my code and an image below.
<!DOCTYPE html>
<html>
<head>
<title>Talk Walk</title>
<style type="text/css">
#canvas {
position: absolute;
top: 0px;
left: 0px;
height: 500px;
width: 750px;
background-color: blue;
}
</style>
</head>
<body>
<canvas id="canvas"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0,0,150,75);
</script>
</body>
</html>
The problem here is that there's some aliasing going on when you're drawing the rectangles.
This is happening because the "edge" of the green rectangle isn't drawn exactly on a pixel. Normally, you wouldn't really see it, but since you're stretching out the canvas by using css to set it's width and height, you get this result:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0,0,150,75);
#canvas {
height: 500px;
width: 750px;
background-color: blue;
}
<canvas id="canvas"></canvas>
To fix that, use the width and height HTML attributes, instead of css:
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext("2d");
ctx.fillStyle = "green";
ctx.fillRect(0,0,150,75);
#canvas {
background-color: blue;
}
<canvas id="canvas" height="500" width="750"></canvas>
This properly scales the canvas, so the aliasing (while still there if you zoom in) doesn't scale up.

CSS div style, javascript canvas color change

I am having an issue trying to get these 3 divs to line up on the same horizontal pane.
I will also like to know if it is possible to have the color of my circle change based on a value of a variable. I would greatly appreciate an example function.
<html>
<body>
<style type="text/css">
.circle
{
width:115px;
height:115px;
border-radius:250px;
font-size:20px;
color:#fff;
line-height:115px;
text-align:center;
background:#000
}
</style>
<div id="container" style=" border: 2px coral solid; width:100%; height:120px;">
<div class="circle">Hello</div>
<div id="leadInfo" style="width:37%; height:115px; float:left; background-color:yellow;"> </div>
<div id="leadInfo2" style="width:37.5%; height:115px; float:right; background-color:blue;"> </div>
</div>
</body>
</html>
First you wrote
float: leftt;
Instead of
float: left;
Also, try adjusting one of the yellow circles to be less then 37.5%, it somehow goes over 100% in total and jumps down. So 37% will be enough.
<div id="container" style=" border: 3px coral solid; width:100%; height:auto;">
<div id="colorwheel" style="width:25%; float:left; border: 3px coral solid;">
<canvas id="circlecanvas" width="100" height="100"></canvas>
<script>
var canvas = document.getElementById("circlecanvas");
var context = canvas.getContext("2d");
context.arc(50, 50, 50, 0, Math.PI * 2, false);
context.fillStyle="red";
context.fill()
</script>
</div>
<div id="leadInfo" style="width:37.2%; height:108px; float:right; background-color:yellow;border:1px solid red;"> </div>
<div id="leadInfo" style="width:37.2%; height:108px; float:right; background-color:yellow;border:1px solid red;"> </div>
<div style="clear:both"></div>
</div>
And about changing the color of a circle on canvas...
No, you can't change anything you've drawn on the canvas (including your circle).
That's because canvas doesn't "remember" where it drew your circle. Your circle becomes an un-remembered group of pixels on the canvas.
Therefore, if you want to change anything on the canvas, you must erase the canvas and redraw your circle using the fillStyle in your variable.
// create a variable to hold your desired fill color
var myFillColor="gold";
// clear the canvas
context.clearRect(0,0,canvas.width,canvas.height);
// set the context.fillStyle to your variable
context.fillStyle=myFillColor;
// redraw your circle
context.beginPath();
context.arc(50, 50, 50, 0, Math.PI * 2, false);
context.fill();
Important note: context.arc is a path command and every group of path commands must be preceeded by context.beginPath. beginPath tells the browser you are finished drawing the previous path and are now drawing a new path. Failing to start new paths with beginPath will cause your next context.fill (or context.stroke) command to redraw all previous path commands.

How to change the height and width of canvas using css while using fabric

As the title says everything. I want to change the size of my HTML5 canvas. I am using fabricjs library to work with HTML5 canvas. However, fabricjs makes the size of the canvas smaller. Now I want to its size using css but it does not affect it. When I give other css rules to canvas then it does affect but not width and height.
jsfiddle
Here is my fabricjs code
var canvas = new fabric.Canvas('c');
var rect = new fabric.Rect({
left: 50,
top: 50,
fill: 'red',
width: 100,
height: 100
});
canvas.add(rect);
here is my html
<canvas id="c"></canvas>
and here is my CSS
#c {
width: 100%;
border: 1px solid green;
}
Found the answer. Below solution works for me
var canvas = new fabric.Canvas('c');
canvas.setHeight(500);
canvas.setWidth(800);
Second solution is
<canvas id="c" width="900" height="600"></canvas>

Categories