How to Bubble onMouseMove event - javascript

I have image, where I want to show div when I starting to hover on it, but when that div is being hovered React going crazy, because after second div appear image stop his onMouseMove event,
State holds variable which will decide if div appear or not. Variable name "zoom"
I want to keep firing onMouseMove event even when second div appear, any ideas how I could get something like this?
<img
onMouseMove={e => {
this.setState({ zoom: 'block' });
}}
onMouseLeave={() => {
this.setState({ zoom: 'none' });
}}
id="productImg"
src={images[this.state.imgActive]}
/>
)}
<div
style={{
display: this.state.zoom,
float: 'right',
overflow: 'hidden',
zIndex: 100,
transform: 'translateZ(0px)',
opacity: '0.4',
zoom: 1,
width: 285,
height: 285,
backgroundColor: 'white',
border: '1px solrgb(0, 0, 0)',
backgroundRepeat: 'no-repeat',
position: 'absolute',
left: 0,
top: 0
}}
>

It seem like you have a div on top of the img.
When it appears your mouse is on top of the div and no more on top of the img consequently canceling the event.
I would suggest to add the CSS attribute pointerEvents: 'none' to the div in order to ignore the mouse events and let them be handled by the element below.
Hope it helps.

Related

offset (using transform) svg element relative to its own size

I want to offset SVG element relative to its own size using translate with percentage, very similarly to how offset div using transform: translate(100%,0) would work:
this code:
<div style={{ overflow: 'visible', position: 'relative' }}>
{/* rect */}
<div style={{ height: 20, width: 20, background: 'black', position: 'absolute' }} />
{/* circle */}
<div
style={{
height: 20,
width: 20,
background: 'purple',
borderRadius: '50%',
position: 'absolute',
transform: 'translate(100%,0)',
}}
/>
</div>
will look like this
good, the circle offset was relative to its own size
while this case:
<svg overflow={'visible'}>
<rect width={20} height={20} />
<circle cx={10} cy={10} r="10" fill="purple" style={{ transform: 'translate(100%,0px)' }} />
</svg>
will cause this to render:
It's basically being offset relative to the size of the svg canvas(that I never explicitly set):
why does transform: 'translate(100%,0)' work relative to self in div html elements but relative to parent on SVG elements?
already tried:
wrapping g elements, or svg elements similar to other answers on this site.
want to avoid:
I could potentialy solve this by using .getbBox() function and calculate dimensions manually and save it to state and then offset by pixels, but I really want to avoid it and am looking for a simpler solution.
Demo
https://codesandbox.io/s/svg-vs-div-transform-translate-o2ii7
You should set the transform-box to fill-box. For React you use camel case so it looks like this:
style={{ transform: "translate(100%,0px)", transformBox: "fill-box" }}

How to Crop an Image's Height Without Changing Size and Ratio (React/CSS)

I'm attempting to crop this image in CSS so that the image fills the entire container and stays the same ratio as the original file, without changing the image size any larger than what it needs to fit the container. Just like what photoshop does with the crop tool:
In this example, the images size doesnt change in either direction, and fills the container its in, but the image is cropped on its Y axis from the bottom to the top:
Heres a video example: https://imgur.com/za9IIIW
Here's a simple working code example: https://codesandbox.io/s/epic-frog-vkvxp?file=/src/App.js:0-1402
import React, { useEffect, useState, useRef } from "react";
import "./styles.css";
import img from "./img.jpg";
const appContainerStyle = {
position: "relative",
height: "100vh",
width: "100vw",
backgroundColor: "rgb(70,70,70)"
};
const btnContainerStyle = {
position: "absolute",
height: "100%",
width: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center"
};
export default function App() {
const [height, setHeight] = useState(100);
const imageStyle = {
position: "absolute",
height: `${height}%`,
width: "100%",
background: `url(${img})`,
backgroundSize: "cover",
backgroundPosition: "top",
backgroundRepeat: "no-repeat"
};
return (
<div style={appContainerStyle}>
<div style={imageStyle}></div>
<div style={btnContainerStyle}>
<button
style={{ height: "50px", width: "100px" }}
onClick={() => {
height > 0 && setHeight(height - 10);
}}
>
Smaller
</button>
<button
style={{ height: "50px", width: "100px" }}
onClick={() => {
height < 100 && setHeight(height + 10);
}}
>
Bigger
</button>
</div>
</div>
);
}
//image is changing size when the height is changed,
//I would like for it to stay the same size, but crop when the height is changed
My problem is that it crops the image sometimes fine, but it also sometimes changes the image size.
The image shouldn't scale in its container, it should only be cropped in the window.
Here's a flawed approach: stillscales
As you can see, the image is cropped until it reaches a point where the image is then being scaled in its container.
Any help would be appreciated!
create an image container with overflow of hidden so this way when you move image it won't show the outside of box.
then you have to set the image position to relative. this helps to move the image from its position without breaking the design.
after that you can give the image left, right, top and bottom positions to set the image position and the overflow will be hidden.
the html:
<div class="image-container">
<img src="https://cdn.pixabay.com/photo/2015/04/23/22/00/tree-736885__340.jpg"/>
</div>
the css:
.image-container {
overflow: hidden;
}
.image-container img {
position: relative;
top: -100px;
}
this is how you crop the image if you need more help ask in the comment for react code
Change the backgroundSize: "cover" to backgroundSize: "150%".
const imageStyle = {
position: "absolute",
height: `${height}%`,
width: "100%",
background: `url(${img})`,
backgroundSize: "150%",
backgroundPosition: "top",
backgroundRepeat: "no-repeat",
};
Codesandbox: https://codesandbox.io/s/admiring-buck-89pv4

Cannot Get Element Behind Another With Z-Index and Declaring Position

I have a div I'm using as header/nav menu. This div has a drop shadow. There is a dropdown menu when you hover over menu item "Configuration". I want this dropdown menu to appear behind the drop shadow. I am using declared positions and z-index for all elements. The dropdown is z-index 99 and header div is index 100. The dropdown will not appear behind the header div.
I am using Gatsby, React, and Radium. The syntax for the styling below is because I'm using a "styles" object in Javascript to apply the styles.
headerDiv: {
background: 'white',
marginBottom: '1.45rem',
paddingLeft: '10px',
paddingRight: '10px',
boxShadow: '0px 6px 6px rgba(0,0,0,0.2)',
zIndex: '100',
position: 'relative'
},
dropdownMenu: {
opacity: '1',
position: 'absolute',
top: '95%',
left: '0',
zIndex: '99',
padding: '20px 100px 0px 20px',
whiteSpace: 'nowrap',
float: 'left',
minWidth: '160px',
margin: '2px 0 0',
fontSize: '12px',
textAlign: 'left',
listStyle: 'none',
backgroundColor: 'white',
backgroundClip: 'padding-box',
boxShadow: '0 6px 12px rgba(0,0,0,0.175)'
}
I solved this with a workaround. I turned off z-index on all elements. Then I created an empty div and gave it the drop shadow. I gave this div a z-index of 99 and the header navigation menu a z-index of 99 (so it appears behind the empty div). Now it works as intended.

React.js show part of component on hover issue

I have a problem with showing an overlay over my component. Below is the code.
<div className="content">
<div className="main" onMouseEnter={this.mouseOver} onMouseLeave={this.mouseLeaves}>
...
</div>
<div className="overlay" style={this.getOverlayStyle()} ref="overlay">
</div>
</div>
This is the style method:
getOverlayStyle: function() {
return {
display: 'none',
position: 'absolute',
top: '0',
bottom: '0',
left: '0',
right: '0',
zIndex: '100'
};
}
And these are the mouse event handlers:
mouseOver: function() {
this.refs.overlay.style.display = 'block';
},
mouseLeaves: function() {
this.refs.overlay.style.display = 'none';
},
Okay, so, when I hover over the content part, the overlay becomes visible, but it's flickering. When I stop moving the mouse above the content, the overlay is displaying nicely. When I move the mouse again, it flickers again, it's barely watchable, very annoying.
When I try making the overlay visible in the console (just your regular document.getElementsByClassName('overlay')[0].style.display = 'block', it works normally and doesn't flicker. I'm guessing this problem is due to my not yet great React knowledge.
Any ideas why is this happening?
Ps, I tried using a pure CSS solution: selector1 + selector2 { display: block; } and it behaved the same as above.
EDIT, I tried setting the visibility through state (change state on mouse enter and mouse leave), following a recommendation in the comments, but it still flickers when the mouse is moving.
I'm pretty sure you need to move the mouseenter and mouseleave to the .content div, not the .main div
what I expect is happening is this:
you enter main, the overlay is displayed which means the mouse leaves main and enters overlay. because it left main, the overlay is then hidden, and when the overlay is hidden, the mouse reenters main causing the cycle to rinse and repeat
although really this can be accomplished with css selectors. is there a reason you want to do this in react?
There is a pure css solution to this (codepen)
.content {
position: relative;
}
.main {
background-color: #0d0;
min-height: 30px;
min-width: 30px;
}
.overlay {
display: none;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
zIndex: 100;
background-color: #d00;
}
.content:hover .overlay {
display: block;
}

jQuery hoverintent creating and removing element

I have a script that animates my menu ul element on hover. It also creates a background element for the ul. I have made this script:
jQuery(document).ready(function($) {
$(".main-navigation ul:first > li").hoverIntent({
sensitivity: 1,
interval: 100,
timeout: 400,
over: function() {
if ($(this).children().length > 1) {
$(this).parent().prepend('<div class="sub-nav" style="position: absolute; top: 0px; left: 250px; display: block; opacity: 1;"></div>');
$(this).children("ul").css({
"display" : "block",
"left" : "250px",
}).stop().animate({
top: '-50px',
opacity: 1,
}, 500)
}},
out: function() {
$(".sub-nav").remove();
$(this).children("ul").stop().animate({
"top" : "-500px",
"opacity": 0,
}, 500).css({
"display" : "none",
})
}
})
});
It works fine, but the problem occurs once I select another menu that is below that one. So, I have two menus with sub-menus. If I select separetly each one of them everything works fine, but if I select first one and then move to the other one the background elements (.sub-nav) doesn't appear.
What am I missing?
JS FIDDLE: http://jsfiddle.net/r8vx07ae/10/ (try moving your mouse from menu item#2 to menu-item#3)
I'm not sure if this is the right way to do it, but by meddling around I kinda achieved what I wanted. I did the following:
jQuery(document).ready(function($) {
$(".main-navigation ul:first li").hoverIntent({
sensitivity: 1,
interval: 100,
timeout: 400,
over: function() {
if ($(this).children().length > 1) {
$(this).parent().prepend('<div class="sub-nav" style="position: absolute; top: 0px; left: 250px; display: block; opacity: 1;"></div>');
$(this).children("ul").css({
"display" : "block",
"left" : "250px",
}).animate({
top: '-50px',
opacity: 1,
}, 500)
}}
})
.mouseleave(function() {
$(".sub-nav").remove()
$(this).children("ul").stop().animate({
"top" : "-500px",
"opacity": 0,
}, 500).css({
"display" : "none",
})
})
});
This solved my problem. It works just like I wanted.
JS Fiddle updated as well: http://jsfiddle.net/r8vx07ae/11/
Before selecting the answer I'd like to wait for anyone to maybe update it with a better more clean solution.

Categories

Resources