I'm trying to create a simple path object using Farbic.js. When the path is added to canvas, it does not appear to be positioned correctly. Here is my code:
HTML
<canvas id="c" height="300" width="300"></canvas>
JS
var canvas = new fabric.Canvas('c');
canvas.backgroundColor = '#f5f5f5';
var line = new fabric.Path('M 0 0 L 100 100',{
stroke: 'black',
fill: ''
});
canvas.add(line);
According to the data I'm passing in, the path should start at point 0,0 and draw a line to point 100, 100. However, my line is actually being placed at point 50,50, as you can see by the alert.
Why isn't the path starting at point 0,0?
Here's a fiddle: http://jsfiddle.net/flyingL123/h14th5pf/3/
You can specify the position properties of your path explicitly.
line.set({top: 0, left: 0});
Fabric.JS seems to include some sort of computed padding by default, based on the line length and canvas size. Try adjusting your canvas dimensions and line length and you'll see the top and left values update automatically.
Edit: It appears Fabric.JS may use the center of the canvas to calculate the X,Y positions for canvases. It may use a similar scheme for path origin points. See this related StackOverflow question:
Canvas coordinates in Fabric.js have offset
It seems to be part of how the library calculates positions automatically. Per the comments of the linked question, you can fix this with:
fabric.Object.prototype.originX = true;
fabric.Object.prototype.originY = true;
And you wont have to adjust the originX or originY properties on each path object.
Related
I adapted an open source game to fit for my fantasy book series, Eloik.
This game
I'd like to replace the blue arc for a png image (about same size).
I know I have to draw an image but how to??
Here's the portion of the code :`
// Shield - Boomlight
context.beginPath();
context.strokeStyle = '#0066cc';
context.lineWidth = 10;
context.arc( player.position.x, player.position.y, player.radius,
player.angle + 1.6, player.angle - 1.6, true );
context.stroke();`
I tried that following code but... The png image doesn't appears at the right spot and it's not interactive with the game as the arc...`
<html>
<body>
<img id="boom" width="176" height="134" src="http://eloik.com/wp/wp-
content/uploads/2017/05/BOOMLIGHT-jeu-bd.png" alt="">
*In the Javascript :
<script>
window.onload = function() {
var image = new Image();
image.src="http://eloik.com/wp/wp-content/uploads/2017/05/BOOMLIGHT-jeu-
bd.png";
context.beginPath();
context.drawImage(image, 10, 10);
}
</script>
</body>
</html> `
So now, what's wrong ?
Thanks ! :)
First, in order to use drawImage, we need to load it. You can do it like this:
/* core.js: line 57 */
// Create a handle for the image
var shieldImage;
/* core.js: line 133 */
// Create a new image
shieldImage = new Image();
// When it's loaded, execute animate
shieldImage.onload = animate;
// Set the src
shieldImage.src = "http://eloik.com/wp/wp-content/uploads/2017/05/BOOMLIGHT-jeu-bd.png";
This way, the animate function will only be called once the image has loaded. Then, in order to position your image and rotate it, you can do this:
/* core.js: line 420 */
// Set the origin of the canvas on the player position
context.translate(player.position.x, player.position.y);
// Rotate the canvas
context.rotate(player.angle + Math.PI + .2);
// Draw the shield
context.drawImage(shieldImage, -player.radius, -player.radius, player.radius*1.5, player.radius*2.3);
// Rotate the canvas back
context.rotate(-player.angle - Math.PI - .2);
// Reset the initial origin of the canvas
context.translate(-player.position.x, -player.position.y);
Since we cannot rotate the image itself, we use this trick, which consists in rotating the canvas, drawing, and reverting the rotation of the canvas. We also translate it in order to have the rotation axis on the player position.
You'll also notice I added some numbers in there. That's because your shield image is not a perfect circle. I distorted it so that it does not look weird with the current collision system (which is based on a circle). If you want to keep the oval shape of the image, you'll need to make more serious changes to the rest of the code so that collisions apply to that shape.
And that's it, your blue arc is replaced with your PNG image (Updated JS here)
PS: You have a cool last name ! - same as mine
I have a bunch of png map tiles that I am trying to stitch together on a canvas element.
jsFiddle
I am making a 10x10 tile with a counter from 0 to 99 (id) to keep track of where I'm up to. This is the line that plots the image:
ctx.drawImage(this, id%10*imgWidth, Math.floor(id/10)*imgHeight, imgWidth, imgHeight);
Where id is some number from 0 to 99, imgWidth is the width of each tile and imgHeight is the height of each tile.
I am reasonably confident that should work, but it appears to just plot one stretched tile on the canvas instead of all 100. When I check the console for what was loaded, the images appear to be the correct shape and contents for each tile. The just don't seem to have been placed on the canvas. Does anyone have any ideas?
One reason to not use jQuery with canvas:
$('canvas').width(imgWidth*10).height(imgHeight*10);
:) as this refers to the element size, not the bitmap. I would suggest using instead:
myCanvas.width = imgWidth*10;
myCanvas.height = imgHeight*10;
Modified fiddle
I was creating some visual elements using Fabric js. In my project, the path's were getting updated. But the issue is, the path's measurements were not as expected.
Refrer to jsFiddle
var canvas = new fabric.Canvas('c', {width: 400, height: 400});
var line = new fabric.Path('M,50,50,L,50,150,150,150,150,50,Z', {
fill: 'blue'
});
line.setCoords();
// During update
line.initialize('M,150,50,L,150,150,300,150,300,50,Z')
line.setCoords();
canvas.renderAll();
In the sample the path was initially drawn 50px away from the canvas left border. Then I have changed the path command so that it move's 100px towards the right.
But after updating the path, the shape is actually positioned at 175px away from the left.
Also, the left property of the path element is not changed.
Also, unable to get the idea of all these properties and their relations like,
left, top, scaleX, scaleY, height, width, pathOffset, oCoords, originalState etc in various conditions like the path / canvas is scaled, rotated, moved, placed inside a group etc.
I'm not sure what you are trying to achieve but the initialize method is not an update method but it's the constructor of the class, you are practically overriding the initial object's path.
If your are just trying to move around your original created path you should play with left, top properties of the Path object like in this updated fiddler
I've been struggling to get this code working. Basically, I want the user to be able to click anywhere inside of the canvas, and the coordinates at the clicked point will be where the rectangle gets drawn. However, the code I have places the rectangles at totally unexpected points along the canvas. I checked the values in Firebug and they seemed to be accurate based on where I clicked inside the canvas, so I'm not sure why the rectangles are not getting drawn at the correct points. Maybe there is some other mistake going on that I am not seeing though, so any help or input would be appreciated. I've posted the relevant code below.
I should also note that the canvas element is inside the div with id='container'.
$('#container').click(function (e) {
var offset=$(this).offset();
var x=(e.pageX - offset.left);
var y=(e.pageY - offset.top);
ctx.fillStyle='#FF0000'; //color red
ctx.fillRect(x,y,10,10); //draw 10 x 10 rectangle starting at x,y
});
pageX/Y gets the x/y coordinate of the page (think 100, 200). Let's say your canvas is positioned at (100,100) on the page. When you're graphing the point, you're saying "Graph a point at 100,200 IN RELATION TO THE CANVAS. That would mean you are trying to graph a point at (200,300) instead of (100,200) linke you want. You need to get your x/y in relation to the canvas, like so:
var x = event.offsetX !== undefined ? event.offsetX : event.layerX;
var y = event.offsetY !== undefined ? event.offsetY : event.layerY;
If you only want to add a click event on the canvas then it's better to use
$("#myCanvas").click(function(e){
});
If you use myCanvas instead of container then $(this) would refer to the canvas and you get the position of the mouse relative to the canvas.
It is because you use the container div that the variable offset is wrong.
Here is the graphics:
http://snag.gy/aVFGA.jpg
the big rectangle is canvas element, the small rectangle is the image object in the canvas. I want to find what is the real distance from the left.
values are such from what I see in console:
regX: 564.256
regY: 41.4
scaleX: 0.4491319444444445
scaleY: 0.4491319444444445
x: 363.3333333333333
y: 409.77777777777777
So as I see x is not real. It somehow relates with regX and scaleX. But I am not finding how it relates. From the image I think the x should be about 100 - 150 px.
THe bigger the x - the more it is to the right.
But the bigger regX - the more it makes rectangle go to the left.
So if I would just take the difference 564.256 - 363.333 = ~200 - left corner of the rectangle should be in them middle of canvas because canvas is 400px widh. But it is not, so substraction does not help. So how do I get how many pixels are in real from the left?
You can do this by using the localToGlobal method (see here).
It depends to which object the given attributes belong.
If they belong to the shape and your rectangle inside the image / shape starts at (0,0):
var point = shape.localToGlobal(0, 0);
// this will calculate the global point of the shape's local point (0,0)
If they belong to the stage:
var point = stage.localToGlobal(yourRectObject.x, yourRectObject.y);
// point.x should contain the position on the canvas
You should use these methods in general because your method might work for the current situation but will probably break as soon as you scale the stage itself or put the shape in a scaled / positioned container.
I guess I found what by experimenting with values:
distanceFromLeft = x - scaleX * regX;
so getting 109.90793888888885 px
If someone has worked more with this library, they could confirm that its not accidental.