detect mouse position over image - javascript

On an image (slideshow) I would like to detect on which side the courser is placed. e.g the left-half side of the image or the right-half side of the image. I would like to show an arrow (left and right) when the user is mouseover the image and depending on the location I will show the right or the left arrow. I just need to know how to achieve the detection of the mousemove over the image. Thanks!

Use event onmouseenter and onmouseleave in img tag or div tag (you can divide two areas left-right in slideshow)
For example:
<img onmouseenter="showArrow(position)" onmouseleave="hideArrow(position)" src="">
onmouseenter when the mouse pointer onto an image
onmouseleave when the mouse pointer out of an image

var imageElement = document.querySelector('.imageElement');
var arrowsElemennt = document.querySelector('.arrowsElement');
var setStatusForArrows = function(status){return function(){arrowsElement.style.display = status}};
imageElement.addEventListener('mouseover',setStatusForArrows('block'));
imageElement.addEventListener('mouseout', setStatusForArrows('none'));

This is some code that is able to detect the relative cursor position over an image. You could repurpose this to show/hide your arrow icons based on its return value (instead of the console.log).
Added mouseout listener for auto-hiding arrows.
const img = document.getElementById('imageTest');
const [imgRects] = img.getClientRects();
// let showLeftArrow = false;
// let showRightArrow = false;
img.addEventListener('mouseover', evt => {
const distanceLeft = Math.abs(evt.clientX - imgRects.left);
const distanceRight = Math.abs(evt.clientX - imgRects.right);
if (distanceLeft < distanceRight) {
// showLeftArrow = true;
// showRightArrow = false;
console.log('left');
} else {
// showLeftArrow = false;
// showRightArrow = true;
console.log('right');
}
});
/*
img.addEventListener('mouseout', () => {
showLeftArrow = false;
showRightArrow = false;
})
*/
<img id="imageTest" src="https://vuejs.org/images/logo.png" style="height:30px;width:30px" />

Related

JS-based hidden image breaks body width and height

I use a Zoom JavaScript for zoom my images when I click on it.
This JavaScript creates a hidden copy of my image with bigger dimensions.
Problem is, when I load my page, the body takes a height and width according to the hidden image.
You can see at the right of the screen the menu doesn't fit with the width of the screen (the hidden image is not displayed).
Is there a solution when I load the page, the size of the body does not take into account the hidden image?
// To achieve this effect we're creating a copy of the image and scaling it up. Next we'll pull the x and y coordinates of the mouse on the original image. Then we translate the big image so that the points we are looking at match up. Finally we create a mask to display the piece of the image that we're interested in.
let settings = {
'magnification': 3,
'maskSize': 200
}
// Once our images have loaded let's create the zoom
window.addEventListener("load", () => {
// find all the images
let images = document.querySelectorAll('.image-zoom-available');
// querySelectorAll produces an array of images that we pull out one by one and create a Zoombini for
Array.prototype.forEach.call(images, (image) => {
new Zoombini(image);
});
});
// A Zoombini (or whatever you want to call it), is a class that takes an image input and adds the zoomable functionality to it. Let's take a look inside at what it does.
class Zoombini {
// When we create a new Zoombini we run this function; it's called the constructor and you can see it taking our image in from above
constructor(targetImage) {
// We don't want the Zoombini to forget about it's image, so let's save that info
this.image = targetImage;
// The Zoombini isActive after it has opened up
this.isActive = false;
// But as it hasn't been used yet it's maskSize will be 0
this.maskSize = 0;
// And we have to start it's coordinates somewhere, they may as well be (0,0)
this.mousex = this.mousey = 0;
// Now we're set up let's build the necessary compoonents
// First let's clone our original image, I'm going to call it imageZoom and save it our Zoombini
this.imageZoom = this.image.cloneNode();
// And pop it next to the image target
this.image.parentNode.insertBefore(this.imageZoom, this.image);
// Make the zoom image that we'll crop float above it's original sibling
this.imageZoom.style.zIndex = 1;
// We don't want to be able to touch it though, we want to reach whats underneat
this.imageZoom.style.pointerEvents = "none";
// And so we can translate it let's make it absolute
this.imageZoom.style.position = "absolute";
// Now let's scale up our enlarged image and add an event listener so that it resizes whenever the size of the window changes
this.resizeImageZoom();
window.addEventListener("resize", this.resizeImageZoom.bind(this), false);
// Now that we're finishing the constructor we need to addeventlisteners so we can interact with it
// This function is just below, but still exists within our Zoombini
this.UI();
// Finally we'll apply an initial mask at default settings to hide this image
this.drawMask();
}
// resizeImageZoom resizes the enlarged image
resizeImageZoom() {
// So let's scale up this version
this.imageZoom.style.width = this.image.getBoundingClientRect().width * settings.magnification + 'px';
this.imageZoom.style.height = "unset"
}
// This could be inside the constructor but it's nicer on it's own I think
UI() {
this.image.addEventListener('mousemove', (event) => {
// When we move our mouse the x and y coordinates from the event
// We subtract the left and top coordinates so that we get the (x,y) coordinates of the actualy image, where (0,0) would be the top left
this.mousex = event.clientX - this.image.getBoundingClientRect().left;
this.mousey = event.clientY - this.image.getBoundingClientRect().top;
// if we're not active then don't display anything
if (!this.isActive) return;
// The drawMask() function below displays our the portion of the image that we're interested in
this.drawMask();
});
// When they mousedown we open up our mask
this.image.addEventListener('mousedown', () => {
// But it can be opening or closing, so let's pass in that information
this.isExpanding = true;
// To do that we start the maskSizer function, which calls itself until it reaches full size
this.maskSizer();
// And hide our cursor (we know where it is)
this.image.classList.add('is-active');
});
// if the mouse is released, close the mask
this.image.addEventListener('mouseup', () => {
// if it's not expanding, it's closing
this.isExpanding = false;
// if the mask has already expanded we'll need to start another maskSizer to shrink it. We don't run the maskSizer unless the mask is changing
if (this.isActive) this.maskSizer();
});
// same as above, caused by us moving out of the zoom area
this.image.addEventListener('mouseout', () => {
this.isExpanding = false;
if (this.isActive) this.maskSizer();
});
}
// The drawmask function shows us the piece of the image that we are hovering over
drawMask() {
// Let's use getBoundingClientRect to get the location of our images
let image = this.image.getBoundingClientRect();
let imageZoom = this.imageZoom.getBoundingClientRect();
// We'll start by getting the (x,y) of our big image that matches the piece we're mousing over (which we stored from our event listener as this.mousex and this.mousey). This is a clunky bit of code to help the zooms work in a variety of situations.
let prop_x = this.mousex / image.width * imageZoom.width * (1 - 1 / settings.magnification) - image.x - window.scrollX;
let prop_y = this.mousey / image.height * imageZoom.height * (1 - 1 / settings.magnification) - image.y - window.scrollY;
// Shift the large image by that amount
this.imageZoom.style.left = -prop_x + "px";
this.imageZoom.style.top = -prop_y + "px";
// Now we need to create our mask
// First let's get the coordinates of the point we're hovering over
let x = this.mousex * settings.magnification;
let y = this.mousey * settings.magnification;
// And create and apply our clip
let clippy = "circle(" + this.maskSize + "px at " + x + "px " + y + "px)";
this.imageZoom.style.clipPath = clippy;
this.imageZoom.style.webkitClipPath = clippy;
}
// We'll use the maskSizer to either expand or shrink the size of our mask
maskSizer() {
// We're in maskSizer so we're changing the size of our mask. Let's make the mask radius larger if the Zoombini is expanding, or shrink it if it's closing. The numbers below might need to be adjusted. It closes faster than it opens
this.maskSize = this.isExpanding ? this.maskSize + 35 : this.maskSize - 40;
// It has the form of: condition ? value-if-true : value-if-false
// Think of the ? as "then" and : as "else"
// if we've reaached max size, don't make it any larger
if (this.maskSize >= settings.maskSize) {
this.maskSize = settings.maskSize;
// we'll no longer need to change the maskSize so we'll just set this.isActive to true and let our mousemove do the drawing
this.isActive = true;
} else if (this.maskSize < 0) {
// Our mask is closed
this.maskSize = 0;
this.isActive = false;
this.image.classList.remove('is-active');
} else {
// Or else we haven't reached a size that we want to keep yet. So let's loop it on the next available frame
// We bind(this) here because so that the function remains in context
requestAnimationFrame(this.maskSizer.bind(this));
}
// After we have the appropriate size, draw the mask
this.drawMask();
}
}
function zoom(e) {
var zoomer = e.currentTarget;
e.offsetX ? offsetX = e.offsetX : offsetX = e.touches[0].pageX
e.offsetY ? offsetY = e.offsetY : offsetX = e.touches[0].pageX
x = offsetX / zoomer.offsetWidth * 100
y = offsetY / zoomer.offsetHeight * 100
zoomer.style.backgroundPosition = x + '% ' + y + '%';
}
//My image generated after page load
.image-zoom-available {
height: unset;
border-radius: 30px;
z-index: 1;
pointer-events: none;
position: absolute;
width: 834.688px;
left: 526.646px;
top: 231.729px;
clip-path: circle(0px at 439.062px 987.812px);
}
<div class="col-12 col-xl-3 col-lg-5 justify-content-center ">
<div class="mb-3">
<img class="image-zoom-available" style="height:75%; border-radius: 30px" src='{{ asset(' /radio/ ') }}{{examen.idpatient.id}}_examen_{{examen.id}}_radio.png' id="image_radio" draggable="false" />
</div>
</div>
Try adding the following property in your hidden image css :
display: none
A non visible element still take space in the web page. Cf: What is the difference between visibility:hidden and display:none?
Remove or override the display: none property when you want to display the image.
I add
this.imageZoom.style.display = "none";
on the event : mouseup and
this.imageZoom.style.display = "block";
on mousedown event. And it's fix thanks !

how to check multi div scroll to top?

I have multiple divs on my page with different classes
how can I check which div is scrolled to the top and therefore do something.
<div class="menu-session-0">
content
</div>
<div class="menu-session-1">
content
</div>
<div class="menu-session-2">
content
</div>
I already tried this :
$(window).scroll(function() {
setTimeout(function(){
var hT = $('.session-index_1').offset().top,
hH = $('.session-index_1').outerHeight(),
wH = $(window).height(),
wS = $(this).scrollTop() + 175;
if(hT <= (wS + 250)){
$('.menu-item').removeClass('menu-item_active');
$('.item-index-1').addClass('menu-item_active');
mySwiper.slideTo(1);
mySwiper.update();
}
},1050);
});
But it did not work as I expected...
Ok.. I get it now, I think.. :P
This should (in theory) work just fine if you copy and paste instead of your code.
If you really want to use JQuery just replace the element reference getters and class writers
const menuItems = document.getElementsByClassName('menu-item');
const menuSessions = document.getElementsByClassName('menu-session');
var nextSession, activeSession;
// do this to get menu-session offsets.. rerun function on viewport resize
function getSessionOffset() {
for( let session of menuSessions ) {
// store position and dataset.index directy on the element reference
session.y = session.offsetTop;
session.indx = session.dataset.index;
}
// define active elements which position we listen for
// these are correct if the window scroll offset is 0 (or at the top)
activeSession = menuSessions[0];
nextSession = menuSessions[1];
onScroll(window.pageYOffset); // so we check and set the correct active elements
}
getSessionOffset();
// page scroll listener
window.addEventListener( 'scroll' , ScrollHandler );
var lastScrollPos = 0; // last recorded window scroll offset
var scrollTick = false; // the tick is used to throttle code execution
function ScrollHandler (ev) {
lastScrollPos = ev.target.scrollTop;
if (!scrollTick) {
window.requestAnimationFrame(() => { // <- read up on this if you are not familiar. Very usefull
onScroll(lastScrollPos);
scrollTick = false;
});
scrollTick = true;
}
}
function onScroll(scrollY) {
if (scrollY > nextSession.y) { // if lower offset is less than scrollPos
removeActiveClass(activeSession.indx); // we remove the active class from menu item
activeSession = menuSessions[nextSession.indx]; // define new elements to listen for
nextSession = menuSessions[nextSession.indx + 1];
addActiveClass(activeSession.indx); // and add an active class to the new menu item
} else if (scrollY < activeSession.y) { // do the same here only in reverse
removeActiveClass(activeSession.indx);
nextSession = menuSessions[activeSession.indx];
activeSession = menuSessions[nextSession.indx - 1];
addActiveClass(activeSession.indx);
}
}
function removeActiveClass(indx) {
menuItems[indx].classList.remove('menu-item_active');
}
function addActiveClass(indx) {
menuItems[indx].classList.add('menu-item_active');
}
We listen only for the current and next values.
This may look like a lot but can be shortened to a third of the size.
Hope this helps :)

Change Right and Left click functionality on MapboxGl

I want to change mouse click functionality on mapboxGl. I need to implement right click panning on map, but there is no documentation about it. So I tried to disable map rotating on right click and enable panning but nothing worked, it just disabled rotation but panning is not triggered.
I want to know if there is a way to programmatically start and stop dragging/panning, I know you can enable it, but I need to actually start panning.
Want to make it clean and easy, I figured you can add listener on mousemove then change map boundaries but it doesn't look nice. Is there any easier way to start dragPan?
I don't know why you want to change left and right click if you want it for left-handed, they should change the mouse settings.
But, anyway, it's possible to make right click for dragging the map.
map.dragPan.disable();
map.dragRotate.disable();
var isMoving = false;
var offset;
map.on("contextmenu", (e) => {});
map.on("mousedown", (e) => {
if (e.originalEvent.button === 2) {
isMoving = true;
offset = e.point;
}
});
map.on("mousemove", (e) => {
if (isMoving) {
map.panBy([offset.x - e.point.x, offset.y - e.point.y], {
duration: 0,
});
offset = e.point;
}
});
map.on("mouseup", (e) => {
isMoving = false;
});
https://jsfiddle.net/cs09g/cnz4xhkt/4/

Css :hover although element not in front

im writing a website on which pictures, ordered in a grid, are shown. I want to make it possible to drag them around with the mouse and zoom in and out with the mouse wheel. This already works so far. here is what my code looks like:
var clicked = [0,0];
var pos = [0,0]; // <-- This ist the position of the image(s)
var dragging = false
var zoom = 1;
//this function is for zooming in and out
window.onmousewheel = function(event)
{
if (event.deltaY > 0)
{
zoom *= 0.9;
}
else
{
zoom *= 1.1;
}
update(0, 0);
}
window.onmousedown = function(event)
{
clicked = [event.clientX, event.clientY];
dragging = true;
}
window.onmousemove = function(event)
{
if (dragging == false){return;}
update((event.clientX-clicked[0]),(event.clientY-clicked[1]))
}
window.onmouseup = function(event)
{
pos = [pos[0] + (event.clientX-clicked[0]), pos[1] + (event.clientY-clicked[1])];
dragging = false;
}
function update(addX, addY) //<-- this function just updades the position of the images by using the zoom and pos variable and the addX and addY parameter
All of this works very fine. But it has one Bug: When i'm start draging while the mouse is directly over one of the images, then when i release the mouse the mouseup event is not triggered an so everything is still moving until you click again with your mouse. What i also do not like is that if you are dragging while the mouse is over one of the images, it shows this standard chrome browser image moving thing.
My Idea for solving this problems was, making a div with opacity: 0; in the front over everything, which fits the whole screen. looks like this:
(css)
#controller
{
position:absolute;
top:0;
left:0;
bottom:0;
right:0;
height:100%;
width:100%;
z-index: 999;
opacity: 0;
}
(html)
<div id="controller"></div>
And now it works fine. I also can drag when i start with the mouse direct over an image. But then i realized that now i can not make any click event or an simple css :hover over one of the images anymore, obviously because the invisible div is now in the front :(
Has anyone of you an idea how two solve this problem?
Put the onmouseup inside onmousedown:
window.onmousedown = function(event)
{
clicked = [event.clientX, event.clientY];
dragging = true;
window.onmouseup = function(event)
{
pos = [pos[0] + (event.clientX-clicked[0]), pos[1] + (event.clientY-clicked[1])];
dragging = false;
}
}

Combining DOM-events in pure JavaScript

I have a webpage with pseudo-canvas (see https://jsfiddle.net/memeladon/vff01jq6/). Circles randomly change their color when a user hovers a cursor over them (mouseover event). How can I modify a program so that colors change only when both left mouse is clicked and a cursor is over a circle (click + mouseover events)? Currently I create cells with such a function:
function createCell() {
var new_cell = document.createElement("DIV"),
cell_circle = document.createElement("DIV");
new_cell.classList.add("paint-cell");
cell_circle.classList.add("paint-cell__circle");
new_cell.appendChild(cell_circle);
new_cell.addEventListener("mouseover", function () { changeColor(cell_circle); });
return new_cell;
}
you can use mouse event object in your callback function and see if a mouse button is clicked
new_cell.addEventListener("mouseover", function (e) {
if(e.buttons !== 0)
{
//do cool stuff
}
});

Categories

Resources