Canvas: Stop panning at end of image - javascript

I'm implementing the ability to zoom-in and pan around my canvas. I'm doing this by having two canvases, one for the drawing and one displaying the viewport. I'm having trouble finding the limit for the clipping region.
Anyway this all works, i'm just setting the scale to some value higher than 1 when zoom-in is called, this has the desired effect.
I'm panning the canvas in the same way you would animate a sprite-sheet, the viewport canvas just acts as the clipping region on-top of the drawing canvas.
I'm stuck with what numbers to set for the boundaries to stop the canvas going too far right and down however.
Here how i'm implementing the pan just for some clarity:
//This only gets called when the canvas is zoomed in.
viewPort.drawImage(canvas,translationX,translationY,viewPort.width,viewPort.height
,0,0,viewPort.width,viewPort.height);
TranslationX starts off at 0 and after every key-press of the right arrow I increment that by some value, I know this should not be some arbitrary number, but for now I've just set it to 4.
Anyway this all works, but it goes off the edge of the canvas, and i'm having trouble working out what the condition should be to stop panning right, here's what I have so far:
if(canvas.width + translationX <= bCanvas.width)
translationX += 4; //Pan right...
Obviously this doesn't work, it pans about 1/5 of the viewport off the canvas edge. I'm now just hacking about with it, just throwing arbitrary numbers into the condition, so thought this would be a good time to ask for some guidance.
Thanks in advance
Edit:
Ok so i've made an image to illustrate the problem incase my explanation was unclear.
The green box represents the image I am panning, the 'canvas' named in the above snippets.
The yellow box represents the clipping region, the 'viewPort' in the above snippet.
The grey area is just represents the rest of the webpage.
So to clarify, i'm confused as to what value to put into the condition to stop the clipping region going off of the canvas.
Thanks again

Related

Why isn't Paper.js's `smooth: continuous` function working as expected?

Sketch link
I want to smooth out the subtraction of these two spheres, as seen in the sketch. I expected smoothing via the continuous type to remove the pointy edges of the sphere, but this didn't happen. If you change the position of the second circle to a number greater than 100 (circle v), then the smoothing works correctly. How can I solve this?
The smooth function will try to remain course to the original curve, that often means keep some corners.
Instead, you can add some handles to your corner points. That way you will have a good control on the curvature of your drawing.

Image registration (aligning one image to match another)

Currently I have an image that needs to be manipulated so it matches the same scale, position, and rotation as a template.
The grey rectangle with a circle in the middle is the template.
The orange rectangle and circle represents the user's input. It needs to be rotated, scaled and aligned to it matches the grey one. I'm currently stumped on how to proceed. I've no code other than the following.
function align_image()
{
// clever transform alignment code here
}
Bad dog, no biscuit!
The process at of aligning the images would normally be done manual input and judged by eye. I'm hoping to automate this step and align the image to its respective size and position but leaving the comfort and safety of Photoshop DOM I'm not sure how to proceed or even if this is a trivial matter or one left best alone. The project is web based currently using javascript and three.js
So if anyone can give me some pointers I'd appreciated it.
I don't code javascript so I can only talk about the algorithm. Generally best tool for registration is to use feature matching methods (using sift, surf,...) but your image is not the kind that have strong features. Now if you're always dealing with rectangles and circles in your images, find the "edges" of the rectangle with Hough Transform, compute the angle of those edges (lines) then rotate the image with that angle in the opposite direction.
Then with the help of Hough Circle Detector, find the center of the circles in the middle of the images, calculate the distance between them, and move the target rectangle to the source's circle position. After the movement by comparing the radius of the circles, you can resize the target image to make it like the source rectangle.
All of these are conveniently doable with Opencv.

Rotate a resized rectangle with SVG and Javascript

I'm using d3js and SVG to resize and rotate rectangles, I capture the mouse events on handles that are positioned in each corner of the rectangle, there are two handles in each corner, one for resizing (square) and other to rotate (circle).
When I do the following process, the rectangle "jumps" from its location to another one:
Rotate (it means it's not more in zero degrees)
Resize (any direction)
Rotate again (here is when the shape "jumps")
The jump only occurs when the center of the rectangle is updated, using transform rotate from SVG.
One thing that gave me a lead was updating the rotation center while the shape is being resized, when I do this the shape starts to move to the final position where the "jump" would have placed it.
I can post code examples, it will take some time to do, but if helps to see the problem, no problems.
All I need is some direction from someone that already had this problem.
Edit:
I've made a Plunker with somewhat the current structure that I'm using in my project. All events controls are concentrated in the svgApp.directive.js.
Things I've noticed while developing this example:
The center of the element is not correctly calculated after the angle is not zero, this is my main issue;
If you apply the {{vm.model.image.transform.rotate}} to the ng-attr-transform attribute in the center <circle> element, you are going to notice how it always is in the correct center (the right circle - blue - is commented at the bottom of the main SVG);
I know this is not the perfect version of the tool, it still has some bugs, like the inversion of the mouse direction (resize/rotate handles) while rotated, but it's well documented and structured very close to how I'm working on the project.
The Plnkr: http://plnkr.co/edit/fXT0kZcRwJTPb7wQVHpg?p=preview
Any help with this problem will be very appreciated.

Wraparound for HTML5 Canvas: How to Get (Static) Shapes to Continue around Edges of Canvas

I'm trying to draw a tiled background using Javascript on an HTML5 canvas, but it's not working because shapes that intersect the edges of the canvas don't wrap around to the other side. (Just to be clear: these are static shapes--no motion in time is involved.) How can I get objects interrupted by one side of the canvas to wrap around to the other side?
Basically I'm looking for the "wraparound" effect that many video games use--most famously Asteroids; I just want that effect for a static purpose here. This page seems to be an example that shows it is possible. Note how an asteroid, say, on the right edge of the screen (whether moving or not) continues over to the left edge. Or for that matter, an object in the corner is split between all four corners. Again, no motion is necessarily involved.
Anyone have any clues how I might be able to draw, say, a square or a line that wraps around the edges? Is there perhaps some sort of option for canvas or Javascript? My google searches using obvious keywords have come up empty.
Edit
To give a little more context, I'm basing my work off the example here: Canvas as Background Image. (Also linked from here: Use <canvas> as a CSS background.) Repeating the image is no problem. The problem is getting the truncated parts of shapes to wrap around to the other side.
I'm not sure how you have the tiles set-up, however, if they are all part of a single 'wrapper' slide which has it's own x,x at say 0,0, then you could actually just draw it twice, or generate a new slide as needed. Hopefully this code will better illustrate the concept.
// Here, the 'tilegroup' is the same size of the canvas
function renderbg() {
tiles.draw(tiles.posx, tiles.posy);
if(tiles.posx < 0)
tiles.draw(canvas.width + tiles.posx, tiles.posy);
if(tiles.posx > 0)
tiles.draw(-canvas.width + tiles.posx, tiles.posy);
}
So basically, the idea here is to draw the groupings of tiles twice. Once in it's actual position, and again to fill in the gap. You still need to calculate when the entire group leaves the canvas completely, and then reset it, but hopefully this leads you in the correct direction!
You could always create your tillable image in canvas, generate a toDataUrl(), and then assign that data url as a background to something and let CSS do the tiling.. just a thought.
Edit: If you're having trouble drawing a tillable image, you could create a 3*widthx3*width canvas, draw on it as regular (assuming you grab data from the center square of data as the final result), and then see if you can't draw from subsets of the canvas to itself. Looks like you'd have to use:
var myImageData = context.getImageData(left, top, width, height);
context.putImageData(myImageData, dx, dy);
(with appropriate measurements)
https://developer.mozilla.org/En/HTML/Canvas/Pixel_manipulation_with_canvas/
Edit II: The idea was that you'd have a canvas big enough that has a center area of interest, and buffer areas around it big enough to account for any of the shapes you may draw, like so:
XXX
XCX
XXX
You could draw the shapes once to this big canvas and then just blindly draw each of the areas X around that center area to the center area (and then clear those areas out for the next drawing). So, if K is the number of shapes instead of 4*K draws, you have K + 8 draws (and then 8 clears). Obviously the practical applicability of this depends on the number of shapes and overlapping concerns, although I bet it could be tweaked. Depending upon the complexity of your shapes it may make sense to draw a shape 4 times as you originally thought, or to draw to some buffer or buffer area and then draw it's pixel data 4 times or something. I'll admit, this is some idea that just popped into my head so I might be missing something.
Edit III: And really, you could be smart about it. If you know how a set of objects are going to overlap, you should only have to draw from the buffer once. Say you got a bunch of shapes in a row that only draw to the north overlapping region. All you should need to do is draw those shapes, and then draw the north overlapping region to the south side. The hairy regions would be the corners, but I don't think they really get hairy unless the shapes are large.... sigh.. at this point I probably need to quiet down and see if there's any existing implementations of what I speak out there because I'm not sure my writing off-the-cuff is helping anybody.

Canvas overlapping elements

I have a canvas animation that sometimes redraws the exact same element over another (it is a long story why this is necessary) but it happens, and it happens often enough.
Now I assumed that drawing an element (using a context path and the stroke method) over an existing exact replica of the image should do nothing at all to my animation. Instead it draws over the past image and blurs all the sides (as if it didn't exactly draw at the same location.
Please let me know if there is a way to fix this
Thanks
This is happening because canvas strokes are anti-aliased. In a practical sense you're drawing some semi-opaque pixels over some other semi-opaque pixels, and where the pixels are overlaid their opacities are added together. I don't think you can (currently) force the canvas object to turn off anti-aliasing on strokes, so you may just have to live with it. Is it that big of a problem?
http://img813.imageshack.us/img813/303/canvasl.png
EDIT: I guess you could try using PNGs with transparent backgrounds for your markers, instead of drawing them with strokes. https://developer.mozilla.org/en/Canvas_tutorial/Using_images

Categories