Inside an object (created based on this tutorial), I have the following code. In this code, the lines:
event.target.x = evt.stageX;
event.target.y = evt.stageY;
are wrong. What should they be to access the mouse movement?:
(function() {
....
var p = createjs.extend(Card, createjs.Container);
p.setup = function() {
this.on("pressmove", this.handlePressMove);
....
p.handlePressMove = function (event) {
event.target.x = evt.stageX; //"Event" is wrong. So is "evt"
event.target.y = evt.stageY;
stage.setChildIndex(this, stage.getNumChildren()-1);
stage.update();
}
}
}());
Your code sample uses evt.stageX instead of event.stageX. All MouseEvents will have a stageX and stageY, which is the position the mouse was in when it fired the event. I think your code came from this tutorial which uses evt exlusively.
Additionally, MouseEvents have a rawX and rawY on pressMove events, which give you the x/y outside of the canvas element. There is no clientX or clientY on EaselJS MouseEvents.
Here is a quick sample using the stageX/stageY.
http://jsfiddle.net/lannymcnie/suva8vt3/
Snippet:
shape.on("pressmove", function(event) {
shape.x = event.stageX;
shape.y = event.stageY;
});
Related
Is there any difference between writing JS touch events for iPad vs. iPhone? I have read a ton of documentation and as far as I can tell it should work the same way for both.
I have a drag-and-drop game, basically you grab a coin from under the dragon and drag it over to your vault. The dragging works on iPad, but not on iPhone. I'm trying to figure out why.
The game, for reference: https://codeeverydamnday.com/projects/dragondrop/dragondrop.html
The JS, abridged to just the relevant code for this question (with comments for clarity):
var dragndrop = (function() {
var myX = "";
var myY = "";
// The coin's starting X and Y coordinate positions
var coin = "";
// The coin you start touching / dragging
function touchStart(e) {
e.preventDefault();
// Prevents default behavior of scrolling when you touch/drag on mobile
var coin = e.target;
var touch = e.touches[0];
var moveOffsetX = coin.offsetLeft - touch.pageX;
var moveOffsetY = coin.offsetTop - touch.pageY;
// Defines offset between left edge of coin and where you place your finger on it
coin.addEventListener('touchmove', function() {
var positionX = touch.pageX+moveOffsetX;
var positionY = touch.pageY+moveOffsetY;
// Defines the X-Y coordinates of wherever you stop dragging
coin.style.left = positionX + 'px';
coin.style.top = positionY + 'px';
// Updates the coin's X-Y coordinates with the new positions
}, false)
}
document.querySelector('body').addEventListener('touchstart', touchStart, false);
})();
If it helps, I am getting this console log error every time I click / tap on the iPad screen in the Chrome Dev Tools emulator:
[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive.
This error doesn't seem to prevent the dragging from working on iPad, but I'm not sure if it has anything to do with the dragging not working on mobile? I tried adding a few things to fix the error based on other Stack Overflow questions I saw (ex. adding touch-action: none; in my CSS, but the error persisted).
Anyone see anything wrong in my code? I would love to get this game playable on mobile, as that's how most people would access it!
The default value of the passive option is set to true for touch-start and touch-move events, and it being true means your function won't call preventDefault to disable scrolling.
Simply set the passive value to false to solve your issue.
var dragndrop = (function() {
var myX;
var myY;
var coin;
function touchStart(e) {
e.preventDefault();
coin = e.target;
const touch = e.touches[0];
const moveOffsetX = whichArt.offsetLeft - touch.pageX;
const moveOffsetY = whichArt.offsetTop - touch.pageY;
coin.addEventListener("touchmove", touchMove, { passive: false });
function touchMove(e) {
const touch = e.touches[0];
const positionX = touch.pageX + moveOffsetX;
const positionY = touch.pageY + moveOffsetY;
coin.style.left = `${positionX}px`;
coin.style.top = `${positionY}px`;
}
}
document.body.addEventListener('touchstart', touchStart, { passive: false });
})();
Edit
I looked at the code from the website you linked, and I realized that one reason the coin wasn't dragged was because of touch we were using and also because of the once option I passed to the touchmove event.
Whenever the touchmove event is used, we have to use the new touch to get the pageX and pageY positions on the screen, I decided to create a function for the touchmove event, because whenever the touchstart function is called, a new touchmove event is registered because of the anonymous function handler.
So creating and naming a function for it will prevent the same function from being added.
I want to simulate clicks on a canvas with javascript\jQuery for testing reasons, but I didn't find a solution. Here's my code:
var e = new jQuery.Event("click");
e.pageX = X[index];
e.pageY = Y[index];
$("#gamecanvas").trigger(e);
Is it possible to do that ?
For example this game (I searched randomly on the web) How can I click from JS\jQuery ?
It depends on the event's used on the canvas , whether it's a click , mousedown , .... etc
In the example you just mentioned , the lucn event uses two event :
One (mousemove) for calculating coordinate to get clientX and clientY
Second (mousedown) for lunching ball using last calculated coordinate
So your code should be like :
var mousemove = new jQuery.Event("mousemove");
mousemove.clientX = x;//passed valuue
mousemove.clientY =y;//passed valuue
var mousedown = new jQuery.Event("mousedown");
$("#canvas").trigger(mousemove);
$("#canvas").trigger(mousedown);
Here a pluncker where I created a script to luanch a ball with passed input coordinate or jus throw the ball in the basket directly :)
See here livePlunker
See url code plunker
Hope this will help :
This example may help you
$('#canvas_element').on("mousedown mouseup", function(e) {
$('#output').text($('#output').text() + (e.type + " event fired at coords: " + e.pageX + ", " + e.pageY));
});
x_coord = 1;
y_coord = 1;
var e = jQuery.Event( "mousedown", { pageX: x_coord, pageY: y_coord } );
$('#canvas_element').trigger(e);
// execute more code
var e = jQuery.Event( "mouseup", { pageX: 255, pageY: 255 } );
$('#canvas_element').trigger(e);
working link
This is because, pageX and pageY doesn't get the coordinates of the canvas, I had the same issue my self when trying to create a signature pad.
use this instead:
var e = new jQuery.Event("click");
//for IE, safari, opera, chrome
if(e.offsetX != null) {
e.offsetX= X[index];
e.offsetY= Y[index];
}
//for firefox
if(e.layerX!= null) {
e.layerX= X[index];
e.layery= Y[index];
}
$("#gamecanvas").trigger(e);
Without know you use case the documentation for jQuery tells me yes:
http://api.jquery.com/trigger/
Why you don't search by your self through the very well documented API for jquery?
I have a custom built fabric.js bundle with touch support. Now I can scale any object with the pinch-zoom gesture. The problem is the zoom is really really sensitive, I barely move my fingers and the object is hugely scaled.
I couldn't find much information in the documents about how I can change the sensitivity. I know Event.js is used to handle the touch events within fabric.js. Is there any way I can change this sensitivity?
Ok, I ended up implementing touch controls myself, this is the code I made. This code was placed on the added event of my custom fabric.js object.
////////////////////////////// Touch event handlers
// Add listener event for pinch-zoom
var bbScope = this;
var hammer = new Hammer.Manager(this.canvas.upperCanvasEl);
var pinch = new Hammer.Pinch();
hammer.add([pinch]);
hammer.on('pinch', function (ev) {
// Set the scale and render only if we have a valid pinch (inside the object)
if (bbScope._validPinch) {
bbScope.set('scaleX', ev.scale);
bbScope.set('scaleY', ev.scale);
bbScope.canvas.renderAll();
}
});
hammer.on('pinchend', function (ev) {
bbScope._validPinch = false;
});
hammer.on('pinchcancel', function (ev) {
bbScope._validPinch = false;
});
hammer.on('pinchstart', function (ev) {
// Convert mouse coordinates to canvas coordinates
ev.clientX = ev.center.x;
ev.clientY = ev.center.y;
// Check if the pinch was started inside this object
if (bbScope.canvas) {
var p = bbScope.canvas.getPointer(ev);
bbScope._validPinch = bbScope.containsPoint(p);
}
else {
bbScope._validPinch = false;
}
});
I'm trying to read the X coordinate of a mouse click on Fabric.js.
Here is my code. The console logs undefined every time.
var canvas = new fabric.Canvas('c1');
canvas.on('mouse:down', function(e){
getMouse(e);
});
function getMouse(e) {
console.log(e.clientX);
}
The best fix is this method
Implementation:
function getMouseCoords(event)
{
var pointer = canvas.getPointer(event.e);
var posX = pointer.x;
var posY = pointer.y;
console.log(posX+", "+posY); // Log to console
}
To get coordinates based on set width and height on the canvas itself, use layerX and layerY property.
canvas.on('mouse:move', function(options) {
console.log(options.e.layerX, options.e.layerY);
});
Try this,
function getMouse(e) {
console.log(e.e.clientX);
}
Demo
Updated, as canvas events takes the options as an argument not an event like,
canvas.on('mouse:down', function(options){
getMouse(options);// its not an event its options of your canvas object
});
function getMouse(options) {
console.log(options);// you can check all options here
console.log(options.e.clientX);
}
just use e.e.clientX
or
e.e.clientY
for getting positions
Maybe this will help:
//Convert To Local Point
function toLocalPoint(event, canvas) {
var offset = fabric.util.getElementOffset(canvas.lowerCanvasEl), localX = event.e.clientX - offset.left, localY = event.e.clientY - offset.top;
return new fabric.Point(localX, localY);
}
The code below draws a rectangle on every mouse move after the mouse button is pressed. When the user releases the mouse it should stop drawing.
I am trying to figure out how to make sure that drawing stops if the user releases the mouse outside the canvas element.
I thought that I could accomplish this by setting onmouseup event handler on my event inside onmousedown like this:
canvas.onmousedown = function (e) {
drawing = true;
e.onmouseup = function (v) { drawing = false; }
};
but it did not work because e.onmouseup is never called. So I ended up setting window.onmouseup instead.
Questions:
why was my e.onmouseup never called?
is my final solution the best way to do it?
<!DOCTYPE HTML>
<html lang="en">
<head>
<meta charset="utf-8" />
<script type="text/javascript">
drawing = false;
function on_load(e) {
var canvas = document.getElementById("canvas");
canvas.onmousedown = function (e) { drawing = true; };
canvas.onmousemove = function (e) {
if (drawing)
{
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
var context = canvas.getContext("2d");
context.strokeRect(x, y, 10, 10);
}
};
window.onmouseup = function (e) { drawing = false; };
}
</script>
</head>
<body onload="on_load()">
<canvas id="canvas" width="500" height="500" style="border: 1px solid black;">
</canvas>
</body>
</html>
Why was my e.onmouseup never called?
e is an Event object. It doesn't have a defined behaviour for an onmouseup property
2. Is my final solution the best way to do it?
Yes, but with some adjustments. First, consider if you really need the global variable. The same effect can be achieved without the global variable, but it might useful to keep it global for debugging purposes.
Second, your not-working code is not needed. It's better to have one always-existing event listener which only changes a harmless variable, than constructing a new event listener for each mouseup event. Besides, in your "wanted" code, the previous mouseup event is never explicitly removed.
function on_load(e) {
var drawing = false; // <-- Always declare variables
var canvas = document.getElementById("canvas");
canvas.onmousedown = function (e) { drawing = true; };
canvas.onmousemove = function (e) {
if (drawing) {
var x = e.pageX - canvas.offsetLeft;
var y = e.pageY - canvas.offsetTop;
var context = canvas.getContext("2d");
context.strokeRect(x, y, 10, 10);
}
};
window.onmouseup = function (e) { drawing = false; };
}
How can an OS guarantee anything like a balanced mouse down/up in some widget. Then if you get it working on OS/browser 'X' how do you know that OS/browser 'i' or OS/browser 'W' will all work the same way? There are a lot of reasons why you need to do something else, like even a timer. Likely the overhead of a timer would be small compared to what you want to do.
You may want to consider an onmouseout handler to stop drawing when the mouse leaves your element.