Jquery Clickable audio slider, messes up on window width change - javascript

I have a custom audio player for a website I'm working on. Its progress bar was made clickable (that is it skips to a certain part of the song, depending on where the prog. bar is clicked.
The slider is by default 1000px, and when vw goes below 1000px, the player becomes 100% of the vw.
Now here is where the problem starts because as the width decreases, the current time gets off the desired point dramatically (to the right side, read beginning of the song).
I have made a failed attempt at working the function with vw, and currenty am out of ideas completely.
Here's the code for the player, it's a part of the entire play function, but only those parts go for the progress bar:
audio.ontimeupdate = function () {
$('.progress').css("width", audio.currentTime / audio.duration * 100 + '%');
}
$('#slider').bind('click', function (ev) {
var $div = $(ev.target);
var $display = $div.find('#progcont');
var vW = $(window).width();
var offset = $div.offset();
var x = ev.clientX - offset.left;
$('.progress').css("width", x);
if (vW > 1000){
/*THIS WORKS BUT ONLY TO vW > 1000*/
audio.currentTime = (x / 850 * audio.duration);
} else{
/*FAILED ATTEMPT BELOW*/
audio.currentTime = ((x / (vW / 1.7)) * audio.duration) ;
}
});
Really grateful for any help.

I figured it out by making the script take not pixel value, but the percentage:
$('#slider').bind('click', function (ev) {
var $div = $(ev.target);
var $display = $div.find('#progcont');
var vW = $(window).width();
var pW = $("#progcont").width();
var offset = $div.offset();
var x = ev.clientX - offset.left;
var ProcRatio = x / pW;
audio.currentTime = ProcRatio * audio.duration;
});

Related

DIV fades onto another DIV

How would you make it if the user scrolls down a page, the top DIV fades into the DIV underneath it, and so on and so forth until it fades to a white background?
Here's a jsfiddle of my attempt: https://jsfiddle.net/fkgzzxku/
And here's it's hosted on a staging server for a better illustration: http://bound.staging.wpengine.com/
var target = $('div.slider-item');
var targetHeight = target.height();
var containerHeight = $('#intro-slider').outerHeight();
var maxScroll = containerHeight - targetHeight;
var scrollRange = (maxScroll / (target.length - 1)) + 250; // originally 450
$(document).scroll(function(e) {
var scrollY = $(window).scrollTop();
var scrollPercent = (scrollRange - scrollY % scrollRange) / scrollRange;
var divIndex = Math.floor(scrollY / scrollRange);
target.has(':lt(' + divIndex + ')').css('opacity', 0);
target.eq(divIndex).css('opacity', scrollPercent);
target.has(':gt(' + divIndex + ')').css('opacity', 1);
});
But the DIVs don't completely fade to 0, they fade to a number close to 0 so I feel like my math is wrong.
I also found that if the user scrolls too fast (by pressing page down, etc) you can see all 3 of the images faded into another.
Thanks!
I think because scrollY%scrollRange is never equal to scrollRange your scrollPercent is never 0. You can use scrollPercent= Math.round(scrollPercent*10)/10; after calculating scrollPercent to round it off to 0.
Moreover the problem caused by scrolling too fast seems to be caused by the has function replacing it with slice function works fine for me ( I can't understand why ). Here is the updated code
$(document).scroll(function(e) {
var scrollY = $(window).scrollTop();
var scrollPercent =(scrollRange - scrollY % scrollRange) / scrollRange;
var divIndex = Math.floor(scrollY / scrollRange);
target.slice(0,divIndex).css('opacity', 0);
target.eq(divIndex).css('opacity', scrollPercent);
target.slice(divIndex+1).css('opacity', 1);
});
This works without rounding off scrollPercent. Hope it helps

Realistic mouse movement coordinates in javascript?

In javascript, is there a way I can create a variable and a function that "simulates" smooth mouse movement? i.e., say the function simulates a user starts from lower left corner of the browser window, and then moves mouse in a random direction slowly...
The function would return x and y value of the next position the mouse would move each time it is called (would probably use something like setInterval to keep calling it to get the next mouse position). Movement should be restricted to the width and height of the screen, assuming the mouse never going off of it.
What I don't want is the mouse to be skipping super fast all over the place. I like smooth movements/positions being returned.
A "realistic mouse movement" doesn't mean anything without context :
Every mouse user have different behaviors with this device, and they won't even do the same gestures given what they have on their screen.
If you take an FPS game, the movements will in majority be in a small vertical range, along the whole horizontal screen.
Here is a "drip painting" I made by recording my mouse movements while playing some FPS game.
If we take the google home page however, I don't even use the mouse. The input is already focused, and I just use my keyboard.
On some infinite scrolling websites, my mouse can stay at the same position for dozens of minutes and just go to a link at some point.
I think that to get the more realistic mouse movements possible, you would have to record all your users' gestures, and repro them.
Also, a good strategy could be to get the coordinates of the elements that will attract user's cursor the more likely (like the "close" link under SO's question) and make movements go to those elements' coordinates.
Anyway, here I made a snippet which uses Math.random() and requestAnimationFrame() in order to make an object move smoothly, with some times of pausing, and variable speeds.
// Canvas is here only to show the output of function
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
document.body.appendChild(canvas);
var maxX = canvas.width = window.innerWidth;
var maxY = canvas.height = window.innerHeight;
window.onresize = function(){
maxX = canvas.width = window.innerWidth;
maxY = canvas.height = window.innerHeight;
}
gc.onclick = function(){
var coords = mouse.getCoords();
out.innerHTML = 'x : '+coords.x+'<br>y : '+coords.y;
}
var Mouse = function() {
var that = {},
size = 15,
border = size / 2,
maxSpeed = 50, // pixels per frame
maxTimePause = 5000; // ms
that.draw = function() {
if (that.paused)
return;
that.update();
// just for the example
ctx.clearRect(0, 0, canvas.width, canvas.height);
if(show.checked){
ctx.drawImage(that.img, that.x - border, that.y - border, size, size)
}
// use requestAnimationFrame for smooth update
requestAnimationFrame(that.draw);
}
that.update = function() {
// take a random position, in the same direction
that.x += Math.random() * that.speedX;
that.y += Math.random() * that.speedY;
// if we're out of bounds or the interval has passed
if (that.x <= border || that.x >= maxX - border || that.y <= 0 || that.y >= maxY - border || ++that.i > that.interval)
that.reset();
}
that.reset = function() {
that.i = 0; // reset the counter
that.interval = Math.random() * 50; // reset the interval
that.speedX = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the horizontal direction
that.speedY = (Math.random() * (maxSpeed)) - (maxSpeed / 2); // reset the vertical direction
// we're in one of the corner, and random returned farther out of bounds
if (that.x <= border && that.speedX < 0 || that.x >= maxX - border && that.speedX > 0)
// change the direction
that.speedX *= -1;
if (that.y <= border && that.speedY < 0 || that.y >= maxY - border && that.speedY > 0)
that.speedY *= -1;
// check if the interval was complete
if (that.x > border && that.x < maxX - border && that.y > border && that.y < maxY - border) {
if (Math.random() > .5) {
// set a pause and remove it after some time
that.paused = true;
setTimeout(function() {
that.paused = false;
that.draw();
}, (Math.random() * maxTimePause));
}
}
}
that.init = function() {
that.x = 0;
that.y = 0;
that.img = new Image();
that.img.src ="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAABJUlEQVRIic2WXbHEIAyFI6ESKgEJkVIJlYCTSqiESIiESqiEb19gL9Od3f5R5mbmPPHwBTgnIPJfChiAGbCkCQgtG7BpmgAWIALaDDyOI2bGuq40BasqIoKZATgwNAWHEEjHbkBsBhYRVJUYIwBNwVlFaVOwiDDPMylmQ1OwquY7d0CBrglYkuEeidoeOKt61I6Cq0ftKFhqR+0MOKuo2BQsInnndvnOr4JvR+0qWO5G7Q44K0XtOXDf96jqh9z9WXAy1FJ8l0qd+zbtvU7lWs7wIzkuh8SvpqqDi3zGndPQauDkzvdESm8xZvbh4mVZ7k8ud/+aR0C3YPk7mVvgkCZPVrdZV3dHVem6bju1roMPNmbAmq8kG+/ynD7ZwNsAVVz9dL0AhBrZq7F+CSQAAAAASUVORK5CYII=";
that.reset();
}
that.getCoords = function(){
return {x: that.x, y:that.y};
}
that.init()
return that;
}
var mouse = new Mouse()
mouse.draw();
html,body {margin: 0}
canvas {position: absolute; top:0; left:0;z-index:-1}
#out{font-size: 0.8em}
<label for="show">Display cursor</label><input name="show" type="checkbox" id="show" checked="true"/><br>
<button id="gc">get cursor Coords</button>
<p id="out"></p>
Last I heard the browser's mouse position cannot be altered with JavaScript, so the question really has no answer "as is". The mouse position can be locked though. I'm not certain whether it would be possible to implement a custom cursor that allows setting the position. This would include hiding and perhaps locking the stock cursor.
Having something smoothly follow the cursor is quite straight forward. You may be able to reverse this process to achieve what you need. Here's a code snippet which simply calculates the distance between the cursor and a div every frame and then moves the div 10% of that distance towards the cursor:
http://jsfiddle.net/hpp0qb0d/
var p = document.getElementById('nextmove')
var lastX,lastY,cursorX,cursorY;
window.addEventListener('mousemove', function(e){
cursorX = e.pageX;
cursorY = e.pageY;
})
setInterval(function(){
var newX = p.offsetLeft + (cursorX - lastX)/10
var newY = p.offsetTop + (cursorY - lastY)/10
p.style.left = newX+'px'
p.style.top = newY+'px'
lastX = p.offsetLeft
lastY = p.offsetTop
},20)

Javascript elements only snapping to grid from right side

I am trying to resize elements so that they snap to a grid and so far it is working if I resize from the right side and bottom but for some reason it doesn't work from the left side. I am sure it's just my math but here is the code:
var dimension = win.getDimension();
var newW = Math.round(dimension[0] / 10) * 10;
var newH = Math.round(dimension[1] / 10) * 10;
win.setDimension(newW, newH);
Any ideas?
So what I ended up doing was having an event called onBeforeResizeStart which saved the current x position for the window and in the onResizeFinish event I checked to see if the new x position matched the saved x position. If it did not then I just updated the x position and did the same snap calculation.
onBeforeResizeStart:
var position = getCoords(win);
window.CurrentX = position.left;
onResizeFinish
var position = getCoords(win);
if(position.left != window.currentX)
{
var newX = Math.round(position.left / 10) * 10;
win.setPosition(newX, position.top);
}
var dimension = win.getDimension();
var newW = Math.round(dimension[0] / 10) * 10;
var newH = Math.round(dimension[1] / 10) * 10;
win.setDimension(newW, newH);

Detect percent on screen of an element

I'm trying to detect what % of the element can be seen on the current window.
For example, if the user can only see half the element, return 50. If the user can see the whole element, return 100.
Here's my code so far:
function getPercentOnScreen() {
var $window = $(window),
viewport_top = $window.scrollTop(),
viewport_height = $window.height(),
viewport_bottom = viewport_top + viewport_height,
$elem = $(this),
top = $elem.offset().top,
height = $elem.height(),
bottom = top + height;
return (bottom - viewport_top) / height * 100;
}
But it doesn't seem to be working. Can anyone help me out in achieveing this I seem to be spinning gears.
What you want to get is the amount of pixels that the element extends past the top and bottom of the viewport. Then you can just subtract it from the total height and divide by that height to get the percentage onscreen.
var px_below = Math.max(bottom - viewport_bottom, 0);
var px_above = Math.max(viewport_top - top, 0);
var percent = (height - px_below - px_above) / height;
return percent;
One thing to note is that jQuery's height method won't include padding. You probably want to use .outerHeight for that.
Your $elem = $(this)assignment seems wrong, here function scoping means this refers to the function you're in (ala ~ the function getPercentOnScreen), try referencing by $elem = $('#yourElementId')instead.
if you only want to calculate percent of element then just do this
function getPercentOnScreen(elem) {
$docHeight = $(document).height();
$elemHeight = $(elem).height();
return ($elemHeight/$docHeight)* 100;
}

jQuery image hover effect

I'm trying to achieve this effect with jQuery.
I wrote some of the code, but it's buggy (move to the bottom-right corder and you'll see).
check it out
Basically, if there's an already-built jQuery plugin that you know of that does this, I'd be very happy using it, if not, any help with my formula would be appreciated. This is what I get for not paying attention in Maths classes :)
Thanks in advance.
Maikel
Overall I think this is what you're looking for:
$.fn.sexyImageHover = function() {
var p = this, // parent
i = this.children('img'); // image
i.load(function(){
// get image and parent width/height info
var pw = p.width(),
ph = p.height(),
w = i.width(),
h = i.height();
// check if the image is actually larger than the parent
if (w > pw || h > ph) {
var w_offset = w - pw,
h_offset = h - ph;
// center the image in the view by default
i.css({ 'margin-top':(h_offset / 2) * -1, 'margin-left':(w_offset / 2) * -1 });
p.mousemove(function(e){
var new_x = 0 - w_offset * e.offsetX / w,
new_y = 0 - h_offset * e.offsetY / h;
i.css({ 'margin-top':new_y, 'margin-left':new_x });
});
}
});
}
You can test it here.
Notable changes:
new_x and new_y should be divided by the images height/width, not the container's height/width, which is wider.
this is already a jQuery object in a $.fn.plugin function, no need to wrap it.
i and p were also jQuery objects, no need to keep wrapping them
no need to bind mousemove on mouseenter (which rebinds) the mousemove will only occur when you're inside anyway.
Nick Craver beat me to an answer by about 10 minutes, but this is my code for this, using background-image to position the image instead of an actual image.
var img = $('#outer'),
imgWidth = 1600,
imgHeight = 1200,
eleWidth = img.width(),
eleHeight = img.height(),
offsetX = img.offset().left,
offsetY = img.offset().top,
moveRatioX = imgWidth / eleWidth - 1,
moveRatioY = imgHeight / eleHeight - 1;
img.mousemove(function(e){
var x = imgWidth - ((e.pageX - offsetX) * moveRatioX),
y = imgHeight - ((e.pageY - offsetY) * moveRatioY);
this.style.backgroundPosition = x + 'px ' + y + 'px';
});
The huge amount of variables are there because the mousemove event handler has to be as efficient as possible. It's slightly more restrictive, because you need to know the dimensions, but I think the code can be easily altered to work with imgs for which the size can be calculated easily.
A simple demo of this: http://www.jsfiddle.net/yijiang/fq2te/1/

Categories