Faking Mouse Interaction

So, basically what @MarkHunt is saying is:

3 Likes

:rofl: :rofl: :rofl:

One thing I just realised though is the OP wants to react to multiple elements intersection

:rofl: :joy: There’s a gif for everything!

Yes, ultimately I need multiple buttons, in different scenes, and not all butons will be the same. By “button” I mean various UI elements that can be interacted with, can be menu items that turn purple on hover and are underlined when selected, but don’t turn purple on hover in the selected state. Triggering dropdowns. etc, etc… Like a cat interacting with budgies in cages and mice and balls of wool? Same cat. Different interactions. Ideal scenario, is that once the code is set up, all I would need to do is animate the cursor (cat) and all the interactions will be triggered automatically / with minimal animation.

Thanks

Well, you could use the Matter-Collision detection built into Hype.

I was also thinking of using classes, changing them / adding / removing depending on the UI element

Here is collision detection using Matter.js in Hype. It just outputs the collision to the console:
rollover_matter.hype.zip (20,8 KB)

Given you don’t mind (mis)using the Physics engine like that.
Update: please redownload… wrong body in the output.

@gleb

I do not know the full extent of your intent with your project but from what I have read You might find using a “Custom Cursor” useful. You can be totally freeform with this approach and not constricted to using motion paths, etc.

Hype Doc: Custom Cursor.hype_JHSv1.zip (18.3 KB)

The cursor in this project uses a “.png” file to replace the standard cursors. Everything acts as normal as with a regular cursor - rollovers and interactions with elements. Then You can do a screen capture of your interaction with a project tutorial. It is a simple, tight set-up with creative possibilities.


Thanks @JimScott,

I did look at this approach too, but it won’t work for my purposes. I even looked at tools that can record your actual ouse movements and keyboard interactions and then play them back, so I could capture the same web tutorial in multiple languages (the website is served up in 12 languages). So my solution is to build a copy of the website’s main pages in Hype, and animate tutorial sequences within a totally controlled environment.

1 Like

Ah… that is what this for then maybe look at something like this:

https://www.rrweb.io/

Read the guide at https://github.com/rrweb-io/rrweb/blob/master/guide.md

Just use the form and then hit replay:
https://www.rrweb.io/demo/checkout-form

1 Like

Thanks @MaxZieb, really nice tool. Still want to try and do it in Hype. Going to be stubborn! Cheers

ButtonRolloverV2.hype.zip (31.5 KB)
Adding / removing classes and checking if a UI element contains class looks promising, but not sure about the logic. The position on the page clearly matters. The first Menu Item is triggered, the first button triggers change on the second button and the second button triggers change on the third button?

ButtonRolloverV2

var cursorTop  = hypeDocument.getElementProperty(cursor, 'top');
var cursorLeft = hypeDocument.getElementProperty(cursor, 'left');
var cursorBottom = hypeDocument.getElementProperty(cursor, 'top') + hypeDocument.getElementProperty(cursor, 'height');
var cursorRight = hypeDocument.getElementProperty(cursor, 'left') + hypeDocument.getElementProperty(cursor, 'width');


var UIElements = document.getElementsByClassName('UI');

for (var i = 0; i < UIElements.length; i++) {

var UI = document.getElementsByClassName('UI')[i];

var Button = document.getElementsByClassName('button')[i];
var Menu = document.getElementsByClassName('menu')[i];

var UITop = hypeDocument.getElementProperty(UI, 'top');
var UIBottom = hypeDocument.getElementProperty(UI, 'top') + hypeDocument.getElementProperty(UI, 'height');

var UILeft = hypeDocument.getElementProperty(UI, 'left');
var UIRight = hypeDocument.getElementProperty(UI, 'left') + hypeDocument.getElementProperty(UI, 'width');

var hit1 = (UIBottom > cursorTop) && (UITop < cursorBottom) && (UILeft < cursorLeft) && (UIRight > cursorLeft);
var hit2 = (UIBottom > cursorTop) && (UITop < cursorBottom) && (UILeft < cursorRight) && (UILeft > cursorLeft);


if (hit1 || hit2) {

if (UI.classList.contains("button") == true){

    Button.classList.add("buttonover");
    Button.classList.remove("buttonout");
	Button.innerHTML = "I'M IN!";
	
	} 

if (UI.classList.contains("menu") == true){
	
	Menu.classList.add("menuover");
    Menu.classList.remove("menuout");
 
    }

} else {

if (UI.classList.contains("button") == true){

	Button.classList.remove("buttonover");
	Button.classList.add("buttonout");
    Button.innerHTML = "OUT!!!";
    
    }
    
if (UI.classList.contains("menu") == true){
    
    Menu.classList.remove("menuover");
	Menu.classList.add("menuout");
 } 

}
}

Fixed it! Just had to do this:

var Button = document.getElementsByClassName('UI', 'button')[i];
var Menu = document.getElementsByClassName('UI', 'menu')[i];!

Added some FAKE CLICKS triggering different actions added to the additional HTML attributes of the buttons (class, text, animation).

ButtonRolloverV3

ButtonRolloverV3.hype.zip (40.5 KB)

4 Likes

HypeIntersectEnabler.hype.zip (20.0 KB)

I deleted some code from the drag-and-drop-enabler and the result should be a “HypeIntersectEnabler”.

Works without custom coding. When an intersection occurs or ends a Hype-custombehavior (defined by a data-attribute) will be triggered …

SetUp:
On a targetelement set two data-attributes:

data-intersect -> true
data-intersecttarget -> className of a sourceelement

On a sourceelement set a corresponding class and two data-attributes:

data-intersectcustombehavior -> name of a Hype-custombehavior to be triggered
data-intersectoffcustombehavior -> name of a Hype-custombehavior to be triggered

///////////////////
I may cleanup and refactor this to add some more features in the future.
Actually it’s done on lowest efford … :wink:
Hope it’ll work :slight_smile:

Thanks @h_classen, I tried the file, but couldn’t get it to work with multiple objects, so went back to the first approach. My idea is to set up onover, onout, onclick CSS styles and reference them through the Additional HTML Attributes, so everything is kept in the same place. I can also add Key and Value pairs to trigger Custom Behaviors.

I was getting really close, and then tried to simplify the code and it broke down, was working really well before, but there must be just the CLICK part in the wrong place now… Aaargh!

var cursorTop  = hypeDocument.getElementProperty(cursor, 'top');
var cursorLeft = hypeDocument.getElementProperty(cursor, 'left');
var cursorBottom = hypeDocument.getElementProperty(cursor, 'top') + hypeDocument.getElementProperty(cursor, 'height');
var cursorRight = hypeDocument.getElementProperty(cursor, 'left') + hypeDocument.getElementProperty(cursor, 'width');

var UIElements = document.getElementsByClassName('UI');

for (var i = 0; i < UIElements.length; i++) {

var UI = document.getElementsByClassName('UI')[i];

var UITop = hypeDocument.getElementProperty(UI, 'top');
var UIBottom = hypeDocument.getElementProperty(UI, 'top') + hypeDocument.getElementProperty(UI, 'height');

var UILeft = hypeDocument.getElementProperty(UI, 'left');
var UIRight = hypeDocument.getElementProperty(UI, 'left') + hypeDocument.getElementProperty(UI, 'width');

var hit1 = (UIBottom > cursorTop) && (UITop < cursorBottom) && (UILeft < cursorLeft) && (UIRight > cursorLeft);
var hit2 = (UIBottom > cursorTop) && (UITop < cursorBottom) && (UILeft < cursorRight) && (UILeft > cursorLeft);

//MY MOUSE ACTIONS
var myOver = UI.getAttribute('over');
var myOut = UI.getAttribute('out');
var myClick = UI.getAttribute('click');
var myAction = UI.getAttribute('action');

if (hit1 || hit2) {

    UI.classList.add(myOver);
    UI.classList.remove(myOut);	
}

if ((hit1 || hit2) && MyCursor.isPlayingTimelineNamed('click') == true) {


    UI.classList.add(myClick);
    UI.classList.remove(myOver);	
    UI.classList.remove(myOut);	

} else {

	UI.classList.remove(myOver);
	UI.classList.add(myOut);

} 
}

ButtonRolloverV4.hype.zip (38.1 KB)

Not gone through all you code.

But try not to use the actual id name as an object reference.

“var cursorTop = hypeDocument.getElementProperty(cursor, ‘top’);”

Where this may work you will run into issues like you have.

It is best to set up a var as a reference to the object/element, that way you always know what you are referencing.

The second thing is to interact with a symbols element properties you need to reference it’s element()

    var MyCursor = hypeDocument.getSymbolInstanceById('cursor'); // ref to cursor symbol instance
	var MyCursorElement = MyCursor.element(); // ref to cursor symbol instance's element
	
var cursorTop  = hypeDocument.getElementProperty(MyCursorElement, 'top');
var cursorLeft = hypeDocument.getElementProperty(MyCursorElement, 'left');
var cursorBottom = hypeDocument.getElementProperty(MyCursorElement, 'top') + hypeDocument.getElementProperty(cursor, 'height');
var cursorRight = hypeDocument.getElementProperty(MyCursorElement, 'left') + hypeDocument.getElementProperty(cursor, 'width');

Also in removing the original MyCursor you left it in below. You ran into errors of undefined

if ((hit1 || hit2) && MyCursor.isPlayingTimelineNamed('click') == true) {

No change needs to be done there though as we re reference it above.
This usage is correct as you are calling the symbol object and not it’s properties.

1 Like

Here is a followup to do intersection observering using Matter.js included in the Hype Runtime. It supports shapes and polygons.

hypeDocument.queryIntersections = function(sourceSelector, targetSelectors) {

	var sceneElm = document.getElementById(hypeDocument.currentSceneId());
	var sourceElm = sceneElm.querySelector(sourceSelector);

	var cursorBody = hypeDocument.getElementProperty(sourceElm, 'physics-body');
	if (cursorBody) {
		var trackElms = sceneElm.querySelectorAll(targetSelectors);
		var trackBodies = [];
		trackElms.forEach(function(elm){
			var elmBody = hypeDocument.getElementProperty(elm, 'physics-body');
			if (elmBody) {
				trackBodies.push(elmBody);
			} else {
				console.log('target '+elm.id+' must be static Physics enabled');
			}
		});
		var collisions = Matter.Query.collides(cursorBody, trackBodies);
		if (collisions.length) {
			return collisions.map(function(collision){
				var isB = sourceElm.id == collision.bodyB.elementId;
				return document.getElementById((isB? collision.bodyA : collision.bodyB).elementId);
			});
		}
	} else {
		console.log('sourceSelector must be static Physics enabled', elm);
	}
	return [];
}

You can then check if something (singular) is intersecting with other elements (plural) and use whatever you want to trigger the check (setInterval, Mutation Observer, requestAnimation frame etc.).

setInterval(function(){
	var intersectingElms = hypeDocument.queryIntersections('.cursor', '.obstacle');
	intersectingElms.forEach(function(elm){
		// do something with them
		console.log(elm);
	});
}, 200);

Only thing it needs the participants to be static Physics objects and inside the same scope (scene).

Download Example:
drag_intersection_matter.hype.zip (28,4 KB)

PS: Apart from having many solutions to a problem this thread is a testament to us all having free time on our hands. Hope everybody is doing fine! :v:

Update: 11. September 2020 … corrected the example and a small error in the detection.

4 Likes

Yes hope everyone is OK! And thanks for all the help and time! :beers:

HypeIntersectEnabler_test.hype.zip (21.0 KB)
this is the setup with multiple elements ... Hope it'll work

1 Like

i've got a four-days week now. to be honest, it's feeling fine somehow :wink:

3 Likes