I'm trying to put mouse enter/mouse-leave events on moving elements. There is a problem in handling the hover event with CSS, so I'm trying to process it with JS. This works fine in chrome but not working in safari. How to make mouseenter/mouseleave work properly when the mouse is stopped?
CSS
.big-box {
position: relative;
width: 500px;
height: 100px;
background: #ee9;
}
.hit-box {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
background: #e99;
}
HTML
<div class="big-box">
<div class="hit-box">hit-box</div>
</div>
JavaScript
const hitbox = document.querySelector('.hit-box');
var position = 5;
hitbox.style.left = 0;
hitbox.addEventListener('mouseenter', function() {
console.log('enter');
});
hitbox.addEventListener('mouseleave', function() {
console.log('leave');
});
setInterval(function() {
if(parseInt(hitbox.style.left) + position > 400) {
position = -5;
} else if(parseInt(hitbox.style.left) + position < 0) {
position= 5;
}
hitbox.style.left = parseInt(hitbox.style.left) + position + 'px';
},20)
Related
I am making a window in the bottom of my HTML page that I would like to be resizeable when the user clicks and drags. This is what I have so far:
var main = document.getElementById("dragWindow")
var dragTop = document.querySelector("#dragWindow .draggerTop")
var dragTopDown = false
dragTop.addEventListener("mousedown", function() {
dragTopDown = true
})
document.body.addEventListener("mouseup", function() {
dragTopDown = false
})
document.body.addEventListener("mousemove", function(e) {
if (dragTopDown == false) {
return
}
var h = (window.innerHeight - e.clientY) + "px"
main.style.top = "calc(100% - " + h + ")"
})
#dragWindow {
background: lightgray;
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: calc(100% - 150px);
}
#dragWindow .draggerTop {
position: absolute;
left: 0;
right: 0;
top: 0;
height: 5px;
background: gray;
cursor: ns-resize;
}
Page content here...
<div id="dragWindow">
<div class="draggerTop"></div>
</div>
In the above example, the dragger doesn't work very well. It is slow and won't move most of the time. Is there something that I am missing? It mainly seems to have trouble moving back upward. Also, when you release the mouse, it still is draggable.
I know that there is the CSS resize property, however, I am trying to make a custom version with js.
Nvm, I figuired it out.
Rather than using document.body for the event listeners, I should have used just document. Like this:
var main = document.getElementById("dragWindow")
var dragTop = document.querySelector("#dragWindow .draggerTop")
var dragTopDown = false
dragTop.addEventListener("mousedown", function() {
dragTopDown = true
})
document.addEventListener("mouseup", function() {
dragTopDown = false
})
document.addEventListener("mousemove", function(e) {
if (dragTopDown == false) {
return
}
var h = (window.innerHeight - e.clientY) + "px"
main.style.top = "calc(100% - " + h + ")"
})
#dragWindow {
background: lightgray;
position: absolute;
bottom: 0;
left: 0;
right: 0;
top: calc(100% - 150px);
}
#dragWindow .draggerTop {
position: absolute;
left: 0;
right: 0;
top: 0;
height: 5px;
background: gray;
cursor: ns-resize;
}
Page content here...
<div id="dragWindow">
<div class="draggerTop"></div>
</div>
How to move or drag the span into the Div element. My element structure is the Div -> Span. Here I need to drag the Span inside the div element without drag beyond that div. I have tried this by calculating pixels but didn't give a solution. I don't need a native onDrag method.
I need to calculate pixels and drag the Span inside the Div. Here is my code.
var handleClick = false;
window.dragging = function(event) {
if (handleClick) {
var bar = document.getElementsByClassName('bar')[0],
handle = document.getElementsByClassName('handle')[0];
var left = bar.offsetWidth - handle.offsetWidth;
tops = (bar.offsetWidth - handle.offsetWidth);
pixel = left < ((pixel - 0) / 1.233445) ? left : ((pixel - 0) / 1.233445);
handle.style.left = pixel + "px";
}
}
document.addEventListener('mouseup', function() {
handleClick = false;
});
window.handlersDown = function() {
handleClick = true;
}
.bar {
width: 100px;
height: 30px;
border: 1px solid;
position: relative;
}
.handle {
width: 20px;
height: 20px;
left: 2px;
top: 5px;
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
}
<div class="bar">
<span class="handle" onmousedown="handlersDown()" onmousemove="dragging(event)"></span>
</div>
I have modified your code a bit and changed the selectors from class to ID. I also would advice you to use external libraries to make it more easy for you. Besides that I also removed the event listeners inside your HTML and translate them to Javascript. Is this what you want?
window.onload = addListeners();
function addListeners(){
document.getElementById('handle').addEventListener('mousedown', mouseDown, false);
window.addEventListener('mouseup', mouseUp, false);
}
function mouseUp()
{
window.removeEventListener('mousemove', spanMove, true);
}
function mouseDown(e){
window.addEventListener('mousemove', spanMove, true);
}
function spanMove(e){
var bar = document.getElementById('bar')
var span = document.getElementById('handle');
// variables
var bar_width = bar.offsetWidth;
var handle_width = span.offsetWidth;
// stop scroll left if the minimum and maximum is reached
if(e.clientX < bar_width - handle_width - 1 && e.clientX > 1){
span.style.left = e.clientX + 'px';
}
}
#bar {
width: 100px;
height: 30px;
border: 1px solid;
position: relative;
}
#handle {
width: 20px;
height: 20px;
left: 2px;
top: 5px;
background-color: rgba(255, 0, 0, 0.5);
position: absolute;
}
<div id="bar">
<span id="handle"></span>
</div>
In 2020, following solution works perfectly on last version of Chrome, Opera, Firefox and Edge Chromium.
window.onload = addListeners();
function addListeners()
{
var div = document.getElementById('div');
var span = document.getElementById('span');
span.addEventListener('mousedown', onMouseDown, false);
window.addEventListener('mouseup', onMouseUp, false);
//compute space between left border of <div> and left border of <span>
// this value is also used to compute space at right
iMinLeft = span.offsetLeft;
// compute max left value allowed so that span remains in <div>
iMaxLeft = div.clientWidth - span.offsetWidth - iMinLeft;
}
function onMouseDown(e)
{
if (e.which === 1) // left button is pressed
{
e.preventDefault();
window.addEventListener('mousemove', onMouseMove, true);
// save mouse X position to compute deplacement
posMouseX = e.clientX;
span.style.background = "yellow";
}
}
function onMouseMove(e)
{
e.preventDefault();
//compute mouse deplacement
deltaX = posMouseX - e.clientX;
//compute new left position of <span> element
iNewLeft = span.offsetLeft - deltaX;
if (iNewLeft < iMinLeft)
{
iNewLeft = iMinLeft;
}
else
{
if (iNewLeft > iMaxLeft)
{
iNewLeft = iMaxLeft;
}
}
span.style.left = iNewLeft + 'px';
// save mouse X position to compute NEXT deplacement
posMouseX = e.clientX;
}
function onMouseUp(e)
{
if (e.which === 1) // left button is pressed
{
e.preventDefault();
span.style.background = "white";
window.removeEventListener('mousemove', onMouseMove, true);
}
}
#div
{
width: 200px;
height: 50px;
border: 1px solid;
position: relative;
left: 50px;
}
#span
{
cursor: pointer;
font-size: 30px;
width: auto;
height: 40px;
left: 2px;
top: 5px;
position: absolute;
}
<div id="div">
<span id="span">😃</span>
</div>
JavaScript line e.preventDefault(); is necessary to avoid <span> to become 'blue' when dragging.
CSS code cursor: pointer; is only to see that unicode is clickable.
Javascript line if (e.which === 1) has been added to prevent emoticon to move when RIGHT mouse button is clicked.
The rectangle around emoticon when <span> is dragged move without being shifted (see previous solution) and space remaining in left or in right are equal.
Thanks to w3schools-exemple
I attempted to add a swiping function to my slider to allow users to swipe through the images on their touchable devices. It hasn't turned out the best. When swiping at the images they do not slide over all of the way and then when I get to the end of the gallery (end of fourth image), the slider goes blank (goes white) and then it goes back to normal after a while.
I have added the important code to this question, as well as added a Fiddle to try it out.
The fiddle doesn't replicate the issue, so if you would like to see what this is doing, please go here to see it live. Scroll about halfway down and then you will see the slider.
The example I used had three images instead of four and I am thinking this may be my issue, but when I remove my 4th image (a repeat of the first image for a smoother transition back to the first), the issue is still present. I'm 99% sure the issue resides within the javascript, but I can't locate it.
Does anyone see what I am doing wrong or how to improve this?
Please note. I am putting the full code for this function, but I believe the issue resides within the move or end function here:
move: function(event) {
// Continuously return touch position.
this.touchmovex = event.originalEvent.touches[0].pageX;
// Calculate distance to translate figure.
this.movex = this.index*this.slideWidth + (this.touchstartx - this.touchmovex);
// Defines the speed the images should move at.
var panx = 100-this.movex/6; // was /6
if (this.movex < 600) { // Makes the figure stop moving when there is no more content.
this.el.figure.css('transform','translate3d(-' + this.movex + 'px,0,0)');
}
if (panx < 100) { // Corrects an edge-case problem where the background image moves without the container moving.
this.el.imgSlide.css('transform','translate3d(-' + panx + 'px,0,0)');
}
},
end: function(event) {
// Calculate the distance swiped.
var absMove = Math.abs(this.index*this.slideWidth - this.movex);
// Calculate the index. All other calculations are based on the index.
if (absMove > this.slideWidth/2 || this.longTouch === false) {
if (this.movex > this.index*this.slideWidth && this.index < 2) {
this.index++;
} else if (this.movex < this.index*this.slideWidth && this.index > 0) {
this.index--;
}
}
// Move and animate the elements.
this.el.figure.addClass('animate').css('transform', 'translate3d(-' + this.index*this.slideWidth + 'px,0,0)');
this.el.imgSlide.addClass('animate').css('transform', 'translate3d(-' + 100-this.index*50 + 'px,0,0)');
Full code:
if (navigator.msMaxTouchPoints) {
$('#slider').addClass('ms-touch');
$('#slider').on('scroll', function() {
$('.slide-image').css('transform','translate3d(-' + (100-$(this).scrollLeft()/6) + 'px,0,0)');
});
} else {
var slider = {
el: {
slider: $("#slider"),
figure: $(".figure"),
imgSlide: $(".slide-image")
},
slideWidth: $('#slider').width(),
touchstartx: undefined,
touchmovex: undefined,
movex: undefined,
index: 0,
longTouch: undefined,
init: function() {
this.bindUIEvents();
},
bindUIEvents: function() {
this.el.figure.on("touchstart", function(event) {
slider.start(event);
});
this.el.figure.on("touchmove", function(event) {
slider.move(event);
});
this.el.figure.on("touchend", function(event) {
slider.end(event);
});
},
start: function(event) {
// Test for flick.
this.longTouch = false;
setTimeout(function() {
window.slider.longTouch = true;
}, 250);
// Get the original touch position.
this.touchstartx = event.originalEvent.touches[0].pageX;
// The movement gets all janky if there's a transition on the elements.
$('.animate').removeClass('animate');
},
move: function(event) {
// Continuously return touch position.
this.touchmovex = event.originalEvent.touches[0].pageX;
// Calculate distance to translate figure.
this.movex = this.index*this.slideWidth + (this.touchstartx - this.touchmovex);
// Defines the speed the images should move at.
var panx = 100-this.movex/6; // was /6
if (this.movex < 600) { // Makes the figure stop moving when there is no more content.
this.el.figure.css('transform','translate3d(-' + this.movex + 'px,0,0)');
}
if (panx < 100) { // Corrects an edge-case problem where the background image moves without the container moving.
this.el.imgSlide.css('transform','translate3d(-' + panx + 'px,0,0)');
}
},
end: function(event) {
// Calculate the distance swiped.
var absMove = Math.abs(this.index*this.slideWidth - this.movex);
// Calculate the index. All other calculations are based on the index.
if (absMove > this.slideWidth/2 || this.longTouch === false) {
if (this.movex > this.index*this.slideWidth && this.index < 2) {
this.index++;
} else if (this.movex < this.index*this.slideWidth && this.index > 0) {
this.index--;
}
}
// Move and animate the elements.
this.el.figure.addClass('animate').css('transform', 'translate3d(-' + this.index*this.slideWidth + 'px,0,0)');
this.el.imgSlide.addClass('animate').css('transform', 'translate3d(-' + 100-this.index*50 + 'px,0,0)');
}
};
slider.init();
}
.animate {
transition: transform 0.3s ease-out;
}
#company-slider-section {
width: 100%;
height: auto;
position: relative;
}
div#slider {
width: 100%;
overflow: hidden;
position: relative;
}
div#slider .figure {
position: relative;
width: 400%;
margin: 0;
padding: 0;
font-size: 0;
text-align: left;
}
.ms-touch.slider {
overflow-x: scroll;
overflow-y: hidden;
-ms-overflow-style: none;
/* Hides the scrollbar. */
-ms-scroll-chaining: none;
/* Prevents Metro from swiping to the next tab or app. */
-ms-scroll-snap-type: mandatory;
/* Forces a snap scroll behavior on your images. */
-ms-scroll-snap-points-x: snapInterval(0%, 100%);
/* Defines the y and x intervals to snap to when scrolling. */
}
.figure2 {
animation: 20s company-slider infinite;
margin: 0;
}
#keyframes company-slider {
0% {
left: 0%;
}
30% {
left: 0%;
}
35% {
left: -100%;
}
55% {
left: -100%;
}
60% {
left: -200%;
}
90% {
left: -200%;
}
95% {
left: -300%;
}
100% {
left: -300%;
}
}
.slide-wrapper img {
width: 25%;
min-height: 100%;
float: left;
position: relative;
overflow: hidden;
}
.slide {
height: 100%;
position: relative;
}
.slide:before {
content: "";
position: absolute;
z-index: 1;
bottom: 0;
left: 0;
width: 100%;
height: 40%;
background: linear-gradient(transparent, black);
}
<div id="company-slider-section">
<div class="section-blocks left">
<div id="slider" class="slider">
<figure class="figure figure2">
<div class="slide-wrapper">
<div class="slide"><img src="/images/work/projects/eslich/es-test1.jpg" alt class="slide-image"></div>
</div>
<div class="slide-wrapper">
<div class="slide"><img src="/images/work/projects//desktop-service.jpg" alt class="slide-image"></div>
</div>
<div class="slide-wrapper">
<div class="slide"><img src="/images/work/projects//es-test2.jpg" alt class="slide-image"></div>
</div>
<div class="slide-wrapper">
<div class="slide"><img src="/images/work/projects//es-test1.jpg" alt class="slide-image"></div>
</div>
</figure>
</div>
</div>
</div>
I am trying to make so that if you scroll down, a blurred picture appears (with opacity) and if you're at the bottom of the page, the blurred picture is fully visible and the old one disappeared. I'm using the same pagecontainer for every page and I want to make this script do this on every page, with different page lengths.
I have this so far:
CSS:
.img-src {
position: fixed;
background-position: center;
-webkit-background-size: cover;
top: 0;
bottom: 0;
left: 0;
right: 0;
z-index: -1;
}
.blurred-img {
opacity: 0;
}
JS:
var divs = $('.social, .title'),
limit = 0;
$(window).on('scroll', function() {
var st = $(this).scrollTop();
if (st <= limit) {
$('.blurred-img').css({ 'opacity' : (1 - st/limit) });
}
});
filter: blur usually works fine and looks better. How about something like this?
var img = document.getElementById("background-img");
var container = document.body;
var maxBlur = 20;
window.addEventListener("scroll", function(){
var position = container.scrollTop / (container.scrollHeight - window.innerHeight);
// Adjust the position for safari that may scroll higher or lower than the
// actual size during their "bounce effect".
position = Math.max(0, Math.min(1, position));
var blurAmount = position * maxBlur;
img.style["filter"] = "blur(" + blurAmount + "px)";
});
#background-img {
position: fixed;
}
#spacer {
width: 50px;
height: 2000px;
}
<img id="background-img" src="http://placehold.it/400x200?text=Background" />
<div id="spacer"></div>
If you really want to do your two images strategy, here is how I would do it.
var img = document.getElementById("blured-background-img");
var container = document.body;
window.addEventListener("scroll", function(){
var opacity = container.scrollTop / (container.scrollHeight - window.innerHeight);
// Adjust the opacity for safari that may scroll higher or lower than the
// actual size during their "bounce effect".
opacity = Math.max(0, Math.min(1, opacity));
img.style["opacity"] = opacity;
});
#background-img {
position: fixed;
}
#blured-background-img {
position: fixed;
opacity: 0;
}
#spacer {
width: 50px;
height: 2000px;
}
<img id="background-img" src="http://placehold.it/400x200/7A6DFF/D3CFFF?text=Bottom" />
<img id="blured-background-img" src="http://placehold.it/400x200?text=Top" />
<div id="spacer"></div>
Here's the jsfiddle.
It's the interface to cropping an image. As you can see the selection div takes the same background image and positions it to the negative of the top and left attributes of the selection div. In theory this should give a perfect overlap, but there's a jitter as you move the selection div around, and I can't seem to figure out what is causing it.
html
<div id="main">
<div id="selection"></div>
</div>
css
#main {
width: 600px;
height: 450px;
position: relative;
background: url("http://cdn-2.historyguy.com/celebrity_history/Scarlett_Johansson.jpg");
background-size: contain;
}
#selection {
width: 100px;
height: 100px;
position: absolute;
background: url("http://cdn-2.historyguy.com/celebrity_history/Scarlett_Johansson.jpg");
border: 1px dotted white;
background-size: 600px 450px;
}
jquery
$(document).ready(function () {
var move = false;
var offset = [];
var selection = null;
$("#selection").mousedown(function (e) {
move = true;
selection = $(this);
offset = [e.pageX - selection.offset().left, e.pageY - selection.offset().top];
});
$("#selection").mousemove(function (e) {
if (move == true) {
selection.css("left", e.pageX - offset[0]);
selection.css("top", e.pageY - offset[1]);
selection.css("background-position", (((-selection.position().left) - 1) + "px " + ((-selection.position().top ) - 1) + "px"));
}
});
$("#selection").mouseup(function (e) {
move = false;
});
})
It would appear that there is a value of 5 offset that needs to be added to ensure seamlessness
DEMO http://jsfiddle.net/nzx0fcp5/2/
offset = [e.pageX - selection.offset().left + 5, e.pageY - selection.offset().top + 5];
So, while experimenting I discovered that this was only a problem at certain sizes of the image. At the original size it is no problem, neither at half nor a quarter of this size. It wasn't simply a matter of keeping the image in proportion not having the image square or using even pixel sizes. I'm assuming this had something to do with partial pixel sizes, but I'm not sure, and I couldn't see any way to work around this, at least none that seemed worth the effort.
So while checking out the code of other croppers I took a look at POF's image cropper, they seem to have got round the problem by not using the background-position property at all (I'm not sure if it's plugin or they coded it themselves). They just set the image down and then used a transparent selection div with 4 divs stuck to each edge for the shading. So there's no pixel crunching on the fly at all. I like the simplicity and lightweight nature of this design and knocked up a version myself in jsfiddle to see if I could get it to work well.
new jitter free jsfiddle with no pixel crunching
I liked the solution for the preview box as well.
html
<body>
<div id="main">
<img src="http://flavorwire.files.wordpress.com/2012/01/scarlett_johansson.jpg" />
<div id="upperShade" class="shade" > </div>
<div id="leftShade" class="shade" > </div>
<div id="selection"></div>
<div id="rightShade" class="shade"></div>
<div id="lowerShade" class="shade" ></div>
</div>
</body>
css
#main {
position:relative;
width: 450px;
height: 600px;
}
#selection {
width: 148px;
height: 148px;
position: absolute;
border: 1px dotted white;
top: 0px;
left: 0px;
z-index: 1;
}
.shade {
background-color: black;
opacity: 0.5;
position: absolute;
}
#upperShade {
top: 0px;
left: 0px;
width: 600px;
}
#leftShade {
left: 0px;
top: 0px;
height: 150px;
width: auto;
}
#rightShade {
left: 150px;
top: 0px;
height: 150px;
width: 450px;
}
#lowerShade {
left:0px;
top: 150px;
width: 600px;
height: 300px;
}
jquery
$(document).ready(function () {
var move = false;
var offset = [];
var selection = null;
$("#selection").mousedown(function (e) {
move = true;
selection = $(this);
offset = [e.pageX - selection.offset().left, e.pageY - selection.offset().top];
});
$("#selection").mousemove(function (e) {
if (move == true) {
selection.css("left", e.pageX - offset[0]);
selection.css("top", e.pageY - offset[1]);
setShade();
}
});
function setShade() {
$("#upperShade").css("height", selection.position().top);
$("#lowerShade").css("height", 600 - (selection.position().top + 150));
$("#lowerShade").css("top", selection.position().top + 150);
$("#leftShade").css("top", selection.position().top);
$("#leftShade").css("width", selection.position().left);
$("#rightShade").css("top", selection.position().top);
$("#rightShade").css("left", selection.position().left + 150);
$("#rightShade").css("width", 450 - selection.position().left);
}
$("#selection").mouseup(function (e) {
move = false;
});
});