how do i accurately track mouse movement on a window? - javascript

Right now i am working on a way to update the state of an element based on IF the mouse is down as well as if the mouse is over the element. This means that once the mouse is down, every time it hovers over one of the elements , the state changes.The tracking is inaccurate, it does not capture every single action. How do i better the process?
The code for my present implmentation is:
document.onmousedown = () => {
document.onmousemove = (e) => {
if (e.buttons === 1) {
let svg = e.target as HTMLElement;
if (svg.id.startsWith('svg')) {
let SVG_ID = svg.id;
let HoverPropsID = svg.id.replace('svg', 'props');
if (document.getElementById(HoverPropsID).classList.contains('no-node')) {
toRemove.forEach(element => document.getElementById(SVG_ID).classList.remove(element));
document.getElementById(SVG_ID).classList.add(`svg-${node}`);
document.getElementById(HoverPropsID).classList.remove('no-node');
document.getElementById(HoverPropsID).classList.add(node);
multiNodeGraphUpdate(node, Number(HoverPropsID.substring(HoverPropsID.lastIndexOf('-') + 1)), 10, false)
}
nodeHoverAnimation(HoverPropsID);
}
}
}
I understand that the information i have provided might be a big ambiguous, so i am linking two website, one is the inspiration website: https://clementmihailescu.github.io/Pathfinding-Visualizer/
and the other one is the WiP webiste (my one):https://aarnavv.github.io/Vagus/

Related

Phaser3 framework javascript: current anims index

In phaser 3 framework, what syntax do I use to check the current frame index?
I want to make a hit area appear only when the player's sprite sheet reaches a certain index(the index displaying the motion of 'attack'). I want to accomplish this through detecting its current frame index.
How can I do this?
You could use the sprite events like: Phaser.Animations.Events.ANIMATION_UPDATE, details in official phaser documenation
player.on(Phaser.Animations.Events.ANIMATION_UPDATE, function (anim, frame, gameObject, frameKey) {
// Here you can check for the specific-frame
if(frameKey == "show_hit_area_frame"){
// ... show hitarea
}
// alternatively: with the index of the frame
if(frame.index == 7){
// ... show hitarea
}
});
In this selected Event, you can also check the current frame, for other properties of the frame object (details in official documenation), if you don't know/have the specific framekey/index.
The solution is found.
//hitbox solution: https://newdocs.phaser.io/docs/3.52.0/Phaser.Animations.Events.ANIMATION_COMPLETE_KEY
//hitboxB listener
gameState.playerB.on('animationstart-kill', function () {
console.log("finish kill <3")
gameState.hitBoxB.x = gameState.playerB.flipX ? gameState.playerB.x + 120 : gameState.playerB.x - 120;
gameState.hitBoxB.y = gameState.playerB.y;
// gameState.hitBoxB.visible = true;
})
gameState.playerB.on('animationcomplete-kill', function () {
console.log("kill <3")
gameState.hitBoxB.x =0 ;
gameState.hitBoxB.y = 0;
// gameState.hitBoxB.visible = false;
})

Mousedown won't change property and run function on range sliders

I've got two sets of range sliders on a video file that need some fine-tuning.
Clicking and dragging the slider will adjust the settings. But clicking without dragging will not change the settings, it will only move the slider.
I need the slider to adjust the settings when any point is clicked within the range. In the words, if the range is currently set to the far right and I click the far left, I'd like it to change settings.
I tested it and noticed that the line with the comment doesn't seem to activate the function handleRangeUpdate.
const ranges = player.querySelectorAll(".player__slider");
let isDragging = false;
function handleRangeUpdate() {
if (!isDragging) return;
console.log(`${this.name}: ${this.value}`);
video[this.name] = this.value;
}
ranges.forEach(range => range.addEventListener("mousemove", handleRangeUpdate));
ranges.forEach(range =>
range.addEventListener("mousedown", () => {
isDragging = true;
handleRangeUpdate; // This doesn't seem to function
})
);
ranges.forEach(range =>
range.addEventListener("mouseup", () => (isDragging = false))
);
You can find all my code on: My Github Repo

Changing All Icons Rotating Down to One

I currently have a giant table of "auditpoints", some of those points are "automated". If they are automated they receive a gear icon in their row. The gear icon is not the only icon each row receives. Each row, no matter if it's automated or not receives two other icons, a pencil and a toggle button. When an automated point "runs" the gear icon rotates until it is finished "running". I've have implemented some code to ran all of these points at once but I have a small problem. When you click my button to run all these points all three of the icons I have mentioned rotate and this is not the result I am looking for. The line commented out in my code snippet (and it's matching bracket) will prevent the code from running all of the automated points. Commenting out the line is what causes all the icons to rotate. I know this line is required to get the automated points to run properly as it used in the single execution of automated points I just don't know what to change it to. It obviously shouldn't be click because you are no longer clicking the gear icon to get a point to run I just don't know what to change it to but the classes in that click function are related to the gear icon.
Hopefully this is a very easy question to solve and doesn't waste anyone's time. Thank you!
private updateAuto() {
var self = this;
$(".auditPointRow").each(function () {
//self.el.on("click", ".update, .edit", function () {
var row = $(this).closest(".auditPointRow");
var id = row.data("id");
var automated = (<string>row.data("automated")).toLowerCase() == "true";
var running = true;
if (automated && $(this).closest(".edit").length == 0) {
var gear = $(this).find(".fa");
var maxTurns = 120;
gear.css("transition", "transform linear " + maxTurns * 2 + "s");
gear.css("transform", "rotate(" + (maxTurns * 360) + "deg)");
var request = $.ajax(self.root + "api/sites/" + self.site.ID + "/auditpoints/" + id, {
"type": "PATCH", data: JSON.stringify([
{
Op: "Replace"
, Path: "/score"
, Value: "run"
}
])
});
request.done(function () {
gear.css("transition", "").css("transform", "rotate(0deg)");
row.prev().find("td").css("background-color", "");
if (row.prev().qtip("api")) {
row.prev().qtip("api").destroy(true);
}
});
}
//}
});
}
I think I found a solution to my problem. I used .each again to go through all of the "gears" and only rotate them.
private updateAuto() {
var self = this;
//$(".auditPointRow").each(function () {
$(".update, .edit").each(function () {
//Left out the rest of the code so this answer isn't too
//long, none of it changed if that matters.
});
//});
}
For some reason the result runs very slowly (but it runs!) and I'm not sure why so if anyone has any better suggestion/optimizations please feel free to leave those here.
Edit: I realized I didn't to go through .each twice, that's what was slowing to down so I removed that first each that went over auditPoints and just did the ones with gears instead.

rotate a globe with the mouse

I can determine where on a globe the user has clicked.
When the user first clicks the mouse button down, I can store where they have clicked; lets call it the pin.
Then, as they drag the mouse around, I want to put the pin under the mouse cursor.
Here is some code that seems to roughly keep the pin under the mouse pointer, but doesn't correctly maintain the globe; it flickers and spins randomly. Sometimes it flips the axis entirely so the globe is momentarily back-to-front.
function evtPos(evt) {
if(!scene.ortho) return null;
var x = lerp(scene.ortho[0],scene.ortho[1],evt.clientX/canvas.width),
y = lerp(scene.ortho[3],scene.ortho[2],evt.clientY/canvas.height), // flipped
sqrd = x*x+y*y;
return (sqrd > 1)?
null:
mat4_vec3_multiply(mat4_inverse(scene.mvMatrix),[x,y,Math.sqrt(1-sqrd)]);
}
function onMouseDown(evt) {
pin = evtPos(evt);
}
function onMouseMove(evt,keys,isMouseDown) {
if(!isMouseDown) return;
var pt = evtPos(evt);
if(pin == null) pin = pt;
if(pt == null) return;
var d = vec3_sub(pt,pin),
rotx = Math.atan2(d[1],d[2]),
roty = (d[2] >= 0)?
-Math.atan2(d[0] * Math.cos(rotx),d[2]):
Math.atan2(d[0] * Math.cos(rotx),-d[2]),
rotz = Math.atan2(Math.cos(rotx),Math.sin(rotx)*Math.sin(roty));
scene.mvMatrix = mat4_multiply(scene.mvMatrix,mat4_rotation(rotx,[1,0,0]));
scene.mvMatrix = mat4_multiply(scene.mvMatrix,mat4_rotation(roty,[0,1,0]));
scene.mvMatrix = mat4_multiply(scene.mvMatrix,mat4_rotation(rotz,[0,0,1]));
}
function onMouseUp(evt) {
pin = null;
}
Also, over time, an error seems to build up and the pin drifts further and further from the mouse pointer. I presume I should somehow compute the mvMatrix completely rather than by lots of samll increments each event?
I want the user to be able to drag the globe around to navigate naturally. All code to spin globes that I've found uses fixed speeds e.g. arrow keys, rather than 'pinning' the globe under a mouse pointer. Unity has a function Quaternion.FromToRotation(fromPos,toPos) which seems very promising but the source is not available.
One of the approaches for doing this is the arcBall algorithm. There are even JavaScript implementations available so you don't need to roll your own.

Easeljs sprite animation stuck on frame

I'm learning javascript by using the easeljs library to make a simple game, for school lessons.
I want to make a crosshair give some feedback to the player by showing a small animation while you are pointing at your target, using a hittest I made.
However, when the crosshair touches the target, the animation (should be two little triangles pointing to the middle of the crosshair) seems to be stuck on it's first frame.
Here is a bit of my code, I put both of these functions inside a ticker function. The functions do what they're supposed to do (I checked by sending a message to the console.log), but I think the animation is reset as soon as the variable "hitTestControle" is set to true, at every tick.
If you want to check out all of the code, here is a link to the "game":
http://athena.fhict.nl/users/i279907/achtergrond/achtergrond.html
function hitTest() {
if(distance(crossHair, block) < 60) {
hitTestControle = true;
} else {
hitTestControle = false;
console.log(hitTestControle);
}
}
function hitTestControl() {
if(hitTestControle == true) {
crossHair.gotoAndPlay("move");
console.log("hit");
} else {
crossHair.gotoAndPlay("stop");
}
}
PS: There also seems to be something wrong with this hittest I used.
function distance() {
var difx = blok.x - crossHair.x;
var dify = blok.y - crossHair.y;
return Math.sqrt( (difx * difx) + (dify * dify) );
}
It looks like you're starting the animation... setting it to the first frame and starting it... every time hitTestControle is true. Since hitTestControle will be true as long as you're hovering over the target, the animation will never reach the second frame.
What you need to do is start the animation when you transition from hitTestControle = false to hitTestControle = true, but once that happens you just let it play automatically.
Try changing your hitTestControl() function to something like this:
function hitTestControl() {
if(hitTestControle == true && alreadyOverHit == false) {
crossHair.gotoAndPlay("move");
alreadyOverHit = true;
console.log("hit");
} else {
crossHair.gotoAndPlay("stop");
alreadyOverHit = false;
}
}
In other words, only start the animation once, during the first frame you're detecting a hit, and then don't touch it unless you move off the target and back on.

Categories

Resources