I'm working in HTML5 canvas + Easeljs
I would like to rotate objects in my application using my mouse. Idea is the following: click on an object > circle appears with draggable box > drag this box over the circle makes the object rotate.
It is kinda the same question as this one, but I have no clue how to do this in Easeljs.
To illustrate
Now you can rotate objects by clicking the buttons in the top right (L = left, R = right), but I want it to be like here:
Click + drag on white box will make it rotate
Help is much appreciated!
You have to add listeners to to the stage (or in your case, maybe the playing field Shape) for the mousedown, mousemove, and mouseup. In this example, I'm just listening to the global stagemouseup, stagemousedown, and stagemousemove events. I don't assign the stagemousemove listener until the stagemousedown is fired. I then remove it when the stagemouseup is fired.
For each stagemousemove event, you need to find the angle between your player and the stage mouse position. You can do this will the following formula where shape is your player:
var angleInRadians = Math.atan2(stage.mouseY - shape.y, stage.mouseX - shape.x);
var angleInDegrees = angleInRadians * (180 / Math.PI);
Then you simply set the shape.rotation = angleInDegrees.
Check out this working example.
Related
I have a 100 (width) x 100 (Height) canvas arranged in a row and column of 5 x 6
it has a triangle drawn on them currently the canvas are arranged in such a way that every canvas overlaps each other. i want to add click on the triangle area
is there a way to bypass click to the underlying canvas when the click is in transparent area of the top canvas
With EaselJS, you can use the nextStage property to pass CreateJS mouse interactions to canvases that are below one another in the DOM.
// Overlapping Canvases
<canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas>
// Multiple Stages
stage1 = new createjs.Stage("canvas1"),
stage2 = new createjs.Stage("canvas2");
// Mouse events on content in each stage
stage1child.on("click", handleClick);
stage2child.on("click", handleClick);
// Stage 2 is higher in the DOM, so it will receive the mouse events first.
// Pass them on to the lower canvas/stage
stage2.nextStage = stage1;
Here is more info:
nextStage documentation
TwoStages demo in GitHub
TwoStages demo on createjs.com
I didn't entirely understood your question, but if you just want for the click to register to the Canvas bellow the shape, then you need to disable the mouse interaction for the shape on top, like this:
triangleShape.mouseEnabled = false;
By doing so, any mouse events will be ignored for this shape and passed instead to the objects bellow it.
Here's the scenario.
A user selects an image, video, or other type of display object. It gets loaded inside a custom class known as EditableObject. The goal of EditableObject is re-sizing and re-positioning. EditableObject has 4 movieclips.
center_mc : Handles drag and drop and contains the display object.
rightside_mc : Handles re-sizing of width on mousedown
bottomside_mc : Handles re-sizing of height on mousedown
bottomright_mc : Handles scaling of object on mousedown
So far I can scale all parts of these objects. The bugs are what's causing trouble.
When I click down on the bottom or right side of the display object, the display object increases size from whichever side it's handling before I move the mouse. I get the amount to move based on the difference of the stageX and stageY positions of the mouse passed on MOUSE_DOWN and at the end of every MOUSE_MOVE. This isn't a problem, it just looks bad and currently solves the second bug..
When I handle bottomright_mc, I can only scale the object down. When trying to scale out, I have to position the mouse outside of EditableObject to get a difference greater than bottomright_mc's current position. This doesn't work because any attempts to exit the bounds of EditableObject trigger MOUSE_UP, even if I add the event listener using this.parent..
I want to be able to re-position and scale anything inside EditableObject using two sides and one corner of EditableObject when a mouse is held down and moved. Currently I can only move the object, scale the object less than its current size, and use the two sides to adjust the objects width and height but without having the mouse match the position of the side it's currently handling on initialization.
Here's an excerpt for the MOUSE_MOVE handler.
private function handleMouseMove(e:MouseEvent):void
{
switch(dragType)
{
case "right":
trace("Right triggered.");
this.width = e.stageX - this.x;
break;
case "bottom":
trace("Bottom triggered");
this.height = e.stageY - this.y;
break;
case "bottomright":
resizeMe(this, e.stageX - this.x, this.height);
break;
}
prevMouseX = e.stageX;
prevMouseY = e.stageY;
}
The full code for the class can be found here on pastebin.
Here's Editable Object in Adobe Flash CC
Here's EditableObject currently containing and handling an image inside the editor.
Based on this answer on stackoverflow provided by TOMATO in the comments, I found a great API that easily lets you handle DisplayObjects with just a few lines of code.
The one I have chosen is senocular's transform tool. A demonstration of his work can be found here. Broken down, this is how to use it.
//Constructor
var editTool:TransformTool = new TransformTool();
//Add to stage (This will not be visible until you give your TransformTool a target)
addChild(editTool);
desiredDisplayObject.addEventListener(MouseEvent.CLICK, handleMouseClick)
function handleMouseClick(e:MouseEvent):void
{
//Set the object clicked as the target for the TransformTool
editTool.target = e.target as Sprite;
//Swap the positioning in the display list so the TransformTool appears in front
editTool.parent.setChildIndex(editTool, editTool.parent.numChildren - 1);
}
You can do this a number of ways, but the basics of it is to simply add the transform tool to the stage and assign whatever display object you would like to the TransformTool.
I've a problem with ROLL_OVER event listener. When I enter the empty area withing the movieclip with mouse cursor, ROLL_OVER event triggers. But I want that event trigger only when mouse cursor is on the colored area.
To Make it more clear: Think about " O " letter, when mouse cursor is between the empty area of O letter (inside of O) , event shouldn't trigger. It should trigger only when mouse curser is on the black area.
How can I implement this?
Thanks
-Ozan
PROBLEM IS SOLVED THANKS TO #Ethan Kennerly
I just want to add a few things to help people have problem same as me. In my situation I tried to make continents glow when my mouse is over them. I used the ROLL_OVER/MOUSE_OVER eventlistener to check if my mouse is over them or not. But with the data given by Ethan Kennerly I produced another way.
In Ethan Kennerly's solution, if your mouse enters the area of continent from a transparent area , it doesn't get blur effect because ROLL_OVER and MOUSE_OVER event listeners only trigger once per enters so I used MOUSE_MOVE event listener on each continent movieclips.
And for this statement:
if (isPixelTransparent(DisplayObject(event.currentTarget), new Point(stage.mouseX, stage.mouseY)) {
return;
}
add whatever is in the "ROLL_OUT or MOUSE_OUT" eventlistener function, add all of them inside this statement. But don't remove ROLL_OUT or MOUSE_OUT functions.
It sounds like the movie clip contains a shape that has transparent pixels. Transparent pixels respond to mouse over and roll over. If you could draw vector graphics that have no shapes with transparent pixels, the mouse would ignore the empty space in the movie clip's bounding box.
Yet it sounds like you need to use transparent pixels and you want the mouse to ignore them, so you could guard, like this:
private function onRollOver(event:MouseEvent):void
{
if (isPixelTransparent(DisplayObject(event.currentTarget), new Point(stage.mouseX, stage.mouseY)) {
return;
}
// respond to roll over.
}
To detect transparency, Miguel Santirso rendered the pixels and translated the coordinate space here: http://sourcecookbook.com/en/recipes/97/check-if-a-pixel-is-transparent-in-a-displayobject (Except line 38 looks on my computer like "rect" got rendered as "ct"). You could optimize that code by only drawing the pixel in question, instead of the whole image, and checking if that pixel value (getPixel32) is 0, instead of calling a hitTest. I would optimize Miguel's code like this:
public static function isPixelTransparent(objectOnStage:DisplayObject, globalPoint:Point):Boolean
{
var local:Point = objectOnStage.globalToLocal(globalPoint);
var matrix:Matrix = new Matrix();
matrix.translate(-local.x, -local.y);
var data:BitmapData = new BitmapData(1, 1, true, 0x00000000);
data.draw(object, matrix);
return 0x00000000 == data.getPixel32(0, 0);
}
By the way, if all your movie clips would have the same hit test shape, you could create a separate transparent shape that listens to the roll over. I use a transparent shape to define a custom hit test shape that is a consistent and simple shape (like a circle) when the image is a more complicate shape (like an X or an O with nothing in the middle). The custom hit test shape is a Sprite with a transparent shape. The sprite listens to the roll over. A separate mouse listener shape is also useful if your movie clip, on later frames, creates new shapes that alter the silhouette of the movie clip.
The easiest solution would be using the Interactive PNG class by Moses.
http://blog.mosessupposes.com/?p=40
Normally the clear areas of a PNG are treated as solid, which can be especially frustrating when dealing with a lot of images that overlap each other because they tend to block mouse interactions on the clips below them.
This utility fixes that so that mouse events don't occur until you
bump against a solid pixel, or a pixel of any transparency value
besides totally clear. InteractivePNG lets you set an alphaTolerance
level to determine what transparency level will register as a hit.
I'm trying to follow this tutorial to create a homing missile in Flash, except I'd like to adapt it to use HTML5 canvas. I'm struggling with getting the sprite to face the direction of the mouse; it rotates but doesn't always face the mouse! I've put up a fiddle so you can see what's going on.
http://jsfiddle.net/Mr4Tz/
Any help would be greatly appreciated.
The angle value passed to the HTML5 rotate method should be in radians, but you are passing degrees instead.
Based on your example, this should work:
var targetX = mouse.x - missile.x
, targetY = mouse.y - missile.y
, rotation = Math.atan2(targetY, targetX);
context.rotate(rotation);
In writing an ActionScript 3 program, I am trying to make it so that I can drag an object from one location to another after doing some other stuff. The trouble is, I can drag just fine, but apparently I can't stop dragging, even with a listener to make it stop. I can't figure out any reason why this is happening. The relevant part of my code is as follows:
public function setToDragAndDrop(){
this.graphic.removeEventListener(MouseEvent.CLICK, rotate);
this.graphic.addEventListener(MouseEvent.MOUSE_DOWN, drag);
this.graphic.addEventListener(MouseEvent.MOUSE_UP, endDrag);
}
private function drag(e:MouseEvent):void{
trace("Dragging...");
this.graphic.startDrag(true);
trace(this.graphic.hasEventListener(MouseEvent.MOUSE_UP)); //Returns true
}
private function endDrag(e:MouseEvent):void{
trace("Stopped dragging.");
this.graphic.stopDrag();
}
I do not get the "Stopped dragging" line in my output, so the endDrag MouseEvent is never getting called, even though it exists (as the trace proves). So instead whether the mouse is up or down, it continues to drag. I've found that if I click on another draggable object, that one starts dragging instead.
I'm baffled. Any help would be greatly appreciated!
I figured out the problem. Apparently when you create the shape, it's "drag point" is at (0,0), or if you premake the shape in Flash, the upper left corner of the "rectangle" that surrounds the figure. When you click on the shape, your mouse jumps to this "drag point."
Apparently, if the drag point does not actually lie on the body of the shape, drag and drop doesn't work. So the ovals I was using earlier didn't work because the drag point was off the shape. Your example did work because it was created at (0,0) and your drag point was at (0,0). But if you draw a circle that isn't at (0,0), like drawCircle(200,200,100) (i.e. draw a circle at point (200,200) with a radius of 100), then you encounter the problem that I have because the drag point is not on the shape.
The solution then is to create the circle at 0,0, then move it to the position you want. It's strange, but I finally got it to work.
public function setToDragAndDrop(){
this.graphic.removeEventListener(MouseEvent.CLICK, rotate);
this.graphic.addEventListener(MouseEvent.MOUSE_DOWN, drag);
}
private function drag(e:MouseEvent):void{
this.graphic.startDrag(true);
this.graphic.removeEventListener(MouseEvent.MOUSE_DOWN, drag);
this.graphic.addEventListener(MouseEvent.MOUSE_UP, endDrag);
}
private function endDrag(e:MouseEvent):void{
this.graphic.stopDrag();
this.graphic.removeEventListener(MouseEvent.MOUSE_UP, endDrag);
this.graphic.addEventListener(MouseEvent.MOUSE_DOWN, drag);
}
it works very well here.
http://wonderfl.net/c/CvWO
Check the flash "fiddle" .