Mouse click through top image - javascript

I created two shapes with image as source using createjs(img1 and img2 at same position but z index is different). one image is on top of another image i.e. img2 on img1 in canvas. and image below has click event i.e. img1 has click event which work fine. but when i enable img2(not having any click event) on img1 than mouse click event work through top image. if add click event to img2 than it work properly. is that compulsory to add click event to each image to avoid click through images.
CODE:
[function test(){
var btnContainer=new createjs.Container();
btnContainer.mouseChildren=true;
var shape = new createjs.Shape();
shape.graphics.clear().beginBitmapFill(loader.getResult("play-btn")).drawRect(0,0,291,98);//"no-repeat"
shape.x=shape.y=200;
shape.mouseEnabled =true;
shape.addEventListener("click", playClick);
var shape1 = new createjs.Shape();
shape1.graphics.clear().beginBitmapFill(loader.getResult("play-btn")).drawRect(0,0,291,98);//"no-repeat"
shape1.x=shape1.y=250;
shape1.mouseEnabled =true;
shape1.addEventListener("click", playClickShape1);
btnContainer.addChild(shape,shape1);
gameStage.AddChildWidget(btnContainer);
}
function playClick(event)
{
console.log("\[playClick\] Start");
ReadXMLFile();
}
function playClickShape1(event)
{
console.log("\[playClickShape1\] Start");
}

If some image is overlaying other content which as click handler, it won't be registered as the top one will be blocking clicks. It won't propagate clicks to the bottom of the site. Try adding pointer-events:none css rule to the top image that you don't want registering click events, and the one on the bottom should be clickable.

The answer from #Sebastian is correct for DOM elements (with the CSS solution).
If both images are bitmaps in Canvas (via EaselJS), then a similar limitation exists. Anything with a "click" event will block clicks on elements below. Unlike HTML though, if there is no mouse event on an element, it will not block mouse events (basically it has pointer-events:none by default.
If you want to determine if a click happened on any element (regardless of layering), you could listen for clicks on the stage, and use getObjectsUnderPoint() to determine what was clicked, and you could check if either (or both) were clicked that way.
stage.on("stagemouseup", function(event) {
var objs = stage.getObjectsUnderPoint(event.stageX, event.stageY);
for (var i=0, l=objs.length; i<l; i++) {
var obj = objs[i];
if (obj == firstElement || obj == secondElement) { doSomething(); break; }
}
);
Docs:
https://createjs.com/docs/easeljs/classes/Container.html#method_getObjectsUnderPoint

Related

Pixi js - need to make clickable background

I need to be able to click on background, and get the position of the click.
I tried adding an event listener to stage like this
app.stage.interactive = true;
app.stage.on('click', function(){
console.log('hello');
})
but it works only if i click on element inside the stage, not the background itself.
Do i need to make a sprite as a background, if so, how do i set its background color and make sure it stays under all the other elements?
The stage is a PIXI.Container, which means it's basically an empty node that can hold children. It doesn't have dimensions of its own, and so when the interaction manager goes to hit-test your click, it isn't detected.
Your suggestion of adding a background sprite is probably the simplest solution. You can add one like so:
// Create the background sprite with a basic white texture
let bg = new PIXI.Sprite(PIXI.Texture.WHITE);
// Set it to fill the screen
bg.width = app.screen.width;
bg.height = app.screen.height;
// Tint it to whatever color you want, here red
bg.tint = 0xff0000;
// Add a click handler
bg.interactive = true;
bg.on('click', function(){
console.log('hello');
});
// Add it to the stage as the first object
app.stage.addChild(bg);
// Now add anything else you want on your stage
...
PixiJS renders objects in order, so if you add your background sprite as the first child of the app's stage, it will be rendered behind all other content. When hit-testing a click, it will be the last object tested, and so will catch a click on the background of the stage. Note that to "block" clicks, other objects will need to be set to interactive = true, even if they don't have a click handler attached!
A possible solution would be to add an event on app's view.
app.renderer.view.addEventListener('click', function(e) {
console.log(e);
});

easeljs mouse events on disabled stage curosr

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.

Programmatic Event Trigger using Hammer.js

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/

Create custom mouse event

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!

How to stop the event bubble in easljs?

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.

Categories

Resources