I have a section of code that I have been fooling around with. The goal of the code is to have four buttons, when you press the open button a window is opened in the top left corner of the screen, when you press the move button the window is supposed to move in an infinite loop around the screen starting in the positive X direction and moving clockwise. I am having an issue with the window moving in the negative X direction. Whenever the widow reaches the bottom righthand corner of my computer screen it will just stop. I do not know how to fix it, I just figured I would put a negative symbol before the direction that I want it to move. The moving function is under var moveWindow.
<html>
<head>
<script>
var aWindow;
var current = 0;
function openWindow() {
aWindow = window.open("", "", "width=400, height = 200");
aWindow.document.write("This is my new Window");
}
function closeWindow(){
if(aWindow) {
aWindow.close();
}
}
var moveWindow = function windowMove() {
var rightLimit = screen.width -400;
var topLimit = screen.height - screen.availHeight;
var bottomLimit = screen.height - 200;
if (aWindow) {
if (aWindow.screenY <= topLimit && aWindow.screenX != rightLimit) {
aWindow.moveBy(100, 0)
}
else if (aWindow.screenX <= rightLimit && aWindow.screenY != topLimit) {
aWindow.moveBy(0, 100)
}
else if (aWindow.screenY <= topLimit && aWindow.screenX != rightLimit) {
aWindow.move(-100, 0)
}
else if (aWindow.screenX <= rightLimit && aWindow.screenX != topLimit) {
aWindow.move(0, -100)
}
}
}
function startWindow(){
timer = setInterval(moveWindow, 350);
}
function stopWindow() {
clearInterval(startWindow)
}
</script>
</head>
</script>
</head>
<body>
<button onclick="openWindow();">Open</button>
<button onclick="closeWindow();">Close</button>
<button onclick="startWindow();">Move</button>
<button onclick="stopWindow();">Stop</button>
</body>
</html>
There are several issues with your conditions:
The inequality (!=) will often be true also when you reached the border. This is because the window does not stop exactly at the offset you had planned for it.
The outer window size is greater than 400x200 pixels, as there are borders. This makes the values you currently have for rightLimit (and other such variables) too tight.
You are testing for topLimit but never for bottomLimit. Also there is no provision for something like leftLimit.
You pass the wrong variable to clearInterval
Because of several metrics which influence the position of the popup window (like border, minimum distance from the screen's end, ...etc), it will be hard to determine where exactly it bumps into a side. As Windows will not let the popup window go outside of the screen, it will be easier to just let the popup window move and see if it actually did move. In case it didn't, then you know the side was reached and the direction should change.
It will also be easier the maintain the current direction in a variable instead of trying to detect what the current direction is based on the coordinates.
For detecting whether the window actually moved, you need a small time delay to allow the move to happen, so I would introduce a setTimeout for that. But otherwise the code can be much simplified:
var aWindow;
var current = 0; // We will use this to denote the current direction
function openWindow() {
aWindow = window.open("", "", "width=400, height = 200");
aWindow.document.write("This is my new Window");
}
function closeWindow(){
if (aWindow) {
aWindow.close();
}
}
var moveWindow = function windowMove() {
if (aWindow) {
var x = aWindow.screenX;
var y = aWindow.screenY;
aWindow.moveBy([100,0,-100,0][current], [0,100,0,-100][current]);
setTimeout(function () {
if (x === aWindow.screenX && y === aWindow.screenY) { // nothing moved
current = (current + 1) % 4; // next direction
windowMove(); // call an extra time to make the move in the next direction
}
}, 50);
}
}
var timer; // better declare it
function startWindow(){
timer = setInterval(moveWindow, 350);
}
function stopWindow() {
clearInterval(timer); // <--- timer
}
Related
I ran across an issue where my code worked just fine in Chrome but in Safari it began to stutter. I read somewhere that "Safari caps intervals at 1000ms and then adds its own exponential delay, doubling every iteration." That being said I am trying to change my code to work both on Safari and Chrome using requestAnimationFrame but am having issues wrapping my head around the subject.
Essentially what I am trying to do is ease a div across a page with each click using requestAnimationFrame instead of setInterval.
Any guidance would be appreciated.
Here is the Javascript:
let progressAvatar = document.querySelector('.box');
progressAvatar.addEventListener('click', checkClick);
var clicks = 0;
function checkClick() {
clicks += 1;
if (clicks == 1) {
startingLocationOfAvatar();
} else if (clicks == 2) {
locationOfAvatar();
}
}
function startingLocationOfAvatar() {
let speed = 10;
// Initial location of Avatar
let pos = 0;
// Ending location of Avatar
let progressBarWidthDivided = 53;
let id = setInterval(frame, speed);
function frame() {
if (pos == progressBarWidthDivided) {
clearInterval(id);
} else {
pos++;
progressAvatar.style.marginLeft = pos + "px";
}
}
}
// Move the avatar based on its previous location
function locationOfAvatar() {
let speed = 10;
// Pos becomes last location of movePixels
let pos = 53;
let id = setInterval(frame, speed);
// movePixels adds last location by its new location
let movePixels = pos * 2;
function frame() {
if (pos == movePixels) {
clearInterval(id);
} else {
pos++;
progressAvatar.style.marginLeft = pos + "px";
}
}
}
Here is the Html:
<div class="box">
</div>
Here is the Css:
.box {
height: 100px;
width: 100px;
background-color:red;
}
Lastly here is a jsfiddle:
Move Div Across Screen
I will let experts answer, but as a 2 weeks coding noob this is what i know, you can compile all individual animation functions into a grand Animation function. And call that function with request animation frame. Trying to make a sensible game myself, i have totally given up on manipulating css values and coding in pure Javascript.
Note, dependent where you will put your mini-functions - the photos/graphical items will display either on top or under eachother visually.
It should look something like this:
function drawEverything(){
context.clearRect(0,0,width,height);
context.save();
draw();
draw1();
draw2();
context.restore();
requestAnimationFrame(drawEverything);
}
requestAnimationFrame(drawEverything);
I have an absolutely positioned div that uses the jQuery .animate function to move horizontally from the right to left of the screen.
My problem is that once the div reaches the far left side, it continues and eventually disappears from the screen. How do you make it so that once the div reaches the left side, it will reverse and start going to the right? (and then vice versa so that the right side won't continue going right, but goes left again once it reaches the end)
HTML:
<div class="container">
<div class="block"></div>
</div>
CSS:
.block {
float:right;
position:absolute;
right:100px;
width:100px;
height:100px;
background:red;
}
jQuery:
$('.block').click(function() {
$(this).animate(
{"right": "+=100px"},"slow");
});
Here is my JSFiddle: https://jsfiddle.net/ebkc9dzL/
Thank you I really appreciate the help!
may be you should try like this:
$('.block').click(function() {
var leftPosition = $(this).position();
if (leftPosition.left > 100) {
$(this).animate({"right": "+=100px"},"slow");
} else {
$(this).animate({"right": "-=100px"},"slow");
}
});
when the element is close to the border the if..else part of the code will reverse the direction.
Here is a fiddle, try to click on the red box to get an idea on how it works:
https://jsfiddle.net/dimitrioglo/ebkc9dzL/14/
Working fiddle: https://jsfiddle.net/ebkc9dzL/19/
You need to have a variable outside the click function that will tell you the direction of the animation, so that once inside the click function you can calculate the location of the animated object using getBoundingClientRect() (mdn reference).
Then, if object is moving left and its left distance is less than its own width, you need to move it only enough so that it comes to the edge. If it's AT the edge (left is zero), you need to change the direction.
If it's moving right and its right distance is less than its own width, you need to move it only enough (calculated by window.innerWidth - 100, since 100 is width of your object) so that it comes to the edge. If it's AT the right edge, you need to change direction.
Changing direction in object you pass to jQuery's animate function is a simple matter of adding or subtracting from its "right" attribute.
var direction = "+";
$('.block').click(function() {
var obj = {},
distance = 100,
rect = this.getBoundingClientRect();
if(direction=="+"){
if(rect.left>0 && rect.left < 100)
distance = rect.left;
else if(rect.left<=0)
direction = "-";
}
else {
if(rect.right >(window.innerWidth-100) && rect.right+1<window.innerWidth)
distance = (window.innerWidth-rect.right);
else if(rect.right+1 >=window.innerWidth){
direction = "+";
}
}
obj = {"right": direction+"="+distance.toString()+"px"}
$(this).animate(obj,"slow");
});
Here you go: jsFiddle.
The new javascript is as follows:
var goLeft = true;
$('.block').click(function() {
var animateDist = 100;
var distLeft = $(this).position().left;
var distRight = window.innerWidth - distLeft;
if (goLeft) {
if (distLeft < 100) {
animateDist = "+="+distLeft+"px";
$(this).animate(
{"right": animateDist},"slow"
);
goLeft = false;
} else {
$(this).animate(
{"right": "+=100px"},"slow"
);
}
} else {
if (distRight < 100) {
animateDist = "-="+distRight+"px";
$(this).animate(
{"right": animateDist},"slow"
);
goLeft = true;
} else {
$(this).animate(
{"right": "-=100px"},"slow"
);
}
}
});
This isn't perfect, you need to adjust your internal window width to match the parent container, but this is enough to get you in the right direction.
Good luck!
Try this code:
var sign = [ "+" , "-" ];
var signPosition = 0;
var maxOffset = $(".block").offset().left;
$('.block').click(function() {
if ($(this).offset().left < 100) {
signPosition = 1;
} else if ($(this).offset().left == maxOffset) {
signPosition = 0;
}
$(this).animate(
{"right": sign[signPosition] + "=100px"},"slow");
});
The variable sign is the array that contains the directions in which the element might move, the variable signPosition contains the position of the direction currently in use, the variable maxOffset contains the starting position.
Hope this will help you.
I created a site which is devided vertically into two columns (each one half of the screen). If I scroll down, having the cursor on any position on the site, the left column should behave normal and scroll down, at the same the right column should scroll up in the opposite direction.
I came along this question – Modify scroll direction – and tried to get a solution out of it, but I cant get it working.
This is what I tried: http://jsbin.com/UJEBohu/1/edit
I've made a working solution, here: http://jsfiddle.net/QDUyR/1/
Put this in your <body> onload event and you should be set :)
// Add event listener for scrolling
$("#left").on("scroll", function () {
var scrolledleft = parseInt($("#left").scrollTop()) * -1;
console.log(scrolledleft + scrolledright)
$("#right").scrollTop(scrolledleft + scrolledright)
})
//Move right column to bottom initially
$("#right").scrollTop($("#right").height())
//Get actual distance scrolled
var scrolledright = parseInt($("#right").scrollTop())
Edit: Updated to work no matter what height the div's have, as long as they are equal.
The different browsers all scroll a different amount each time you scroll.
Here's my updated fiddle i have not tried it yet in safari.
I'm using a bind on the mouse wheel because Mozilla's scroll event fires multiple times every time you scroll once.
First I check to see which browser we are using and setting how much each scroll will be for that browser. Then I calculate how much to move the right div based on the amount to scroll for each browser.
In the mouse wheel event I check to make sure the right div does not go to far below or above the screen.
I'm using event.originalEvent.detail to tell which direction the mouse wheel is going in mozilla, and in IE and Chrome I am using event.originalEvent.wheelDelta.
Below is the code.
$(function()
{
if (navigator.userAgent.indexOf('Firefox') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Firefox') + 8)) >= 3.6)
{
//Firefox
var eachScroll = 114;
}
else if (navigator.userAgent.indexOf('Chrome') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Chrome') + 7).split(' ')[0]) >= 15)
{
//Chrome
var eachScroll = 100;
}
else if(navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Version') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Version') + 8).split(' ')[0]) >= 5)
{
//Safari
}
else
{
//IE
var eachScroll = 94;
}
var windowHeight = $(window).height();
var containerHeight = $("#container").height();
var heightLeftover = containerHeight - windowHeight; // Actual amount left to scroll
var totalScrolls = heightLeftover / eachScroll; // Total number of scrolls
totalScrolls = Math.ceil(totalScrolls); // Always round up
var amountToScroll = ($("#right").height() - containerHeight) / totalScrolls;
// Amount that right div will move every time we scroll
$(window).bind("mousewheel DOMMouseScroll", function(event){
var top = $("#right").position().top;
if(event.originalEvent.wheelDelta) // Check if wheelDelta exists
{
if(event.originalEvent.wheelDelta == - 120)
{
if(top < 2)
$("#right").css({top: top + amountToScroll});
}
else
{
if(top > -2000)
$("#right").css({top: top - amountToScroll});
}
}
else if(event.originalEvent.detail) // check if detail exists
{
if(event.originalEvent.detail == 3)
{
if(top < 2)
$("#right").css({top: top + amountToScroll});
}
else
{
if(top > -2000)
$("#right").css({top: top - amountToScroll});
}
}
});
});
I have a function to follow the object after the mouse,
and I want to be able to stop and start following at will, without hiding the object.
It almost works as I wanted, and is following the mouse indeed, but I cannot make it move initial position without actually moving the mouse.
E.G. When I trigger the function, the object is still somewhere in another place, until I move the mouse, but what I'm trying to do is to move it the initial position first, before attaching the mousemove event.
Here is how I want to trigger the function:
showtrail();
function showtrail(shit){
//this is how I tried to set the initial position first, but this get me an error:..
//followmouse();
document.onmousemove=followmouse; //and this is how I attach the event.
}
This is a part of the actual function to move the object,
but, I can't get the coordinates if I try to initilize/imitate the first movement.
function followmouse(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
if (typeof e != "undefined"){ //This- if triggered by mousemove, and it works
xcoord+=e.pageX
ycoord+=e.pageY
}
else { //this was meant for the initial call, but... for some reason
xcoord+=document.body.scrollLeft+event.clientX // it triggers an error,
ycoord+=document.body.scrollTop+event.clientY // saying event.clientX undefined.
}
}
So the event.clientX never seems to work, and I cannot figure out how to get the actual mouse position otherwise..
Please guide..
event.clientX and event.clientY are wrong. They should be e.clientX and e.clientY
A more elegant cross browser way to get xcoord and ycoord in followmouse(e) is:
xcoord = e.pageX||(e.clientX+(document.body.scrollLeft||document.documentElement.scrollLeft));
ycoord = e.pageY||(e.clientY+(document.body.scrollTop||document.documentElement.scrollTop));
Now if I'm getting it right, the object that follows is expected to have an initial absolute position and displayed as a block, meaning that you have initial x and y (left and top). Therefore by using a global bool var for currently following or not you're done.
<style>
...
#trail {position:absolute;left:0;top:0;display:none}
...
</style>
<script>
var following = false;
...
function followmouse(e){
if (!following){
document.getElementById('trail').style.display='none';
return;
}
...
document.getElementById('trail').style.display='block';
}
</script>
By changing display you have the option to move your #trail to its initial position and then follow the mouse, and the option to avoid the move and let it follow the mouse from its latest following position.
EDIT 1:
For this very purpose, I recommend using of requestAnimationFrame API, not classic DOM events. said API is more efficient for creating animations and pausing them.
take a look at this too: requestAnimationFrame for smart animating
This is sad, but true that you can not get mouse's initial position before moving mouse on a webpage. I mean you can't calibrate your object before mousemove event. this is what I will do in a similar project:
<!DOCTYPE html>
<html>
<head>
<title>Title</title>
<script type="text/javascript">
var targetID = 'mydiv'; // div that is to follow the mouse
var pauseFollowing = false;
// (must be position:absolute)
var offX = 15; // X offset from mouse position
var offY = 15; // Y offset from mouse position
function mouseX(evt) {if (!evt) evt = window.event; if (evt.pageX) return evt.pageX; else if (evt.clientX)return evt.clientX + (document.documentElement.scrollLeft ? document.documentElement.scrollLeft : document.body.scrollLeft); else return 0;}
function mouseY(evt) {if (!evt) evt = window.event; if (evt.pageY) return evt.pageY; else if (evt.clientY)return evt.clientY + (document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop); else return 0;}
function follow(evt) {
if(pauseFollowing) {
//or do something else at pause
return false;
}
var obj = document.getElementById(targetID).style;
obj.visibility = 'visible';
obj.left = (parseInt(mouseX(evt))+offX) + 'px';
obj.top = (parseInt(mouseY(evt))+offY) + 'px';
}
function toggleFollow() {
pauseFollowing = !pauseFollowing;
}
window.onload = function() {
window.onclick = toggleFollow;
document.onmousemove = follow;
}
</script>
</head>
<body>
<div id="mydiv" style="visibility: hidden; top:0; left:0 ;width: 100px; height: 100px; background: #ff0; position: absolute;"></div>
</body>
</html>
Alright that's how I done it.
The best Idea was to always capture a move to set position in a global var.
Now I have an option to display it fixed at any specific place (if I pass coords to showtrail)
or to actually follow the mouse;
I also added an event listener, so if the mouse gets outside the window while following- it will be hidden.
So far it works exactly as I wanted:
var trailimage=["scripts/loading_mouse.gif", 24, 24] //image path, plus width and height
var offsetfrommouse=[2,10] //image x,y offsets from cursor position in pixels. Enter 0,0 for no offset
var global_coord=[0,0]
var follow=false;
if (document.getElementById || document.all)
document.write('<div id="trailimageid" style="z-index: 10;position:absolute;display:none;left:0px;top:0px;width:1px;height:1px"><img src="'+trailimage[0]+'" border="0" width="'+trailimage[1]+'px" height="'+trailimage[2]+'px"></div>')
function gettrailobj(){
if (document.getElementById)
return document.getElementById("trailimageid").style
else if (document.all)
return document.all.trailimagid.style
}
function hidett(){ gettrailobj().display="none"; }
function showtt(){ gettrailobj().display="block"; }
function truebody(){ return (document.body||document.documentElement); }
function showtrail(shit){
if (typeof shit == "undefined"){ //Follow Mouse
follow=true;
setmousepos(global_coord[0],global_coord[1]);
}
else { //Set fixed in specific place
follow=false;
showtt()
gettrailobj().left=shit.left+6+"px"
gettrailobj().top=shit.top-5+"px"
}
}
function hidetrail(){
hidett()
follow=false;
}
function setcoord(e){
var xcoord=offsetfrommouse[0]
var ycoord=offsetfrommouse[1]
var xxcoord = e.pageX||(e.clientX+truebody().scrollLeft);
var yycoord = e.pageY||(e.clientY+truebody().scrollTop);
if (typeof xxcoord != "undefined"&&typeof yycoord != "undefined"){
xcoord+=xxcoord;
ycoord+=yycoord;
global_coord=[xcoord,ycoord];
if (follow) setmousepos(xcoord,ycoord);
}}
function setmousepos(xcoord,ycoord){
var docwidth=truebody().scrollLeft+truebody().clientWidth
var docheight=Math.max(truebody().scrollHeight, truebody().clientHeight)
if ((xcoord+trailimage[1]+3>docwidth || ycoord+trailimage[2]> docheight ||!follow)){
hidett()
}
else{
showtt();
gettrailobj().left=xcoord+"px"
gettrailobj().top=ycoord+"px"
}
}
window.addEventListener("mouseout",
function(e){
mouseX = e.pageX;
mouseY = e.pageY;
if ((mouseY >= 0 && mouseY <= window.innerHeight)
&& (mouseX >= 0 && mouseX <= window.innerWidth)){
return false;
}else{
if (follow) hidett()
}
},
false);
document.onmousemove=setcoord;
I'm wondering if there is a simple way to make use of JavaScript (probably jQuery too?) in order to make the contents of a fixed-height div element scroll infinitely up and down (top, bottom, top, bottom, etc) when the page loads and without any user input or manipulation?
Thanks ahead of time, any input is greatly appreciated as I am hardly mediocre with JavaScript.
With pure js you can do something like this:
var scroller = document.getElementById('scroller');
var delta = 15;
var lastSc;
//console.log(scroller.scrollTop, scrollHeight);
setInterval(function(){
var sc = scroller.scrollTop + delta;
scroller.scrollTop = sc;
if (scroller.scrollTop === lastSc){
delta = delta*(-1);
}
lastSc = scroller.scrollTop;
}, 10);
Here is demo
Edit: updated demo
Here is something I've just written, using jQuery:
var speed = 100; //smaller means faster
var offset = 5; //bigger means more text will be "scrolled" every time
function ScrollMyDiv() {
var myDiv = $("#MyDiv");
var direction = myDiv.attr("scroll_dir") || "";
var lastScrollTop = parseInt(myDiv.attr("last_scroll_top") || "0", 10);
if (direction.length === 0) {
myDiv.attr("scroll_dir", "down");
direction = "down";
}
var top = myDiv.scrollTop();
myDiv.attr("last_scroll_top", top + "")
if (direction === "down") {
if (top > 0 && lastScrollTop === top)
myDiv.attr("scroll_dir", "up");
top += offset;
} else {
if (top <= 0)
myDiv.attr("scroll_dir", "down");
top -= offset;
}
myDiv.scrollTop(top);
window.setTimeout(ScrollMyDiv, speed);
}
$(document).ready(function() {
ScrollMyDiv();
});
Live test case: http://jsfiddle.net/HmfNJ/1/
Basically, it will start by scrolling down (adding to the scrollTop) then when it identify it reached the bottom by seeing the scrollTop remains the same, it will change direction and start scroll up.
Thanks for the replies but I found my answer elsewhere. Here's what I ended up using: http://jsbin.com/onohan/3/edit#preview
It had a couple of small problems but I at least knew enough about basic JavaScript to fix them. Hopefully this will benefit someone in the future. :)
To get a smooth transition for scroll to bottom this is VanillaJS code that works well with me
var delta = 0.6, interval;
interval = setInterval(function(){
window.scrollBy(0, delta);
}, 20);
To clear the Interval you can run
clearInterval(interval);