If possible I would prefer to do this in HTML/CSS/JS but if not, anything goes.
I'm trying to set the background for a webpage to have a kind of absolute position that will remain there regardless of where the browser window is on the screen and regardless of size.
Picture for clarification:
(Explaination for picture: Red outline is browser window, the light blue-transparent picture is the position and size that the picture should always have)
You can get the screen position of the window with window.screenX and window.screenY. Then you can track that with a simple interval timer:
setInterval(function() {
$('body').css('backgroundPosition',
-window.screenX + 'px ' + -window.screenY + 'px');
}, 50);
(That uses jQuery but it's not necessary.)
Here is a jsbin to demonstrate. It's a little jumpy, but it'll probably heat up client machines as it stands so I wouldn't run the timer too much faster. The problem is that while the browser will tell you about window size changes (the "resize" event), it won't tell you via events about the window being moved around.
Here's a somewhat more efficient version without jQuery and with some checks to avoid touching the style when the window hasn't moved. This doesn't seem to make Firefox or Chrome go too nuts even running every 15 milliseconds:
(function() {
var sx = window.screenX, sy = window.screenY;
setInterval(function() {
if (window.screenX !== sx || window.screenY !== sy)
document.body.style.backgroundPosition =
-(sx = window.screenX) + 'px ' + -(sy = window.screenY) + 'px';
}, 15);
})()
Related
I am using a html5 video on my website. I want it to play only when in view and pause otherwise.
I am also using javascript to have a play/pause button on it.
I was able to use both the features on one site easily and the video was the first element on the site. However this time it is the second div
I feel like there is a conflict because of the same element being targetted or something going wrong that I just can't seem to understand
In this case the video autoplays when I open the site, and when I scroll to the actual video, it stops(pauses)! Can anyone see what I am doing wrong ?
<script>
var videos = document.getElementsByTagName("video"), fraction = 0.8;
function checkScroll() {
for(var i = 0; i < videos.length; i++) {
var video = videos[i];
var x = video.offsetLeft, y = video.offsetTop, w = video.offsetWidth, h = video.offsetHeight, r = x + w, //right
b = y + h, //bottom
visibleX, visibleY, visible;
visibleX = Math.max(0, Math.min(w, window.pageXOffset + window.innerWidth - x, r - window.pageXOffset));
visibleY = Math.max(0, Math.min(h, window.pageYOffset + window.innerHeight - y, b - window.pageYOffset));
visible = visibleX * visibleY / (w * h);
if (visible > fraction) {
video.play();
} else {
video.pause();
}
}
}
window.addEventListener('scroll', checkScroll, false);
window.addEventListener('resize', checkScroll, false);
</script>
I have attached a fiddle
http://jsfiddle.net/5wZLL/12/
other plugins that I have used on this site :
Stellar.Js
FlexSlider
SmoothScroll
The code you've posted here is mostly fine and should work more or less correctly, but here are a few things to look out for:
Remove the autoplay attribute completely from your video element. Setting it to "0" does not turn it off. Any value at all for autoplay will make it true.
You'll probably want to call checkScroll one time at page load to cover the initial window state, in case the video is in view initially. Otherwise, it won't start until you scroll at least one time.
The math here assumes that your video is positioned statically, with no parent elements that have CSS position as fixed, relative, or absolute. If you need to do that, you may need to modify the position calculation slightly. But this is not a problem in the jsfiddle you posted.
Based on the value of fraction, the video will only play if 80% of it is visible. If the browser window is smaller than 80% of the area of the video element, it will never play no matter where you scroll. You may want to adjust the value compared to visible to account for that, or you can leave it as is. Up to you.
Make sure the video is actually being loaded. If the file is not found or if the network is too slow, the play state may be set but you may not see it playing. You might want to have some other visual indicator of the play state, using the play and pause events and the paused property.
Finally, if you're going to have a separate pause/play button, you'll want to use that to set some external variable that disables the scrolling logic so they don't conflict.
Based on your description, I suspect that you want to pay close attention to 1. and 3., as they will likely solve your problem.
Update:
It looks like your problem is 3. When you have parent elements that are not positioned statically, offsetTop and offsetLeft are not sufficient to get the position of your video element within the page. You need to loop through all the ancestor elements that can affect the position, like this:
parent = video;
while (parent && parent !== document.body) {
x += parent.offsetLeft;
y += parent.offsetTop;
parent = parent.offsetParent;
}
Here's a working example:
http://jsbin.com/qekat/1/edit
So I designed a website that is for 1024x768... A decision I made based on global stats showcasing this to be still the predominant resolution.
I myself zoom in and it looks great. I used a few tricks on some pictures they are higher res but scaled down if you zoom in they are not blury.
However... now anyone who opens and doesn't know how to zoom in will see a page that's tiny as more and more people are using higher resolution screens. Still having the users to zoom in is not right and I want to fix this...
Is there a way to scale the page upon opening for each user depending on their viewport?
How a user sees it now: http://i.stack.imgur.com/XBqiQ.jpg
How I view it and would like users to view: http://i.stack.imgur.com/xNTIF.png
The only stuff I could find relating to zooming and scaling was for images only...
ADDITIONAL EDIT:
Ok in response to the answer given to me to what was given to me did not work in firefox not sure about IE as I did not test it but it was exactly what i wanted!
$('body').css('zoom',$(window).width()/1200);
Any suggestions?
The problem I also run in to using this is with an iframe I have: I use this on an iframe page to load the forum and fit it in the content of the wordpress page . This code automaticaly resizes it and puts it on top.
<script language="javascript" type="text/javascript">
function resizeIframe(obj)
{
obj.style.height = obj.contentWindow.document.body.scrollHeight + 'px';
obj.style.width = obj.contentWindow.document.body.scrollWidth + 'px';
}
</script>
[iframe id="frmid" frameborder="0" padding="0" margin="0" onload="javascript:resizeIframe(this); window.parent.parent.scrollTo(0,0)" src="http://muslimbodybuilding.com/Forum/" scrolling="no"]
See screenshot in comment I could not post another link limits me...
======================
I've also run across another similar solution that works in Firefox
<script type="text/javascript">
jQuery(window).load(function() {
var currentWidth = jQuery(document.body).width();
var targetWidth = 1100; // experiment for your self
var scrollWidth = 0; // need to make it dynamic --- was 20
// if the screen is not bigger than the target, then don't mess with zooming
if (currentWidth > targetWidth) {
if (typeof document.body.style.transform != "undefined")
document.body.style.transform = currentWidth / targetWidth;
else if (typeof document.body.style.MozTransform != "undefined") {
document.body.style.MozTransformOrigin = "left top";
document.body.style.MozTransform = 'scale(' + currentWidth / targetWidth + ')';
}
else if (typeof document.body.style.WebkitTransform != "undefined")
document.body.style.WebkitTransform = 'scale(' + currentWidth / targetWidth + ')';
jQuery(document.body).width(targetWidth - scrollWidth);
}
});
</script>
It zooms in the iframe too, however the facebook slider I have then gets pushed and moves around as I keep changing pages.
In chrome it still does not zoom the iframe with this method.
Any ideas on this?
Assuming you are using jQuery (you can do it without jQuery but it makes the code much more succinct for cross-browser compatibility) you could do:
$('body').css('zoom',$(window).width()/768);
This sets the zoom property of the body to the ratio by which the browser window is wider than your design. Beware that not all browsers support css zoom.
However, this is really a bit of a nasty hack - the 'modern' way to do it is to use responsive web design, to give a good experience whatever the width of the client browser.
I am currently developing a webpage for an iPhone which contains a DIV element that the user can touch and drag around. In addition, when the user drags the element to the top or bottom of the device's screen, I want to automatically scroll the page up or down.
The problem I am having is trying to determine a reliable formula to get the coordinates in the onTouchMove event that coorespond with the user's finger reaching the top or the bottom of the device viewport. My current formula seems tedious and I feel there may be an easier way to do this.
My current formula to determine if the touch event has reached the bottom of the screen:
function onTouchMoveHandler(e)
{
var orientation=parent.window.orientation;
var landscape=(orientation==0 || orientation==180)?true:false;
var touchoffsety=(!landscape?screen.height - (screen.height - screen.availHeight):screen.width - (screen.width - screen.availWidth)) - e.touches[0].screenY + (window.pageYOffset * .8);
if(touchoffsety < 40) alert('finger is heading off the bottom of the screen');
}
I have done a bit of Javascript reflection on objects such as the window, document, body, e.touches to see if I could find a set of numbers that would always add up to equal the top or bottom of the screen, but without reliable success. Help with this would be greatly appreciated.
Assuming the screenY field of a touch holds the y coordinate relative to the screen-top regardless of current scroll position, your current calculation does not make a whole lot of sense to me. I hope I did not misunderstand what your trying to do.
To find out if a touch is close to the top or the bottom of the device, I would first check if screenY is close to top (top being 0), since you can work with that value directly. Then, if it's not close to top, calculate how close it is to the bottom and check that.
var touch = e.touches[0];
if (touch.screenY < 50)
{
alert("Closing in on Top");
}
else //Only do bottom calculations if needed
{
var orientation=parent.window.orientation;
var landscape=(orientation==0 || orientation==180)?true:false;
//height - (height - availHeight) is the same as just using availHeight, so just get the screen height like this
var screenHeight = !landscape ? screen.availHeight : screen.availWidth;
var bottomOffset = screenHeight - touch.screenY; //Get the distance of the touch from the bottom
if (bottomOffset < 50)
alert("Closing in on Bottom");
}
That's actually not bad. You could also use Zepto.js and its built-in touch events and .offset() method to get it a little easier:
http://zeptojs.com/#touch
http://zeptojs.com/#offset
However, I'm interested to know whether or not you actually manage to get it scrolling at the bottom, and if the performance is smooth enough to make the effect worthwhile. (frequently scrolling in iOS interrupts JavaScript really hard)
Im trying to figure out best practices in regard to performance when creating multiple DIV's at an insane rate. For example, on every .mousemove event...
$('head').append("<style>.draw {width: 20px; height: 20px; position:fixed;</style>");
$(document).mousemove(function(mouseMOVE) {
//current mouse position
var mouseXcurrent = mouseMOVE.pageX;
var mouseYcurrent = mouseMOVE.pageY;
//function to create div
function mouseTRAIL(mouseX, mouseY, COLOR) {
$('body').append("<div class='draw' style='top:" + mouseY + "px; left:" + mouseX + "px; background: " + COLOR + ";'></div>");
}
// function call to create <div> at current mouse positiion
mouseTRAIL(mouseXcurrent, mouseYcurrent, '#00F');
// Remove <div>
setTimeout(function() {
$('.draw:first-child').remove();
}, 250);
});
So, this works all nice and dandy but it's mega inefficient (especially so when I try filling in the space between each mouse move position). Here's an example...
$('head').append("<style>.draw {width: 20px; height: 20px; position:fixed;</style>");
$(document).mousemove(function(mouseMOVE) {
//current mouse position
var mouseXcurrent = mouseMOVE.pageX;
var mouseYcurrent = mouseMOVE.pageY;
// function to create div
function mouseTRAIL(mouseX, mouseY, COLOR) {
$('body').append("<div class='draw' style='top:" + mouseY + "px; left:" + mouseX + "px; background: " + COLOR + ";'></div>");
}
// function call to create <div> at current mouse positiion
mouseTRAIL(mouseXcurrent, mouseYcurrent, '#00F');
// variabls to calculate position between current and last mouse position
var num = ($('.draw').length) - 3;
var mouseXold = parseInt($('.draw:eq(' + num + ')').css('left'), 10);
var mouseYold = parseInt($('.draw:eq(' + num + ')').css('top'), 10);
var mouseXfill = (mouseXcurrent + mouseXold) / 2;
var mouseYfill = (mouseYcurrent + mouseYold) / 2;
// if first and last mouse postion exist, function call to create a div between them
if ($('.draw').length > 2) {
mouseTRAIL(mouseXfill, mouseYfill, '#F80');
}
// Remove <div>
setTimeout(function() {
$('.draw:first-child').remove();
$('.draw:nth-child(2)').remove();
}, 250);
});
I really cant figure out how to improve things. Believe me, Ive tried researching but it hasn't done much good... What I'm looking for is some suggestions, examples, or links to better practices...
Please note that I'm teaching myself to code. I'm a Graphic Design student and this is how I'm spending my summer out of class... Making little projects to teach myself JavasSript, fun stuff :)
Ive set up some jsfiddles to show what Im working on...
Mouse Trail, More Elements - Very Very Slow
Mouse Trail, Less Elements - Very Slow
Mouse Trail, Bare Bones - Slow
There are multiple bad practices going on here:
Using elements instead of Canvas
Using those elements via jQuery
Abusing that jQuery as if you were trying to make it slow on purpose
Stuffing all of the above inside a mousemove handler
The root issue here really is using elements instead of canvas. After fixing that, the interaction with DOM should become minimal and thus
fix the other points as well.
Also, those who claim that this works fine didn't check their CPU usage. On my Core I5-2500K one core is instantly maxed up which is ridiculous and unacceptable for something trivial like rendering a mouse trail on screen.
I can very well imagine this being very very slow on an older computer. So yes, it's smooth but at the cost of using amount of resources enough for 10-20+ tabs to do the same properly.
This takes 7-14% cpu for me when moving mouse around fast, this takes full 25%.
You should be careful not to cause a reflow and stick only to a repaint. -> When does reflow happen in a DOM environment?
So creating <div>s is no option. - But you don't need to :)
Just create as many <div>s as you will need in future and then reposition them. If you have them in an array you'd only need an integer that points to the current most one and on each mouse movement you'd increase that value (set it to 0 once it reaches the array lenght) and reposition the <div> that's pointed to by that number.
I've got a javascript slideshow at the top of my page. When a slide changes to the next image, I call another function to change the background colour of the page.
The client wants the background colour to stop changing when the slideshow is no longer in view, i.e. when the user has scrolled down the page.
Is there any way to detect if an element is no longer visible due to scrolling?
Test code in jQuery
function test() {
var $elem = $('.test');
var visibleAtTop = $elem.offset().top + $elem.height() >= $(window).scrollTop();
var visibleAtBottom = $elem.offset().top <= $(window).scrollTop() + $(window).height();
if (visibleAtTop && visibleAtBottom) {
alert('visible');
} else {
alert('invisible (at ' + (visibleAtTop ? 'bottom' : 'top') + ')');
}
}
Full working example at http://jsfiddle.net/9PaQc/1/ (Updated: http://jsfiddle.net/9PaQc/2/ )
P.S. This only checks for vertical scroll. For horizontal, just do the same with top replaced with left, Y -> X and height() -> width()
EDIT
Made it all the way jQuery (to ensure x-browser compatibility) by changing window.scrollY -> $(window).scrollTop()
You can use the jQuery $.scrollTop function, probably from a scroll event handler to script this.
Use the window.pageYOffset to determine scroll amount in window. Use current offset of the object to check if it is in view. Note that these values are mostly browser dependent, so first check if it exists then act on it.