I have a mousedown event listener on stage and a mousedown event listener on a shape.when I click on the shape, the mousedown event listener on stage will also fire? How to solve this?
var stage = new createjs.Stage("test");
stage.addEventListener('stagemousedown',mouseDown);
var shape = new createjs.Shape();
shape.graphics.beginStroke("#000").setStrokeStyle(8,"round").drawRect(0, 0, 100, 100);
shape.addEventListener('mousedown',smouseDown);
stage.addChild(shape);
The stagemousedown event is a special event to always capture stage mouse interaction, regardless of what is clicked. If you would like to ONLY receive that event when a child on the stage is not clicked there are other approaches.
One suggestion would be to add a stage-level child that is the size of the stage, and listen for mouse events on it. You can then check the target to see what was clicked (or not clicked)
var stage = new createjs.Stage("canvas");
var bg = new createjs.Shape();
bg.graphics.f("#ddd").dr(0,0,550,400);
var shape = new createjs.Shape().set({x:200,y:200});
shape.graphics.f("#f00").dc(0,0,100);
stage.addChild(bg, shape);
stage.update();
stage.addEventListener("mousedown", function(event){
if (event.target == bg) {
console.log("Missed Content");
} else {
console.log("Hit Content");
}
});
this is one of the ways to remove the shape object in the stage.
stage.removeChild(shape);
you can put that in a function and just call it when you want to remove the object.
please let me know if that is what you need.
There is maybe a better way, but you could check if there is no object under the mouse when you catch the "stagemousedown" event :
function mouseDown(event) {
if (stage.getObjectUnderPoint(event.stageX,event.stageY) == null) {
// ...
}
}
I think what you're looking for is stage.mouseEnabled = false:
Indicates whether to include this object when running mouse
interactions. Setting this to false for children of a Container will
cause events on the Container to not fire when that child is clicked.
Setting this property to false does not prevent the
getObjectsUnderPoint method from returning the child.
However, from the docs:
Note: In EaselJS 0.7.0, the mouseEnabled property will not work
properly with nested Containers. Please check out the latest NEXT
version in GitHub for an updated version with this issue resolved. The
fix will be provided in the next release of EaselJS.
Related
I want to disable the click on an entity after it's been clicked once by the raycaster. The entity opens up a panel so I don't want it to show more than once
This really depends whether or not you're using raycaster="objects: ...;". This is usually the recommended approach so your raycaster isn't interacting with every entity in the scene causing a drop in performance.
This can be done many ways, but one of the most common is to use a class selector like .clickable and then remove that class upon click. Then remove the event listener if it is no longer needed.
Cursor Raycaster:
<a-cursor raycaster="objects: .clickable;"></a-cursor>
Component:
AFRAME.registerComponent('click-once', {
init: function () {
var self = this;
var scene = self.el.sceneEl;
var raycaster = scene.querySelector('[cursor]').components.raycaster;
// Define function to be executed on click.
var clickHandler = function (e) {
// Log clicks.
console.log('clicked');
// Remove "clickable" class from entity.
self.el.classList.remove('clickable');
// Refresh raycaster object list to reflect changes.
raycaster.refreshObjects();
// Remove event listener since no longer needed.
self.el.removeEventListener('click', clickHandler);
};
// Add event listener for click.
self.el.addEventListener('click', clickHandler);
}
});
EDIT: This can be simplified even further if data-xxxx attributes or components are used as selectors, rather than classes/ids. E.g.: data-clickable
By default, A-Frame's raycaster automatically refreshes when entities and attributes/components (not classes) are added/removed, so there is no need to use raycaster.refreshObjects() in this case. https://aframe.io/docs/master/components/raycaster.html#properties_autorefresh
HTML:
<a-entity cursor raycaster="objects: [data-clickable];"></a-entity>
JS:
self.el.removeAttribute('data-clickable');
Demo of the code in action: https://codepen.io/dansinni/pen/MGKGZq
EDIT: If you are using <a-cursor> rather than <a-entity cursor="...", then you may need to use the following var raycaster assignment:
var raycaster = scene.querySelector('a-cursor').components.raycaster;
Or, if you are attaching the raycaster component explicitly:
var raycaster = scene.querySelector('[raycaster]').components.raycaster;
Hope this helps.
In my simple application i need to hide original cursor stage.cursor = 'none'; stage.enableMouseOver(), than i replace it with my own image
Than i register listener on stagemousemove event:
myBitmap.x = stage.mouseX;
myBitmap.y = stage.mouseY;
After this action i loose access to listen mouse events on other stage objects:
//nothing happen on mouse over
someBitmap.on('mouseover', function() { console.log(1) });
Is there any possible solutions, expect check every time hitTests on my objects inside stage mouse events?
Fixed by setting up cursor: none in my css rules and removing stage.cursor = 'none'from js. Thanks #Andew for example.
I am finding it very difficult to create programmatic events using Hammer.js. What I would like is to have two elements, when element one is tapped, I would like to fire or trigger or emit an event on the second element as well.
My end goal is to use this technique when dragging items. Basically, hold down on an element to create a clone of it, and then emit the drag event on the clone. This would stop dragging the original element and start the drag on the new cloned element.
With that said, I've created a simple jsFiddle http://jsfiddle.net/vk3reu0w/1/. It has two div elements. What I am trying to do is have div one be tapped and an event automatically fire a tap event on div two.
var buttonOne = document.getElementById("one");
var buttonTwo = document.getElementById("two");
var mc1 = Hammer(buttonOne);
var mc2 = Hammer(buttonTwo);
mc1.on("tap", function(event) {
alert("MC1 Tapped");
console.log("MC1 Tapped");
mc2.emit("tap");
});
mc2.on("tap", function(event) {
alert("MC2 Tapped");
console.log("MC2 Tapped");
});
Any help is much appreciated. Thanks.
You should add to .emit method a second param.
mc1.on("tap", function(event) {
alert("MC1 Tapped");
console.log("MC1 Tapped");
mc2.emit("tap", event); // HERE
});
http://jsfiddle.net/Lnvgcupg/1/
You can custom your event as well.
mc1.on("tap", function(event) {
console.log("MC1 Tapped");
var customEvent = JSON.parse(JSON.stringify(event)); // Creating
customEvent.center.x = 999; // ...changing something
mc2.emit("tap", customEvent); // Emitting
});
http://jsfiddle.net/ntgrdq7n/3/
I need to handle a zoom event in Open Layers 3.
The following is my code:
map_object = new ol.Map({
target: 'map',
controls: controls_list,
interactions: interactions_list,
overlays: [overlay],
layers: [OSM_raster, WFS_layer],
view: view
});
map_object.on("Zoom", function() {
console.log('Zooming...');
});
This code runs with no errors and shows a map, but there is no output to the console, suggesting this function isn't firing.
I have also tried:
map_object.on("drag", function() {
console.log('Dragging...');
});
And this too does nothing.
Any help as to how to handle map control events in OL3 would be much appreciated (particularly zooming!). Note I have tried 'zoom' as well as 'Zoom' for the type field of the on method.
Just to add to this, you can check variations of events available with 'propertychange', from what I am seeing, there is no explicit .on ('zoom', ...) but rather you can access 'resolution' and other properties as mentioned in previous comments:
map.getView().on('propertychange', function(e) {
switch (e.key) {
case 'resolution':
console.log(e.oldValue);
break;
}
});
try with moveend event. (see https://openlayers.org/en/latest/apidoc/module-ol_MapEvent-MapEvent.html#event:moveend).
As mentioned by tonio, the way to listen on zoom change, which is called resolution change in openlayers terminology, is with
map.getView().on('change:resolution', (event) => {
console.log(event);
});
I find this is better (more succinct, less cruft) than listening on the general propertychange and verifying manually if the change concerns resolution.
This fires rapidly when using the mouse button so throttling it might be a good idea before launching any computation that waits for it to change.
Documentation for View
You can manage the moveend event...
We will need a global variable to alocate map’s view zoom level. I’ve
named it as currentZoomLevel.
There is available a moveend event. Let’s use it, and add a zoom level
check function..
In case of there’s a new zoom level, we trigger a zoomend event to
DOM’s document.
Finally we will need to add zoomend listener to the document element.
var = currentZoomLevel;
map.on('moveend', checknewzoom);
function checknewzoom(evt)
{
var newZoomLevel = map.getView().getZoom();
if (newZoomLevel != currentZoomLevel)
{
currentZoomLevel = newZoomLevel;
$(document).trigger("zoomend", zoomend_event);
}
}
$(document).on('zoomend', function () {
console.log("Zoom");
//Your code here
});
Source
I'm working on a card game. I have a CardSet (custom Container object) that contains Cards (custom Container objects). I'd like to create custom events like: cardMouseOver and cardMouseOut so that I can listen to these card events like this:
cardSet.on('cardMouseOver', function(event) { set the event.card highlighted or anything );
cardSet.on('cardMouseOut', function(event) { set the event.card back to normal );
In the init block of the CardSet I added listeners to each cards:
card[i].on('mouseover', function (event) {
var evt = new createjs.Event('cardMouseOver');
evt.card = event.target;
this.dispatchEvent(evt);
});
The issue is when I move the mouse over the card it fires the over and out events right after each other. If I move the mouse it keeps firing these event like a mousemove. Any idea? Please ask if I wasn't clear enough. Thanks!