I am making a responsive horizontal scroll UI. The horizontal scroll position is calculated according to the mouse horizontal position:
$(document).ready(function() {
var docWidth = $('body').width(),
slidesWidth = $('#imgs').width(),
rangeX = slidesWidth - docWidth,
$images = $('#imgs');
$(window).on('resize', function() {
var docWidth = $('body').width(),
slidesWidth = $('#imgs').width(),
rangeX = slidesWidth - docWidth;
})
$(document).on('mousemove', function(e) {
var mouseX = e.pageX,
percentMouse = mouseX * 100 / docWidth,
offset = percentMouse / 100 * slidesWidth - percentMouse / 200 * docWidth;
$images.css({
'-webkit-transform': 'translate3d(' + -offset + 'px,0,0)',
'transform': 'translate3d(' + -offset + 'px,0,0)'
});
});
})
body,html {
margin: 0;
overflow: hidden;
height: 100%;
}
#imgs {
position: absolute;
top: 0; left: 0;
width: 150%; height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
margin: 0 25%;
/* transition: transform .1s; */
}
#imgs > div {
max-width: 9%;
perspective: 500px;
z-index: 1;
}
#imgs img {
display: block;
max-width: 100%;
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imgs">
<div><img src="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6083/6055581292_d94c2d90e3.jpg" alt="" /></div>
<div><img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6139/5986939269_10721b8017.jpg" alt="" /></div>
<div><img src="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6083/6055581292_d94c2d90e3.jpg" alt="" /></div>
<div><img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6139/5986939269_10721b8017.jpg" alt="" /></div>
</div>
This works pretty well in the browsers I tested. And other than general performance enhancement I am concerned about this issue:
When the mouse comes out of the window and back in, the images snap to the new position. I tried to make that snap smoother with transition:transform .1s
on the #imgs
element (commented out in the CSS) but:
- in chrome, it is a little janky
- in Firefox and edge it is very janky even on small mouse moves
2 Answers 2
Your project is looking great! But I have a few thoughts on how to improve the clarity of your javascript code:
Unused code
Your window.resize
handler doesn't end up doing anything. Functions create a new scope for variables, so since you're redeclaring docWidth
and slidesWidth
with var
, you don't actually affect the initially declared variables. The reason why all your code still works is that the body's width and the slide's width don't actually change when the window is resized. I'm not sure if this is different on mobile or even why the widths aren't changing (maybe it has something to do with your css) but you ought to either change the handler to something like:
$(window).on('resize', function() {
docWidth = $('body').width();
slidesWidth = $images.width(); // stay consistent with this variable
rangeX = slidesWidth - docWidth;
})
Or just remove it to prevent confusion if the widths aren't affected by resizing.
You also don't end up using rangeX
in your code. Consider removing it.
More straightforward calculation
I think you could simplify the way you calculate the offset in your document.mousemove
handler by eliminating the mousePercent
variable:
$(document).on('mousemove', function(e) {
var mouseX = e.pageX,
offset = mouseX / docWidth * slidesWidth - mouseX / 2;
$images.css({
'-webkit-transform': 'translate3d(' + -offset + 'px,0,0)',
'transform': 'translate3d(' + -offset + 'px,0,0)'
});
});
This way you don't multiply by 100 and then divide by it right after, and you also have fewer variables to worry about.
Unnecessary functionality
You don't use the 3d aspect of translate so why not just use the 2d version:
$images.css({
'-o-transform': 'translate(' + -offset + 'px, 0)', // opera 11.5
'-ms-transform': 'translate(' + -offset + 'px, 0)', // IE9
'-moz-transform': 'translate(' + -offset + 'px, 0)', // firefox 3.5-15
'-webkit-transform': 'translate(' + -offset + 'px, 0)',
'transform': 'translate(' + -offset + 'px,0)'
});
More concise and direct jquery syntax
Another option would be to use jquery's built in methods for creating events instead of using on
:
$(document).ready(function() {
var docWidth = $('body').width(),
slidesWidth = $('#imgs').width(),
rangeX = slidesWidth - docWidth,
$images = $('#imgs');
$(window).resize(function() {
var docWidth = $('body').width(),
slidesWidth = $('#imgs').width(),
rangeX = slidesWidth - docWidth;
})
$(document).mousemove(function(e) {
var mouseX = e.pageX,
percentMouse = mouseX * 100 / docWidth,
offset = percentMouse / 100 * slidesWidth - percentMouse / 200 * docWidth;
$images.css({
'-webkit-transform': 'translate3d(' + -offset + 'px,0,0)',
'transform': 'translate3d(' + -offset + 'px,0,0)'
});
});
});
Once again, great work so far! I wish I could have helped more with the snapping issue. I have a few ideas--mouseenter
, jquery.stop().animate()
--but none that are fully developed. Good luck figuring it out!
This seems to work in IE and FF:
transition: transform .1s; /* default */
-webkit-transition: transform .1s; /* Webkit browsers (safari...) */
-moz-transition: transform .1s; /* Mozilla browsers (Firefox) */
-o-transition: transform .1s; /* Opera browser */
-ms-transition: transform .1s; /* Microsoft browsers (IE...) */
I don't have other browsers to test this on but according to Can I use...:
$(document).ready(function() {
var docWidth = $('body').width(),
slidesWidth = $('#imgs').width(),
rangeX = slidesWidth - docWidth,
$images = $('#imgs');
$(window).on('resize', function() {
var docWidth = $('body').width(),
slidesWidth = $('#imgs').width(),
rangeX = slidesWidth - docWidth;
})
$(document).on('mousemove', function(e) {
var mouseX = e.pageX,
percentMouse = mouseX * 100 / docWidth,
offset = percentMouse / 100 * slidesWidth - percentMouse / 200 * docWidth;
$images.css({
'-webkit-transform': 'translate3d(' + -offset + 'px,0,0)',
'transform': 'translate3d(' + -offset + 'px,0,0)'
});
});
})
body,html {
margin: 0;
overflow: hidden;
height: 100%;
}
#imgs {
position: absolute;
top: 0; left: 0;
width: 150%; height: 100%;
display: flex;
justify-content: space-around;
align-items: center;
margin: 0 25%;
transition: transform .1s; /* default */
-webkit-transition: transform .1s; /* Webkit browsers (safari...) */
-moz-transition: transform .1s; /* Mozilla browsers (Firefox) */
-o-transition: transform .1s; /* Opera browser */
-ms-transition: transform .1s; /* Microsoft browsers (IE...) */
}
#imgs > div {
max-width: 9%;
perspective: 500px;
z-index: 1;
}
#imgs img {
display: block;
max-width: 100%;
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="imgs">
<div><img src="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6083/6055581292_d94c2d90e3.jpg" alt="" /></div>
<div><img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6139/5986939269_10721b8017.jpg" alt="" /></div>
<div><img src="https://farm9.staticflickr.com/8461/8048823381_0fbc2d8efb.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6217/6216951796_e50778255c.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6083/6055581292_d94c2d90e3.jpg" alt="" /></div>
<div><img src="https://farm8.staticflickr.com/7187/6895047173_d4b1a0d798.jpg" alt="" /></div>
<div><img src="https://farm7.staticflickr.com/6139/5986939269_10721b8017.jpg" alt="" /></div>
</div>
-
\$\begingroup\$ Thx for the answer but 1. My target audience will only require the
-webkit-
prefix (-moz-
stopped at FF15 and-o-
is only for opera 11.5) 2.-ms-transition
has never existed 3. As I said in my question the transition property doesn't work in FF (very janky) and chrome doesn't handle it very well either. \$\endgroup\$web-tiki– web-tiki2016年05月26日 07:38:49 +00:00Commented May 26, 2016 at 7:38
-ms-transform: .1s;
and-webkit-transform: .1s;
? \$\endgroup\$transition: transform .1s
\$\endgroup\$