Running into offset bug when drawing sprites using pixijs - javascript

I have the map on which I need to draw some amount of hexagons (approximately it will be from 50*50 to 150*150 elements).
When I draw them on the canvas using PIXI, I get really strange behavior: while it's not a lot of elements, the map has been drawn correctly, all the elements on their places. But when the canvas size changed to about 5000px width and height, all the elements are moved top above the screen. Moreover, the click on the element has been handled on the place where it should be.
I've created a pen to demonstrate this: https://codepen.io/cuddlemeister/pen/OdzMBw
Try to change canvasWidth and canvasHeight in the evnironment from
canvasWidth: 1500, canvasHeight: 1500 to canvasWidth: 4500, canvasHeight: 7500 and you will see the result.
Here's the evnironment object:
const environment = {
size: 60,
map: {
rows: 30,
cols: 30,
},
canvasWidth: 1500,
canvasHeight: 1500
}
You will the that all the visible content has been moved in top direction and it depends on the height of the canvas.
There's a logger enabled on click, try to click the elements or the area where they are supposed to be - the click is handled correctly on the place where the element should be

It's because the max size that WebGL context can handle. You can check it by logging app.gl property.
When using not accelereated canvas via "forceCanvas" everything is ok.
I don't think there is any way to bypass this limitation.
Why do you need so big canvas?

Related

Scaling a shape in Phaser 2 without having it move

So, I'm trying to create a (very) simple progress bar in Phaser, (initially it's empty) and getting it to resize/scale to a specific size.
I'm not a fan of erasing and redrawing, since I assume this is more resource-heavy / not as efficient as simply tweening.
Whenever I scale its width, it insists on moving to the right - it is also updating its X coordinate as well.
I do know that we should change/set the anchor. I tried setting it to 0.5 (center), to 0 (left, top) and to 1.0 (bottom, right) as I saw in this question (and in the Phaser forums), but no matter the value that I set, the progress bar always moves (and always to the same place) as well.
Here is my code:
//Fill
var graphs = game.add.graphics(0, 0);
graphs.lineStyle(2, 0xFF0000, 1);
graphs.beginFill(0xFF0000, 1);
progressBar = graphs.drawRect(100, 50, 1, 20);
progressBar.anchor.setTo(0.5, 0.5);
//Outline
graphs = game.add.graphics(0, 0);
graphs.lineStyle(2, 0xFFFFFF, 1);
progressBarOutline = graphs.drawRect(100, 50, 100, 20);
progressBarOutline.anchor.setTo(0.5, 0.5);
//Resize it whenever the user presses the game area
game.input.onDown.add( resizeProgressBar, this );
And here is the code that I call to resize the (fill) bar (currently done through a tween):
function resizeProgressBar()
{
game.add.tween(loadingProgressBar.scale).to( { x: 2.5},
1000, Phaser.Easing.Quadratic.InOut, true);
}
Here is a fiddle that shows the issue (click on the canvas to update the bar).
This can't be that complicated. Am I forgetting something? Or am I supposed to calculate the new x position myself?
I'm using Phaser CE 2.11
I'm not sure why the height of the progressBar is growing, nor why it's moving, as I haven't done much with the raw graphics drawing capabilities in Phaser. However, there's a few things I do know which might help.
The difference between the questions you've linked to and your progress bar is that you're using raw graphics, instead of sprites.
If you switch to using a sprite-based progress bar you could either scale or set the width, depending upon what your progress graphic looks like.
Another option would be to do something similar to this tutorial for progress bars in Phaser 3. The relevant bits are defining the progress bar and then creating it:
var progressBar = this.add.graphics();
/// ...
this.load.on('progress', function (value) {
progressBar.clear();
progressBar.fillStyle(0xffffff, 1);
progressBar.fillRect(250, 280, 300 * value, 30);
});
You can change the last five lines as needed for your particular circumstances.
While this does clear and then redraw the rectangle, I personally haven't seen much of a performance hit doing this. At least with older versions of Phaser 2, using Sprites instead of Graphics seems to be the way to go. Of course, it also depends upon how often and how many of these progress bars you'll be displaying.

Resize rectangle "onResize" in paper.js

Ok, I feel incredibly stupid, but after trying for half an hour or so, I give up.
How do I resize a rectangle via the onResize() event in paper.js?
I am trying with this example, which comes with a onResize() function already, but I am having no success (you can edit the sample by clicking on the Source button on the top right).
The current resize function looks like this:
function onResize() {
text.position = view.center + [0, 200];
square.position = view.center;
}
Now, I tried to make the square 80 % of the viewport height on resize by adding:
square.size = [view.size.height / 100 * 80, view.size.height / 100 * 80];
(I tried the same with static numbers, just to be sure).
I tried
square.size = new Size(width, height);
square.set(new Point(view.center), new Size(width, height)
square.height = height;
square.width = width;
and probably 20 more version that I cannot remember now.
When I console.logged the square.size it did show me the newly assigned values (sometimes?), but it still left the size of the rectangle unchanged.
What can I do to actually change the size of rectangle?
Just to make sure, the onResize() function gets called whenever the window's dimensions change. That's not the only place you can change the rectangle's size / it has nothing to do with the rectangle per se.
To change the rectangle's sizes, you have to check the documentation. There's a scale(amount) and an expand(amount) method attached to the Rectangle object. size is just a property, and it doesn't seem to come with a setter.
Hence, if you want to keep a ratio in between the square and the view, I guess you could save the previous view width, see what the difference is and scale the rectangle accordingly – see how in this this answer to a previous question.
Alternatively, you could just reinitialise the square and set the size property to 80% of the view's width on each view resize:
square = new Path.Rectangle({
position: view.center,
size: view.bounds.width * 0.8,
parent: originals,
fillColor: 'white'
});

Having the classic blur issue but not finding a working solution

So we all know the issue with shapes being drawn with a slightly blurred stroke. I was able to fix it without further problems when using plain js and canvas with following methods:
context.sRect=function(x,y,w,h){
x=parseInt(x)+0.50;
y=parseInt(y)+0.50;
this.strokeRect(x,y,w,h);
}
context.fRect=function(x,y,w,h){
x=parseInt(x);
y=parseInt(y);
context.fillRect(x,y,w,h);
}
However, when using easeljs stage, these methods dont have any impact at all and the shapes stay blurred. I also tried offsetting x and y as well as width and height by -.5 when using drawRect(); That didnt work either. The last thing I tried was setting stage.regX and stage.regY to -.5 which did change the output but only to an altered blur (slightly more blurry).
Did I miss something?
PS: I need the canvas to always have the same width and height (200 * 200) but at the same time always fill the screen. I accomplish this by always setting canvas.width/height to 200 and the css of canvas to 100%.
Simple answer: you can't.
When you use CSS to scale a canvas, you can think of it as scaling each pixel on the canvas individually. Because of this, you are going to need to counteract the antialiasing of the browser itself.
To accurately counteract antialiasing in raster graphics, you always need more space than the container, simply because of the quantisation of information in pixels. If you do want your canvas to hold a fixed amount of information (200x200 pixels), this is not possible.
What you can still do is use that canvas as the model, but not the view ;)
If I did not want antialiasing of a fix-sized canvas over a variable space, I'd create another canvas whose size won't depend on the css, but on js events (look into window resize event listener and window.innerWidth, window.innerHeight), then draw the "model" original canvas on it while disabling ctx.imageSmoothingEnabled (= false), so that you'll get the needed result.
Here's a minimal example:
var canvasModel = document.createElement( 'canvas' ), // your current canvas
canvas = document.getElementById( 'view-canvas' ), // displaying on the screen
ctxModel = canvasModel.getContext( '2d' ),
ctx = canvas.getContext( '2d' );
ctx.imageSmoothingEnabled = false;
// all of your stuff that you're currently doing goes here
...
// every time you update the 200x200 canvas, you do this:
ctx.drawImage( canvasModel, 0, 0, w, h );

raphael zoom out with grid - infinite paper size

I am attempting to create a simple drawing package using Raphael.
For this example, I have defined a paper with a specific size that has a grid drawn to the edges of the paper . In my actual application, the paper is set to the size of the div.
See the fiddle http://jsfiddle.net/davidbe/LhWZ5/
I'm using the raphael.pan-zoom package to support zooming with the scroll wheel and panning with the left mouse button.
page = Raphael(graph_paper, 402, 602);
panZoom = page.panzoom({ initialZoom: 0,
initialPosition: { x: 0, y: 0},
maxZoom: 30,
minZoom: -10});
panZoom.enable();
This works fine when I zoom in, but the problem I am having is that when I zoom out so that the Raphael paper is smaller than the div, the grid lines do not extend to the edge of the div. I'm trying to figure out a way to have the grid lines always displayed to the edges of the div, regardless of my zoom setting. In order to do this, I think that I either need to define a larger paper size when I create the paper so that when I zoom out, I am still seeing part of the original paper. Alternatively, I may need to change the paper size as part of the zooming. Either way, I don't want to see x and y scroll bars for the div.
Another way to look at this is that I am trying to simulate an infinite page size. Any suggestions on how to implement this?

createImageHitRegion is not scaled with the image object

I am using a Kinetic.image object like this:
this.icon = new Kinetic.Image({
x: self.x,
y: self.y,
offset: [32,32],
image: self.imageItem.image,
width: self.size,
height: self.size,
scale: self.scale,
rotationDeg: self.angle,
draggable: true
});
The image is a PNG with transparent pixels. I also create a image hit region:
self.icon.createImageHitRegion(function() {
self.icon.getLayer().drawHit();
});
However, the hit region is wrong when I use the mouseover event. I suspect the hitregion is not scaled. Note that I also use offset so that the image rotates around it's center.
Am I doing something wrong of am I dealing with a bug here?
I had the same problem when the image is created passing width and height.
The library uses the width and height of the image to create the canvas to draw the hit region but the width and height is not used to scale the image that is drawn on the canvas.
If you search the kineticjs source you will see that inside createImageHitRegion there is a line that looks something like:
_context.drawImage(image, 0, 0);
Add the width and height for the image and it should work as expected:
_context.drawImage(image, 0, 0, this.getWidth(), this.getHeight());
In my case I didn't have to pass the scale attribute while creating the image, please verify if this is working when you provide the scale attribute otherwise you will have to tweak createImageHitRegion to account for that.

Categories