I am dynamically creating a canvas element which i want to use as pattern in the createPattern function.
However, the actual size of the pattern is not an integer value but a decimal, with dynamic size. Of course, it is impossible to create a canvas element with decimal size.
The question is: can i make the canvas to have a decimal spacing between the pattern tiles?
It's not possible out of the box. There is however a possible work around -
Lets assume the spacing wanted is 0.5 pixel, then you can:
Create a canvas of double size of the pattern image plus an extra pixel for spacing.
Set the canvas as pattern
Scale transform the main canvas, here it would be ctx.scale(0.5, 0.5);
Set fill style and fill the region with scaled positions (all coordinates must be scaled x2 in this case). For example:
If you want to fill the area 10, 10 to 100, 100, you would need to use 20, 20 to 200, 200 etc. dependent on the actual scale and assuming origin isn't translated.
The scaling will force the pattern to sub-pixel so you get the appearance of "decimal lines". Just remember to scale back to original scale afterwards (use save()/restore() for a simple solution to that).
If you wanted the gap to be 0.33 then use 3 as a factor, 4 for 0.25 and so on.
Related
I need to generate image on which will be lines representing distances between frets on guitar. It is supposed to be printed later and act as mask for marking the frets. Therefore, the distances has to be precise.
How can i generate image of specific size in centimeters / milimeters, so when I print it, it will have same size?
I can use Python / JS / Java / C++
As #Chris G wrote in the comment:
Generating an image is pixel based. If you create an image that has a line every 300 pixels and print it at 300dpi, the lines will be exactly one inch apart. (dpi = dots per inch). You can set the dpi in Photoshop for instance, then make sure the image is printed # 100% scaling. (in case it's not clear: the "digital distance" doesn't matter, since you can always adjust the dpi to achieve a specific millimeter distance in the printout)
For example, if I make an image of size 6*300px and 9*300px and I print it with 300dpi, it will be 6x9 inches on paper.
I use getImageData and putImageData to draw on canvas from a buffer canvas. I use these methods because I have a large number of particles and these proved to provide the best performance.
Now I'd like to add rotation of particles but I'm having problems with that.
Here is a jsfiddle which uses transformation matrix for rotation. As you can see in the picture (or fiddle) there are holes in the resulting image which I kinda expected from using this matrix.
nx = ~~ (xx * Math.cos(angle) + yy * Math.sin(angle) + cx);
ny = ~~ (xx * Math.sin(angle) - yy * Math.cos(angle) + cy);
But I don't know how to make this better, especially when I'm looking performance effecient solution?
jsfiddle demo
Image - square after rotation (square is used as a simple body):
Currently my backup is procedurally generated sprite animation which is prepared in advance with standard canvas states: save -> translate -> rotate -> restore.
Thank you very much for any directions you can give me.
The problem is that you are trying to map a single pixel to a single pixel. When you rotate an image, each pixel in the original can influence any of the surrounding pixels in the new image. You are effectively mapping the top left corner of each pixel to it's location in the new image, but you need map the center of each pixel to it's location in the new image and then check the overlap of this rotated pixel with that location, and the 8 surrounding pixels in the new image.
Here you can see the effect. The yellow dots are the centers of the pixel which find the "home" location for the pixel (i.e. where the majority of the influence will be placed). You then need to figure out the percentage of that pixel (the underlying blue/white grid) cell is covered by the original pixel (black box surrounding the yellow dot). Once you figure out the home location influence, you need to repeat that process for the 8 surrounding pixel with respect to current pixel in the original image. In your current code, you are using the top left corner of each pixel to find the home pixel for the new image. You should use the center of the pixel.
Since multiple iterations might affect the same pixel, you'll need to calculate the transformation in a buffer before drawing it to the final image. For pixels in the transformation that are not fully covered by pixels in the original image, figure out the percentage of the pixel that is covered and use that to influence the alpha channel. You'll have to take care when applying the pixels to the final image that you account for the alpha portion and blend with what's already there.
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.
I need to do something like this:
This may look quite easy, but there are some requirements:
- the width of the containing div should depend on the text length (is it possible at all in CSS?)
- all circles should be positioned randomly - this is the most diffucult part for me.
As I'm using border-radius for creating circles (setting height, width and border-radius of 50%) I try to create some kind of grid in JavaScript where I iterate through each element and get its dimensions. Then I get the position of previous element (if any) and add them to the current element dimensions. Additionally, adding some margins will help avoid collisions. Is it correct approach?
I'm just looking for a suggestion how to solve my two issues.
Circles that scale based on size of content.
This is something you will need to solve first, because you wont be able to place them anywhere without first knowing their dimensions.
Naturally the size of a DIV expands first by width, then by height. That is, the maximum width of a container must first be utilized before moving on to the height constraint. Because of this, making a circle scale with equal radius may prove to be quite difficult without using a relative averaging.
Relative averaging is finding the average dimensions of your height / width based of the exhisting area of the contianer bounding your content. For example:
The width and height of the DIV bounding your content can be detected with javascript. Let's say youve discovered those properties too be 200px x 20px respectively.
Your total area is width * height so 4000px; But we are trying to acheive a square so we can apply rounded corners and form a rounded circle. We want to find dimensions of a rectangle that will be equal to the same area and then apply those new dimensions.
To acheive the same area with an equal width * height you can do something like:
√ 4000 = 63.2455532
Thus: 63.2455532 x 63.2455532 = 4000
Random placement of DIVs, and avoid collisons between DIVs.
After finding dimensions, you will be able to use a rand on your (X,Y) coordinates for the placement. Push these coordinates and radius onto an array. Use recursion too place the remaining circles on collsion failures. A collision failure would come from an element that has overlapping (X,Y)+radius relative too elements in the array that were pushed successfully.
There's a 3x3 image. The CanvasPixelArray is:
[12,24,48,255,12,24,48,255,12,24,48,255,12,24,48,255,12,24,48,255,12,24,48,255,12,24,48,255,12,24,48,255,12,24,48,255]
I change the alpha of all pixels to 0 and back by:
bobs = this.gfx.getImageData(0,0,3,3).data
for (a=3;a<bobs.data.length;a+=4)
bobs.data[a] = 0
this.gfx.putImageData(bobs,0,0)
bobs = this.gfx.getImageData(0,0,3,3).data
for (a=3;a<bobs.data.length;a+=4)
bobs.data[a] = 255
this.gfx.putImageData(bobs,0,0)
All pixels became black. The browser changed the colors to black to save memory. Is there a way to prevent this or should I save a duplicate?
I think the reason for this is that Canvas uses premultiplied alpha, meaning all rgb values are multiplied by the alpha value for those pixels. It's done to speed up alpha blending with backgrounds, etc.
There's a section on premultiplied alpha in this article: wikipedia:Alpha_compositing
You'll probably have to either, as you say keep a copy of the unmodified values, or perhaps store an alpha value for the image and set the globalAlpha property before drawing the image.
(When I say image, you can equally create a 3x3 canvas, store the pixels there and use drawImage() to draw it to the main canvas).