It seem when I trying to drag the bordercontainer to move along x-axis position on mouse down. It appear to move stable but became jerky when I drag a little faster.
Any way to get bordercontainer move with smooth motion?
private function mDownHandler(event:MouseEvent):void {
gMouseX = event.localX;
borderCntr.addEventListener(MouseEvent.MOUSE_MOVE, mMoveHandler);
}
private function mMoveHandler(event:MouseEvent):void {
borderCntr.x = int(event.localX)-gMouseX;
}
are you targeting mobile devices? MouseEvent.MOUSE_MOVE is quite intensive for mobile devices since it calls many more times faster than the framerate. it's not optimized nor recommended to use MouseEvent.MOUSE_MOVE for projects with mobile deployment targets.
instead, create your own moving logic by employing either the stageX and stageY properties or startDrag() and stopDrag() functions with an Event.ENTER_FRAME event.
1) You shouldn't use local coordinates in your mMoveHandler, because it's coordinates of mouse inside borderCntr - it simply couldn't work as you wish to. Use parent's or top level application's mouseX or simply event.stageX.
2) Don't add MouseEvent.MOUSE_MOVE listener to borderCntr. When you will make very quick movement and mouse will walk outside borderCntr, you simply won't recieve move events anymore. Instead listen to parent or stage or top level application (again), the one that would not loose mouse.
Related
I'm trying to make my own component that behaves like a list and supports infinite scrolling (in 1-dimension : vertical or horizontal) - both directions. For eg, a vertically laid out list which the user can scroll up or down forever - without ever hitting the 'last' or 'first' item. A good use for this: a calendar that displays each month as a list item.
Anyway, there are a bunch of things to overcome. The first of which, I think, is to disable the scrollbar's bounce effects (introduced in the latest Flex 4.5 (mobile) SDK).
If I can disable the bounce effects, I'm guessing I can then add/remove items as needed to the list and it would scroll infinitely.
Any ideas?
Krishna
Personally, an infinite list would mean a lot of rework of the core List component. It's a lot of work to reverse engineer and you'll probably hit a wall. I think what you want to do is create a component from scratch and extends SkinnableContainer.
From here on out, you need to decide how to implement and what's the user interaction for an infinite list, then need to implement proper practices and reuse your item renderers.
From my experience, you can simply implement the lazy loading on the List component by adding property change event to the viewport of the list's dataGroup
list.dataGroup.addEventListener( PropertyChangeEvent.PROPERTY_CHANGE, onScrollPropertyChangeHandler );
Then in the event, listen to the vertical scroll position
if ( event.property == "verticalScrollPosition" ){
var listHeight:Number = itemList.height;
var curAnchorPoint:Number = event.newValue + listHeight;
var bottomPositionToLoad:Number = 200; // Start loading when the list nearly reach the bottom minus 200
var anchorToLoadNextPage:Number = itemList.dataGroup.contentHeight - bottomPositionToLoad;
if(curAnchorPoint >= anchorToLoadNextPage){
loadNextPage();
}
}
When loadNextPage() is running, remember to remove the property change event so the loadNextPage will not be called multiple times.
I have Sprites that I want to have move around when I click and hold them and stop when I release them. I have methods that add Event listeners to the Sprites:
public function layOutEventListeners():void
{
var addSpriteEventListener:Function =
function(spr:Dictionary, index:int, vector:Vector.<Dictionary>)
{
spr["sprite"].addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
spr["sprite"].addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
gridVec.forEach(addSpriteEventListener);
}`
and methods to handle the events:
public function mouseDownHandler(me:MouseEvent):void
{
trace(me.target.toString());
trace(me.currentTarget.toString());
this.drawSprite(me.target);
this.growByTwo(me.target);
me.stopImmediatePropagation();
me.currentTarget.startDrag(me);
}
public function mouseUpHandler(me:MouseEvent):void
{
trace(me.target.toString());
trace(me.currentTarget.toString());
me.stopImmediatePropagation();
this.originalSize(me.target);
me.currentTarget.stopDrag();
}`
My problem is: when I click on the Sprites, as soon as I move the cursor, the Sprite's registration point snaps to the cursor, and when I release the mouse the Sprite doesn't stop following the cursor. I initially thought it was a problem with pixel collision. I thought the cursor wasn't touching anything on MOUSE_UP, but that proved to be false after I experimented. I even replicated the exact same Event adding and handling methods by starting another project and found that I wasn't having this problem. The test Sprite was simply dragging and dropping like usual, not snapping to the registration point, and being dragged by the point I clicked.
The only difference I can see, and also my only suspicion, is that the Sprites in my original code are being added to a Sprite, which is then being added to the stage, whereas the Sprite in the test project is being added to the root DisplayObject. I'm thinking that somehow the Event propagating down to the container Sprite and dragging and dropping that without dropping the other Sprite. The weird snapping I'm seeing might be the cursor snapping to the object behind the other sprite. Another important thing: when I drop a Sprite on top of another Sprite, that Sprite stops moving like I want it to, but still trails the registration point.
Regardless, I'm really stumped and I really don't know that I'm running over. Any ideas?
This is usually because sometimes the mouse is not over the clip when MOUSE_UP occurs, either because of other clips getting in the way or maybe the player is not refreshing the stage fast enough, etc...
I'm not sure this is your case, but either way it is often recommended to assign the MOUSE_UP event to the stage, so you can safely assure it is always triggered. Make sure to remove the listener on the mouseUp handler though ;)
spr["sprite"].addEventListener(MouseEvent.MOUSE_DOWN, mouseDownHandler);
public function mouseDownHandler(me:MouseEvent):void {
stage.addEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
public function mouseUpHandler(me:MouseEvent):void {
stage.removeEventListener(MouseEvent.MOUSE_UP, mouseUpHandler);
}
The down side is that you lose your clip reference on mouseUp, but you can create a reference by hand on mouseDown, or do the whole thing internally (within the sprite's code).
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 am creating a component that will be a large plus or a large minus. I don't want to use a bitmap because even I can draw this using the Graphics class, but the component must be clickable (the Shape class is not).
It will be part of an item renderer, so I want it to be as light-weight as possible. UIComponent does not seem to sent CLICK messages.
Thanks for any ideas
I would suggest creating a Sprite object and drawing the minus and plus arrows to its graphics object. You'll then have to addEventListener(MouseEvent.CLICK, someFunction); in its constructor or wherever else you'll need it.
You may also want to set cacheAsBitmap to true at that point, so that it's not redrawn every frame.
EDIT: Per #jeremynealbrown you have to use the SpriteAsset class if you are working in Flex, apparently. Very similar, but another 2 levels of abstraction are added.
If you look here:
UIComponent Docs
You will see that UIComponent has InteractiveObject in its inheritance path. InteractiveObject is the class that adds mouse event functionality.
UIComponent will actually dispatch click events. However, if there is no content drawn to the graphics, the UIComponent will have no area that can be clicked. If the plus or minus icon you draw is too small to reliably catch mouse activities, then draw a fully-transparent rectangle to increase the hit area.
When a Flex component moves directly, so that its x and y properties change, then a "move" event is dispatched on the component. That's all fine.
However, a component may also move as a result of its parent component moving — or its parent moving, and so on. Now when a parent component moves, its children just "move along" without any properties changing or move events being dispatched on the children. Still, the children are moving on the screen. So how can you detect this kind of generalized movement?
One workaround is to capture all move events in the application:
Application.application.addEventListener
(MoveEvent.MOVE, handleMove, true, 0, true);
The third argument is required because move events do not bubble, and so instead have to be captured. The fourth argument is unimportant, and the fifth argument turns on weak references, which is a good idea in this case because we are creating a global reference from Application.application to handleMove — a recipe for memory leaks.
Of course, this will fire too often (once each time anything whatsoever in the application moves), and in a large application could lead to performance problems. If you know that there is some component higher up in the hierarchy that’s sure to stay still, you can put the listener at that point instead of globally, which could reduce the problem.
Still, it would be nice to have a cleaner way to solve this.
Well, you've already suggested the most general solution, but I think it's possible for the child to go through parents/grandparents until it reaches one that is stationary (set by some dynamic property you set), at least this would save you some trouble in figuring out which parent handles which child.
private function addHandlerToStationaryParent(handler:function):void
{
var currentParent:DisplayObjectContainer = parent;
while(currentParent != null)
{
if(currentParent["stationary"] == true)
{
currentParent.addEventListener(MoveEvent.MOVE, handler);
return;
}
}
}
I guess it would be your preference as to whether or not this would be a better solution.