Recently I worked in a project using Flex. Its a Photo editing project. I have took a Canvas and take a image in that canvas using the code canvas.addChild(image) . Now i can move the image freely by using moving code. The image move inside the canvas and outside the canvas. I want to move the image/child only inside the canvas not outside. How can i do this?
There are two ways to do this:
Bounding Rectangle
Scroll Rectangle (or Mask)
Assuming your "moving code" is something like an Event.ENTER_FRAME handler initialized onClick, you want to make it so the image can't leave the bounds of the parent Canvas.
The first case (bounding rectangle) will allow you to drag the image within the retangle but you will always be able to see the whole image. This is how Image croppers work.
To create a bounding rectangle, you'll have to write a fairly detailed method, but the idea behind it is simple. Just get the bounding rectangle from the canvas, and don't let the image.x go below 0 and don't let image.x + image.width go beyond canvas.width. Same with height. Here's a sample Image Cropper in Flex (and the source). Check out how they did it for details.
The second case (scroll rectangle) would allow you to create more of a pan/zoom like container like you see on this Flex Pan/Zoom Map (here's the source). Also, the large image in the Flex Image Cropper on the right is an example of this second case, but they don't have the dragging. That requires that you manipulate the position of the scrollRect property on the canvas. The scrollRect property is a flash.geom.Rectangle defining the Canvas' "viewport". You then change/update the verticalScrollPosition and horizontalScrollPosition properties, so it's backwards (compared to the Bounding Rectangle).
I think if you set clipAndEnableScrolling to true on the canvas, and you drag a child image around inside of it (and image.includeInLayout = true), it should clip the image to only show up inside the canvas. But I'm guessing you want case 1. Just search those properties and you'll find some good examples on google.
Good luck, should be a fun project.
Lance
Related
Hi i'm trying to get a photoshop-like behaviour for my QGraphicsScene
The grid in the background should not resize with the call of scale. And I must be able to save the picture with QPixmap::grabWidget(view) but without the background grid. I can probably do it with removing the background layer just before saving the picture, but i'm not sure if its cleanest way to do it.
Any ideas ?
thx.
Question 1
The grid in the background should not resize with the call of scale.
Use the QGraphicsItem::ItemIgnoresTransformations flag.
The item ignores inherited transformations (i.e., its position is
still anchored to its parent, but the parent or view rotation, zoom or
shear transformations are ignored). This flag is useful for keeping
text label items horizontal and unscaled, so they will still be
readable if the view is transformed. When set, the item's view
geometry and scene geometry will be maintained separately.
In order to set this flag use the setFlag function when creating the grid item.
Question 2
I must be able to save the picture with QPixmap::grabWidget(view) but without the
background grid.
Call the hide function on the grid item before calling the grabWidget. After you have grabbed it you show it again by calling the show function.
I have an image that I show inside a canvas which I can zoom in on.
The problem is that when zoomed in, I try to drag the image, I can see the outline of the image in the foreground, (i.e.) outside the canvas boundary.
Is there anyway to tell the dragHandler to crop the "grabbed" image outside the canvas boundary?
In my experience using the built in drag/drop flex stuff is overkill for something that involves moving a component around in a canvas.
The easier way to do this (in my opinion) would be to listen for mouse down/up/move the image around in the canvas yourself.
When you detect a mouse down on your image, add a listener for mouse move (pro tip: make sure you set useCapture to true when calling addEventListener) and store the position of the mouse relative the origin of your image. Then whenever you get a mouse move, change the position of your image within your canvas taking into account the position of the mouse within the image (which you stored on mouse down). Keep doing this until mouse up occurs, then remove your mouse move listener.
There are some additional finer points to account for (what if the user drags outside of the canvas? Or outside of the browser window?), but this will get you started.
Hope that helps.
I'm programming a debate-graph with Raphael JS. Users can add nodes to the graph. Eventually the graph gets really big and the canvas is still the same size. the canvas (in raphael js: paper) is inside another div with "overflow: scroll;", so lets ignore screen real estate
Is there a way that I resize the canvas without reloading the page (to assign new X/Y values)?
Alternatively, can I create a second bigger canvas in parallel and copying all the elements over? is there a way?
If I understand your question, just call setSize() to expand the size of the canvas to the size needed as you need it. I've used this in a div with overflow:scroll to get the effect you describe.
In my case, I didn't want to resize, I wanted to zoom.
In other words, show the user the growing graph inside a constant-sized div.
So I needed: setViewBox()
I have a component which draws a grid of things and I want a small highlight square to follow the mouse around highlighting the square that the mouse is currently over.
The whole grid is basically just one big sprite (it's a very large grid and this was faster than using pre-existing components) and the highlight square is another sprite which I'm trying to move around according to the mouse position.
So, what I have is a MouseEvent.MOUSE_MOVE handler attached to the grid sprite and this tries to determine where the mouse is and what square it's over so that it can move the highlight square to the right place. I was using localX/localY for this, but as soon as I move the highlight sprite under the mouse, these become local to the highlight and not the grid!
I was toying with stageX/Y as well, but these seemed to become pretty useless when the stage is scrolled or your component is hiding in nested display containers.
Basically, i think, you want to check the the grid components mouseX and mouseY property which will give you the mouse coordinates relative to that component. Then a little bit of maths should be able to give you what grid element you are over.
Assuming your highlight sprite is a sibling to the grid and they are both children of the main application, and you've drawn child sprites (squares) within the grid: You could add event listeners to each of the grid's square sprites. On rollover, highlight the square. Then you probably won't need to perform any translation of grid or mouse coordinates using grid.localToGlobal(new Point(targetSquare.x, targetSquare.y)) or highlightSquare.globalToLocal(grid_point).
If I have an object in a layout in Flex what is a good way to 'break it out' of that layout to be able to animate it.
For instance I have an image and a caption arranged at an angle. I want to make the image 'zoom out' slightly when the mouse rolls over it. Since its in a layout container is active if I were to resize it then obviously it would move around everything else.
I dont think I can achieve what I want by just setting includeinlayout=false.
Any experience with best practices on this?
My best idea I'm wondering about is making the image invisible and creating another image at the same location by using the screen coordinate conversion functions. This jsut semes clumsy
Wrap your object in a fixed size Canvas so that the layout upstream will remain the same. Then position the object manually within that container and then set its includeInLayout to false. At that point, you could do whatever you wanted with the interior object. Oh, also set clipContent to false. This should work whether you want it to grow or shrink.
If this is an itemrenderer or something that you've wrapped into a class, you could handle all of this in the class definition and make it transparent to consumers of the object. You'd also be able to write a mouseOver function that did what you wanted with the interior object that should zoom.