I want to detect clicks and move elements from off-screen right to off-screen left with jquery.
I achieved the general idea already (fiddle) but only for one div, once.
HTML:
<div class = "outer">
<div id = "box">
</div>
</div>
CSS:
body {
overflow-x: hidden;
height: 500px;
}
#box{
height: 100px;
width: 100px;
background: #FF00FF;
position: absolute;
right: -100px;
}
JS:
$(document).ready(function(){
$(document).click(function(){
var bodyHeight = document.body.clientHeight;
var randPosY = Math.floor((Math.random()*bodyHeight));
$('#box').css('top', randPosY);
$("#box").animate({left: '-100px'}, 5000);
});
});
How can make a new instance div appear (at random y-position) per click on the document?
My random y-position is calculated in jQuery the following way, but gets its value from my css height: 500px; - how can I make this value responsive?
Use a function constructor to add object instances of a div, where each one uses .box class instead of #box:
fiddle
function SlidingDiv(bodyHeight){
this.randPosY = Math.floor((Math.random()*bodyHeight));
this.$div = $("<div>").addClass('box').appendTo('.outer');
};
SlidingDiv.prototype.slide = function(){
this.$div.css('top', this.randPosY);
this.$div.animate({left: '-100px'}, 5000);
};
$(document).ready(function(){
$(document).click(function(){
var bodyHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
var div = new SlidingDiv(bodyHeight);
div.slide();
});
});
Edit: To remove divs, you could try the complete function:
SlidingDiv.prototype.slide = function() {
this.$div.css('top', this.randPosY);
this.$div.animate({
left: '-100px',
duration: 5000,
complete: function() { this.$div.remove(); }.bind(this)
});
};
Related
I am trying to make a code learning app (like scratch but not block based) where users write code to create games and animations. I have given them a series of commands which they can use in any desired order to create an animation sequence on multiple characters.
So far, I have no issues applying animations on a single character. However when two or more characters (two divs) come in a picture, the animations are executed parallelly instead of sequentially
example:
$("#div1").turnLeft();
$("#div1").moveForward()
$("#div2").moveForward () // this should run when first two are complete
$("#div3").moveForward() // this should run when first three are complete
The challenge is the order of commands is not fixed. User may use commands in any order.
How do I make sure the commands entered by users are run one after another?
Thanks
you must do it in call back function of each animation
$("#div1").animate({...},()=>{
$("#div1").animate({...},()=>{
$("#div2").animate({...},()=>{
$("#div3").animate({...})
})
})
});
this is a simple sample for more explain:
$("button").click(function(){
$("div").animate({
left: '250px',
opacity: '0.5',
height: '150px',
width: '150px'
},()=>{alert("finish")});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button>Start Animation</button>
<p>By default, all HTML elements have a static position, and cannot be moved. To manipulate the position, remember to first set the CSS position property of the element to relative, fixed, or absolute!</p>
<div style="background:#98bf21;height:100px;width:100px;position:absolute;"></div>
You can use jquery's queue to queue animations against a different element, then they all queue in a single queue.
Adapting this answer and the info on the jquery help applying this to "body" gives you:
$.fn.moveToX = function(pos) {
var el = $(this);
$("body").queue(
function() {
el.animate({
left: pos + "px"
}, 500, () => {
$.dequeue(this);
});
});
}
$.fn.moveToY = function(pos) {
var el = $(this);
$("body").queue(
function() {
el.animate({
top: pos + "px"
}, 500, () => {
$.dequeue(this);
});
});
}
$("#d1").moveToX(100);
$("#d2").moveToX(200);
$("#d1").moveToY(50);
$("#d2").moveToY(100);
$("#d1").moveToX(0);
$("#d2").moveToX(0);
$("#d1").moveToY(0);
$("#d2").moveToY(0);
div {
position: absolute;
width: 50px;
height: 50px;
border: 1px solid magenta;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='d1'>1</div>
<div id='d2'>2</div>
To have multiple "single" queues (ie multiple queues that can have different elements applied to them (to give parallel animations)) you can supply the "queue[name]" parameter, eg:
$("body").queue("q1", function() { ...
$("body").queue("q2", function() { ...
so your move methods can be easily extended to provide parallel animations
$.fn.moveToX = function(pos, q) {
var el = $(this);
$("body").queue(
q || "fx",
function() {
el.animate({
left: pos + "px"
}, 500, () => {
$.dequeue(this, q);
});
});
}
$.fn.moveToY = function(pos, q) {
var el = $(this);
$("body").queue(
q || "fx",
function() {
el.animate({
top: pos + "px"
}, 500, () => {
$.dequeue(this, q);
});
});
}
$("#d1").moveToX(100);
$("#d2").moveToX(200);
$("#d1").moveToY(50);
$("#d2").moveToY(100);
$("#d1").moveToX(0);
$("#d2").moveToX(0);
$("#d1").moveToY(0);
$("#d2").moveToY(0);
$("#d3").moveToX(250, "q3");
$("#d3").moveToY(50, "q3");
$("#d3").moveToX(300, "q3");
$("#d3").moveToY(0, "q3");
$("body").dequeue("q3"); // queue "fx" auto dequeues
div {
position: absolute;
width: 50px;
height: 50px;
border: 1px solid magenta;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='d1'>1</div>
<div id='d2'>2</div>
<div id='d3' style='left:300px;'>3</div>
I know how to fix the animation that goes down only when the image is showing up in the window with jQuery, but now I want to do that with JavaScript. Struggling with that. The image must be fluently go down (+50px for 1.6 seconds). Have googling around, but most of them are done with jQuery I suggest and that is not what I want. Furtermore the animation should start when the scrollTop is between 600px and 800px.
function scrollFunction() {
var animate = document.getElementById("picture");
var position = 0;
var top = 0;
var scrollTop = window.pageYOffset || document.documentElement.scrollTop;
if(scrollTop > 600 && scrollTop < 800){
position++;
animate.style.top = position + "50px";
} else {
stop();
}
}
function stop() {
clearTimeout(animate);
}
#picture {
width: 100%;
height: auto;
top: -5px;
position: relative;
display: block;
margin-left: auto;
margin-right: auto;
margin-bottom: 20px;
}
<div class="col-sm-12 col-xs-12">
<h1 class="responsive-h1">Mi<span class="logo-orange"> Pad2</span></h1>
<p class="edition-title above-text-black">Black Edition</p>
<img src="Img/picture.jpg" id="picture"/>
</div>
jsFiddle : https://jsfiddle.net/n1q3fy8w/
Javascript
var imgSlide = document.getElementById('slidedown-image');
var slideDown = setInterval(function() {
var topVal = parseInt(window.getComputedStyle(imgSlide).top, 10);
imgSlide.style.top = (topVal + 1) + "px";
}, 15);
setTimeout(function( ) { clearInterval( slideDown ); }, 1600);
You get the element first, after that you setup a setInterval which will basically move our img downwards, we then also set a setTimeout which after 1600ms remvoes the slideDown interval and the image stops. Your image however may need position: absolute.
The above answer will only work in Chrome, this however should work in all browswers
jsFiddle : https://jsfiddle.net/n1q3fy8w/1/
javascript
var imgSlide = document.getElementById('slidedown-image');
var slideDown = setInterval(function() {
var topVal = parseInt(imgSlide.style.top, 10);
imgSlide.style.top = (topVal + 1) + "px";
}, 15);
setTimeout(function( ) { clearInterval( slideDown ); }, 1600);
Ok so getComputedStyle only works in chrome, so to get this to work on all other browsers, you have to specifically set the css property on the element and not via CSS.
When you use javascript to access an element and change its style like so element.style.bottom = '150px' the .style gets you all of the css values for your inline styles on that element, so any css changes on an element that is done via a .css/.less file you can't access via javascript.
So all the above code does is we set a top: 0 on the element itself and in our code we use imageSlide.style.top instead of chrome's window.getComputedStyle
Have you considered using a CSS transition? if you are changing the value of top you should be able to add transition: top 1.6s in your css (to picture). (Then the vendor prefixed versions when you get it working)
Say my image (panoramic) is 10,000 pixels long, but I want to be able to view only 1000 pixels wide at a time, and in order to view more of it, I can just hover my mouse either left or right, and then the image will move accordingly please? If possible, a simple script on HTML? (I'm not sure how to use Javascript or CSS, but if it needs to come down to that, do guide me step by step?
Thank you.
Here is a simple JQuery which you can use to scroll the whole page when hovering over either the left or right;
Example - https://jsfiddle.net/38da9pca/
Need any help implementing it just leave a comment and I will try and help you.
$(function() {
$('#right').on('mouseenter', rscroll);
$('#left').on('mouseenter', lscroll);
$('#right, #left').on('mouseleave', function() {
$('body').stop();
});
function rscroll() {
$('body').animate({
scrollLeft: '+=25'
}, 10, rscroll);
}
function lscroll() {
$('body').animate({
scrollLeft: '-=25'
}, 10, lscroll);
}
});
Edit (Scroll Image Only)
Example - https://jsfiddle.net/38da9pca/1/
I have change it so the lscroll and the rscroll will effect the id of image instead of the body and change it from scrollLeft to left, and that way it will move the images scroll. Dont forgot to change the $('body').stop(); to $('#bg').stop(); or it will never stop scrolling
$(function() {
$('#right').on('mouseenter', rscroll);
$('#left').on('mouseenter', lscroll);
$('#right, #left').on('mouseleave', function() {
$('#bg').stop();
});
function rscroll() {
$('#bg').animate({
left: '-=25'
}, 10, rscroll);
}
function lscroll() {
$('#bg').animate({
left: '+=25'
}, 10, lscroll);
}
});
Here's one. It's using jquery (javascript library). You would have to add it in order to make it work.
Example:
http://www.gayadesign.com/scripts/jqueryphotonav/
Tutorial:
https://blog.gaya.ninja/articles/jquery-convertion-panoramic-photoviewer-in-javascript/
Something like this?
var imgView = document.querySelectorAll('.img-view')[0];
var img = imgView.querySelectorAll('img')[0];
imgView.onmousemove = function(e) {
var x = e.clientX;
var px = ((x / this.offsetWidth) * 100);
var ix = ((px / 100) * img.offsetWidth);
img.style.left = '-' + (ix - this.offsetWidth) + 'px';
}
.img-view {
width: 256px;
height: 160px;
overflow: hidden;
position: relative;
border: 1px solid #ddd;
}
.img-view img {
height: 100%;
position: relative;
top: 0;
left: 0;
}
<div class="img-view">
<img src="http://panoramalove.com/wp-content/uploads/2013/01/nighttime-panoramic-view-of-hong-kong-island-from-the-avenue-of-stars-in-tsim-sha-tsui.jpg">
</div>
I use backstretch on my website. Now trying to move the backgroudn automatically from left to right and back. But til now, it just moves in one direction. I'm lookig for a continous loop of that moving image.
How can I reset / move back the image??
backstretch.js: http://dev.disaster-kfw.com/fileadmin/template/js/slidebackground.js
some more javascript for moving-effect & initialisation
var images = ['fileadmin/template/gfx/background02-03.jpg'];
jQuery.backstretch( images[Math.floor(Math.random() * images.length)] );
jQuery(function($){
(function swoop(element) {
element
.animate({'margin-left':'-=5px'}, 100, function(){
setTimeout(function(){
swoop(element);
}, 0);
});
})($('#backstretch img'));
});
resulting this HTML output
<div id="backstretch" style="left: 0px; top: 0px; position: fixed; overflow: hidden; z-index: -999999; margin: 0px; padding: 0px; height: 100%; width: 100%;"><img src="fileadmin/template/gfx/background02-03.jpg" style="position: absolute; margin: 0px 0px 0px -3404.98890491151px; padding: 0px; border: none; z-index: -999999; width: 3006px; height: 835px; left: -551.5px; top: 0px;"></div>
sorry for posting the html code a littlt bit ugly, don't know to do it right...
EDIT:
Thanks a lot, but I think that's not what I need.
I think I need a calculation about image-width and margin-left to switch from moving-left to moving-right and back.
So I tried to calculate width of my image, but
iWidth = jQuery("#backstretch img").width();
is always NULL.
And
iWidth = $("#backstretch img").width();
breaks the whole javascript.
I thought it could be a solution to write a second function called backswoop for counting up the margin-left. And then do a condition about margin-left and image-width.
iWidth = jQuery('#backstretch img').width();
jQuery(function($){
(function swoop(element) {
element.animate({'margin-left':'-=5px'}, 50, function(){
setTimeout(function(){
if(element.css('margin-left')*-1 <= iWidth){
swoop(element);
}else{
backswoop(element);
}
}, 0);
});
})($('#backstretch img'));
(function backswoop(element) {
element.animate({'margin-left':'+=5px'}, 50, function(){
setTimeout(function(){
if(element.css('margin-left') >= 0){
swoop(element);
}else{
backswoop(element);
}
}, 0);
});
})($('#backstretch img'));
});
But, because I'm not great with javascript, it does not work :-(
Before you move the element, use jQuery .data() to store the original margin. That way when you want to reset you can animate the margin to that value.
This code isn't perfect. It's just to give you an idea of what you can do.
//I would avoid global variables, but I don't know enough of your code.
swoopingElement = $('#backstretch img');
swoopingElement.data("startingmargin", $('#backstretch img').css('marginLeft'));
(function swoop(element) {
element
.animate({'margin-left':'-=5px'}, 100, function(){
swoopingElement.data("timer", setTimeout(function(){
swoop(element);
}, 0));
});
})($('#backstretch img'));
function resetElement(element){
//First shut down any remaining animation
element.stop();
clearTimeout(element.data("timer")); //even though it's zero... it might be active.
//Send element back
element.animate({'margin-left':element.data("startingmargin")}, 100);
//Or for instant return.
// element.css({'margin-left':element.data("startingmargin")});
};
https://api.jquery.com/jquery.data/
I am relatively new to all this so if you see anything I am doing wrong, or anyways to simplify any code please do not hesitate to say.
I have the following code to enlarge the div element:
var profilePostsClick = function () {
$('.largeBox, .smallBox, .longBox').click(function () {
$(this).animate({
width: '100%',
height: '40%'
}, 200);
$('.closePost', this).removeClass('closePostHide');
});
};
$(document).ready(profilePostsClick);
https://jsfiddle.net/jvkhmpbt/
I am wanting to close each div when the cross is clicked, returning it to it's original size and positioning (with height: auto if feasible).
Aslo is there a way to make it so each div opens above the smaller ones? (like the top left div does, i am aware this is because of it's positioning)
Thanks
You can do like following way by adding and removing class
JQuery:
$('.largeBox, .smallBox, .longBox').click(function (e) {
e.preventDefault();
$(this).addClass('increaseSize');
$('.closePost', this).removeClass('closePostHide');
});
$('.glyphicon-remove').click(function (e) {
e.stopPropagation()
$('.glyphicon-remove').parent().parent().removeClass('increaseSize');
$('.closePost', this).addClass('closePostHide');
});
CSS:
.increaseSize{
width: 100%;
height: 40%;
}
Check Fiddle Here.
You could save the animation properties/values in an cache-object and restore them after your animation.
http://jsfiddle.net/jvkhmpbt/4/
var animationResetCache = [];
var saveValues = function (node) {
animationResetCache.push({
node: node,
width: node.css('width'),
height: node.css('height')
});
};
var restoreValues = function (node) {
for (var i = 0; i < animationResetCache.length; ++i) {
var item = animationResetCache[i];
if (item.node.is(node)) {
return item;
}
}
};
var profilePostsClick = function () {
$('.largeBox, .smallBox, .longBox').click(function (e) {
var $this = $(this);
if ($this.hasClass('open')) return;
saveValues($this);
$this.addClass('open').animate({
width: '100%',
height: '40%'
}, 200);
$this.find('.closePost').removeClass('closePostHide');
});
$('.closePost').click(function () {
var $parent = $(this).parent('.largeBox, .smallBox, .longBox');
if ($parent.hasClass('open')) {
var cachedValues = restoreValues($parent);
$parent.animate({
width: cachedValues.width,
height: cachedValues.height
}, function () {
$parent.removeClass('open');
});
$parent.find('.closePost').addClass('closePostHide');
}
});
};
$(document).ready(profilePostsClick);
I think it's easier to use a toggle and do the animation in CSS3
$("img").click(function(){
$(this).toggleClass('expanded');
});
I would suggest to add one more identical class to each of smallBox,largeBox and longBox which will be called parentd to identify parent div and animate it back and add below js:
DEMO
$('.closePost').on('click',function(e)
{
$(this).closest('.parentd')
.animate({
width: '40%',
height: 'auto'
},200).removeAttr('style');
$(this).addClass('closePostHide');
e.stopPropagation();
});
If we continue on Rover his answer, we can use the switchClass function in jQuery Ui. (source)
This function let's you switch the classes of an object, creating an animation in the difference between those classes.
Example code: jsFiddle
<div class="large"></div>
CSS:
.large{
width: 100%;
height: 200px;
background-color: red;
}
.small {
width: 10%;
height: 50px;
background-color:green;
}
JS:
$("div").switchClass("large","small",500);