I'm creating my own drag and drop using canvas. In order to select the ball, I've created an invisible bounding box around it. Clicking in this area will allow you to drag the ball.
On mouse move, I'm using
xBall = xMouse;
yBall = yMouse;
So the ball will follow the mouse. This is great except at the very start of the drag, the center of the ball will jump to where the mouse is which I don't want. So I need to take into account the offset between the Mouse and Ball.
Can anyone explain the maths behind this? From my reasoning, I need to add the offset on to the mouse's position. So I get xBall = xMouse + (xBall - xMouse) but as you can see, this just ends up giving me xBall = xBall which is no use.
Where am I going wrong?
You need to determine where the initial click occured and the offset calculation should be carried out with respect to this initial coordinates.
On mouse down, store the initial clicked coordinates:
xInitial = xMouse;
yInitial = yMouse;
movingFlag = true;
On mouse move:
if (movingFlag) {
xBall = xBall + xMouse - xInitial;
yBall = yBall + yMouse - yInitial;
}
On mouse up :
movingFlag = false;
Related
I have a grid of cubes and I need to show a button while hovering over a row. I have created the button with a plane geometry but while setting is position.y such that it stands right on top of the row, it displaces along the z axis and appears against another row at the back giving the wrong appearance. Please see the code below for the button and also a screenshot of the issue. The white button should appear right on top of the orange row.
I have tried to do what this post talks about. But inspite of all that, I am unable to fix it. Not sure why making the object high enough should affect the depth. I have not added any translation or rotation to it. Please help.
function createButtonForEachRow(numCols, width, offsetX, rowIndex, cubeSize , cubePadding)
{
var geometry = new THREE.PlaneGeometry( width, 1);
var material = new THREE.MeshBasicMaterial( {map: buttonTexture, side:THREE.DoubleSide } );
material.map.minFilter = THREE.LinearFilter;
var plane = new THREE.Mesh(geometry, material);
var referenceZPos = 1- (rowIndex * (cubeSize + cubePadding));
plane.position.x = offsetX + cubeSize + cubePadding * numCols + 3 ;
plane.position.y = cubeSize*3;
plane.position.z = referenceZPos;
// plane.rotation.x = 3 * Math.PI/2;
plane.visible = false;
return plane;
}
Screenshot
Creating 2 scenes and adding the button on the second scene worked. The link mentioned in the question actually worked. I had forgotten to set autoclear to false.
I have a custom chart which I scale using the following code:
final double SCALE_DELTA = 1.1;
treePane.setOnScroll(new EventHandler<ScrollEvent>()
{
#Override
public void handle(ScrollEvent event)
{
event.consume();
if (event.getDeltaY() == 0)
{
return;
}
double scaleFactor = (event.getDeltaY() > 0) ? SCALE_DELTA : 1 / SCALE_DELTA;
treePane.setScaleX(treePane.getScaleX() * scaleFactor);
treePane.setScaleY(treePane.getScaleY() * scaleFactor);
}
});
I noticed that when I scroll the chart with mouse wheel I cannot zoom the chart where my mouse points. Instead of this the chart is zoomed to left or right for example.
I would like when I zoom with the mouse wheel to scale the chart where my cursor points. Is there any solution?
I haven't worked with javafx, but I will try to answer anyway. From my experience with Win32Api/GDI and XNA you should definitely be able to read mouse coordinates. Anything you display is displayed at coordinates x,y. When you want to scale and zoom to the cursor's location, you will redraw with this in mind: (assume zoom factor = z, mouseX and mouseY the mouse coordinates X and Y the new coordinates)
your cursor will have to point at the same pixel, so if the image is z times bigger now, so will the mouse coordinates be, relative to the source of the picture. To these coordinates, essentially the distance from the top and left of the image, you have to add the coordinates of the source itself, which should remain unchanged relative to the window's top-left corner. This eventually means that mouseX - X = (mouseX - x)*z, which means X = mouseX - (mouseX - x)*z
Same goes for the Y coordinate. In theory this should work perfectly, i have not tried it with code but it seems right on paper. You will notice X and Y seem to be getting smaller, essentially they might even turn out negative since by scaling and keeping the mouse on the same pixel, you push/stretch the top-left corner further up and left, possibly out of the screen.
You will probably work with the scrollbars though, same philosophy on their displacement.
Play around with the variables a bit to make them fit the drawing mode, I do not know if the libraries you are working with start from the screen's (0,0), or the window's, or the working areas, so you will have to adapt it to the rest of the code, but this is the math/geometry behind it.
I've got an issue that I simply can't figure out; probably because I don't have the correct knowledge.
I have a TMX map made in Tiled. The Map is bigger than the screen size (tiles are 32x32pixels and there are 100x100 tiles).
What I want to do is to be able to move the map by swiping the screen.
I've looked at various tutorials online and examined the paddle.m example but still can't get it to work.
All the tutorials I've come across all focus on moving a clamped centered sprite around a map...
Again, what I want to do is to be able to move the map by swiping/sliding the screen; much like when scrolling through your iPod or moving a picture around.
Can anyone help?
Here is my ccTouchMoved code
-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
CGPoint touchPointMap = [touch locationInView: [touch view]];
touchPointMap = [[CCDirector sharedDirector] convertToGL: touchPointMap];
touchPointMap = [self convertToNodeSpace: touchPointMap];
CCLOG(#"Touch Point Map %lf, %lf", touchPointMap.x, touchPointMap.y);
self.position = CGPointMake(touchPointMap.x, touchPointMap.y);
}
To illustrate the problem I'm seeing on screen when I swipe the screen using the code above:
It seems that if I touch the center of the screen, the bottom left corner of the map will jump to that touched coordinate and will move with my touch until my touch is lifted.
The Map's bottom left corner will always move to where I begin my touch.
Also while the map is being moved, it flashes like crazy and if moved excessively, disappears entirely.
Thanks again All, much appreciated.
Best and Kind Regards,
hiro
I found the solution to the problem.
There's a very bright person in the Cocos2D community who has written a controller to not only pan around organically, but zoom in and out.
Link to Controller, example and preview movie
You wont need to write your touchBegan, Moved and End methods; this Controller does it all for you.
My init
self.theMap = [CCTMXTiledMap tiledMapWithTMXFile: #"city_map.tmx"];
self.bgLayer = [theMap layerNamed:#"bg"];
// boundingRect is the area you wish to pan around
CGRect boundingRect = CGRectMake(0, 0, 32*50, 16*50);
theMap.anchorPoint = ccp(0,0);
[self addChild: theMap z: -1];
// _controller is declared in the #interface as an object of CCPanZoomController
_controller = [[CCPanZoomController controllerWithNode:self] retain];
_controller.boundingRect = boundingRect;
_controller.zoomOutLimit = _controller.optimalZoomOutLimit;
_controller.zoomInLimit = 2.0f;
[_controller enableWithTouchPriority:0 swallowsTouches:YES];
I've been having trouble creating a mechanism to allow the user to select a span of time from a timeline. Basically i want them to be able to click and drag horizontally, and retrieve the start and end positions of that event.
I especially need to include the case where the event goes off the edge of the screen (even if the end position is snapped to the edge of the screen that's fine).
While doing all of this, I want to be able to draw a box that goes from the start of the event to the current position of the mouse, so that it's obvious which area if being selected.
Basically, it doesn't seem to me that you're dragging something. You just have a sequence of press, move and release. You will have to click on something, I bet you could consider the press event on the timeline itself. So it'll be something like:
timeline.addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
timeline.addEventListener(MouseEvent.MOUSE_UP, onMouseUp);
// the next line just considers that leaving the object surface is the same as depressing the mouse button
timeline.addEventListener(MouseEvent.MOUSE_OUT, onMouseUp);
function onMouseDown(evt:MouseEvent):void {
// add the event listener for the mouse move action
timeline.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
// create the movie clip for the box
// you get the mouse coordinates from evt.localX and evt.localY (relative to the origin of the timeline movieclip) or evt.stageX and evt.stageY (as global values)
}
function onMouseMove(evt:MouseEvent):void {
// adjust the selection width and height
// you get the mouse coordinates from evt.localX and evt.localY (relative to the origin of the timeline movieclip) or evt.stageX and evt.stageY (as global values)
}
function onMouseUp(evt:MouseEvent):void {
// remove the event listener for the mouse move, that means that the function onMouseMove will no longer be called
timeline.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
// brush up and send the final coordinates of the selection to the next function
}
For the selection graphics itself, you can either use an instance of a movie clip from your library, or you could simply create an empty movie clip, make it semitransparent and draw a rectangle in it, like so:
var selection:MovieClip = new MovieClip();
selection.alpha = 0.5;
selection.graphics.beginFill(0x000000);
selection.graphics.drawRect(x,y,width,height);
selection.graphics.endFill();
this.addChild(selection);
I want to use javascript to detect the mouse position once the mousedown event has fired. It appears I am not getting an onmousemove event when the left button is held down. The cursor is changing to some circle with a cross through it.
My whole goal is to detect the start position of the cursor on mousedown and change the top left style of a image in a div with overflow set (kind of fake pan effect).
Thanks
Set up an ondragstart handler:
function dragstart(ev)
{
if (!ev) ev = window.event;
ev.returnValue = false;
return false;
}
image.ondragstart = dragstart;