I am trying to make a zoom-like effect on hover event in a gallery exercise. What I need is for an image to seem to expand from its center, not down and right. If I understood correctly, I need to move it half way left and up for this to work. Also, I'm using em, so I try to convert em to pixels here.
Relevant html:
<div id="gallery">
<img src="img/cool1.gif">
<img src="img/cool2.gif" id="gal2">
<img src="img/cool3.gif" id="gal3">
</div>
CSS:
#gallery {
width: 31em;
margin-left: auto;
margin-right: auto;
}
#gallery img {
width: 10em;
height: auto;
position: absolute;
}
#gal2 {
margin-left: 10em;
}
#gal3 {
margin-left: 20em;
}
Finally, jQuery:
var fontSize = $("#gallery img").css("font-size");//equal to 1em?
var fontInt = parseInt(fontSize);
var t = $("#gallery img").position().top;
var tNew = t - (5 * fontInt);//top position
var l = $("#gallery img").position().left;
var lNew = l - (5 * fontInt);//left position
$("#gallery img").hover(
function() {
$(this).stop().css("zIndex", "1").animate({
height : "20em",
width : "20em",
top : tNew,
left : lNew
}, 400);
}, //end mouseover
function() {
$(this).stop().animate({
height : "10em",
width : "10em",
top : t,
left : l,
zIndex : "0"
}, 400);
} //end mouseout
);//end hover
edit 1 Images expand and change position, but not as expected. Also, they don't return on mouseout. Thanks to Racil Hilan for solving em-px conversion problem!
edit 2 Problem moslty solved by fixing variable scope – position values moved before hover() function. The only remaining bug is that the pictures escape to the top right corner of the body before returning to their place on first interaction. Afterwards, it runs as expected. Also, could somebody explain why this works when the fontInt variable is multiplied by five, not by 10?
edit 3 – solution As Mauricio Santamaria said below, just add the css() function setting top and left parameters before hover on #gallery img element like so:
$("#gallery img").css({"top" : t, "left" : l}).hover(...);
The rest stays the same.
I improvised a fiddle for this, too: http://jsfiddle.net/dzenesiz/wudw5hmu/15/
The problem is that the $(this).css("font-size"); returns the size with the unit (e.g. 16px) which is not a number and the calculation results in a NaN.
A quick solution is to parse it to an integer like this:
var fontSize = parseInt($(this).css("font-size")); //equal to 1em?
to remove the "jump" when first interaction you should set "top" and "left" on your css, this removes that behavior (tested on your fiddle with 8px or 0.4em equivalent to your initial image size), and for your question about why 5 gets your desired result its that the result of that operation (5 * fontInt) gives you the initial value of images ie. 100px (10em), and that's the amount for top and left that you need to make it zoom from center. (the initial value for fontSize is 20em, initial t =8, so 8-100 = -92, the right value taking in account the margin )
Related
The closest solution I found is Show div on scrollDown after 800px.
I'm learning HTML, CSS, and JS, and I decided to try to make a digital flipbook: a simple animation that would play (ie, load frame after frame) on the user's scroll.
I figured I would add all the images to the HTML and then use CSS to "stack them" in the same position, then use JS or jQuery to fade one into the next at different points in the scroll (ie, increasing pixel distances from the top of the page).
Unfortunately, I can't produce the behavior I'm looking for.
HTML (just all the frames of the animation):
<img class="frame" id="frame0" src="images/hand.jpg">
<img class="frame" id="frame1" src="images/frame_0_delay-0.13s.gif">
CSS:
body {
height: 10000px;
}
.frame {
display: block;
position: fixed;
top: 0px;
z-index: 1;
transition: all 1s;
}
#hand0 {
padding: 55px 155px 55px 155px;
background-color: white;
}
.frameHide {
opacity: 0;
left: -100%;
}
.frameShow {
opacity: 1;
left: 0;
}
JS:
frame0 = document.getElementById("frame0");
var myScrollFunc = function() {
var y = window.scrollY;
if (y >= 800) {
frame0.className = "frameShow"
} else {
frame0.className = "frameHide"
}
};
window.addEventListener("scroll", myScrollFunc);
};
One of your bigger problems is that setting frame0.className = "frameShow" removes your initial class frame, which will remove a bunch of properties. To fix this, at least in a simple way, we can do frame0.className = "frame frameShow", etc. Another issue is that frame0 is rendered behind frame1, which could be fixed a variety of ways. ie. Putting frame0's <img> after frame1, or setting frame0's CSS to have a z-index:2;, and then setting frame0's class to class="frame frameHide" so it doesn't show up to begin with. I also removed the margin and padding from the body using CSS, as it disturbs the location of the images. I have made your code work the way I understand you wanted it to, here is a JSFiddle.
It depends on your case, for example, in this jsFiddle 1 I'm showing the next (or previous) frame depending on the value of the vertical scroll full window.
So for my case the code is:
var jQ = $.noConflict(),
frames = jQ('.frame'),
win = jQ(window),
// this is very important to be calculated correctly in order to get it work right
// the idea here is to calculate the available amount of scrolling space until the
// scrollbar hits the bottom of the window, and then divide it by number of frames
steps = Math.floor((jQ(document).height() - win.height()) / frames.length),
// start the index by 1 since the first frame is already shown
index = 1;
win.on('scroll', function() {
// on scroll, if the scroll value equal or more than a certain number, fade the
// corresponding frame in, then increase index by one.
if (win.scrollTop() >= index * steps) {
jQ(frames[index]).animate({'opacity': 1}, 50);
index++;
} else {
// else if it's less, hide the relative frame then decrease the index by one
// thus it will work whether the user scrolls up or down
jQ(frames[index]).animate({'opacity': 0}, 50);
index--;
}
});
Update:
Considering another scenario, where we have the frames inside a scroll-able div, then we wrap the .frame images within another div .inner.
jsFiddle 2
var jQ = $.noConflict(),
cont = jQ('#frames-container'),
inner = jQ('#inner-div'),
frames = jQ('.frame'),
frameHeight = jQ('#frame1').height(),
frameWidth = jQ('#frame1').width() + 20, // we add 20px because of the horizontal scroll
index = 0;
// set the height of the outer container div to be same as 1 frame height
// and the inner div height to be the sum of all frames height, also we
// add some pixels just for safety, 20px here
cont.css({'height': frameHeight, 'width': frameWidth});
inner.css({'height': frameHeight * frames.length + 20});
cont.on('scroll', function() {
var space = index * frameHeight;
if (cont.scrollTop() >= space) {
jQ(frames[index]).animate({'opacity': 1}, 0);
index++;
} else {
jQ(frames[index]).animate({'opacity': 0}, 0);
index--;
}
});
** Please Note that in both cases all frames must have same height.
I've been trying to solve this problem for a week now and it seems basic, so maybe I'm missing something.
I want to have a div centered on the screen (or its container), and then insert a second div to the right of it, so that afterwards the two of them are centered (space on each side is equal).
Inserting the second div is not a problem, but I need the first block to slide over to where its going to be after the new block is inserted.
http://jsfiddle.net/rdbLbnw1/
.container {
width:100%;
text-align:center;
}
.inside {
border:solid 1px black;
width:100px;
height:100px;
display:inline-block;
}
$(document).ready(function() {
$("#add").click(function() {
$(".container").append("<div class='inside'></div>");
});
});
<div class="container">
<div class="inside"></div>
</div>
<input id="add" type="button" value="add"/>
Do I need to explicitly calculate where the original box is going to end up and then animate that, or is there a better way to do it?
I like your question so decide to write this:
$(document).ready(function() {
var isInAction = false;
var intNumOfBoxes = 1;
var intMargin = 10;
$containerWidth = $(".container").width();
$insideWidth = $(".inside").width();
$(".inside").css('margin-left',($containerWidth - $insideWidth - intMargin)/2 + 'px');
$("#add").click(function() {
if (!isInAction){
isInAction = true;
intNumOfBoxes +=1;
$(".current").removeClass("current");
$(".container").append("<div class='inside current'></div>");
$('.inside').animate({
'margin-left': '-=' + ($insideWidth + intMargin)/2 + 'px'
}, 300, function () {
$(".current").css('margin-left',($containerWidth + ((intNumOfBoxes - 2) * ($insideWidth + intMargin)))/2 + 'px');
$(".current").fadeIn(500,function(){
isInAction = false;
});
});
}
});
});
Also add this class in CSS:
.current {
display:none;
}
You don't need to change variables in JS code except intMargin. you can change this var to set margin between boxes.
Note: This code works fine on older browsers too and not need to support CSS3 features like transition.
Update: Some bugs like repeated clicks fixed.
Check JSFiddle Demo
First, we can animate only things that have explicit numerical values such as width, left or margin. We can't animate things like alignment (which actually use the same margin property but implicitly, never mind). So if we know width of inserted div let's just add it to our container.
1) Let's centre container itself and add transition to it
.container {
width: 102px; /* set explicit width; 102 - because of borders */
margin: auto; /* set margin to 'auto' - that will centre the div */
transition: width 0.5s;
}
2) Then increase the width when add div
$(".container").width($(".container").width() + 102);
3) But wait! If we add div to too narrow container it will be added to bottom not to right. So we need another container set to appropriate width before.
See final example on JSFiddle.
BTW, remove all line breaks and tabs from your code when you use inline-block, because it will cause spaces between your blocks.
I have div called first which width can be dynamic and horizontally centered according margin left right to auto
.first
{
width:70%;
background-color:#5b9a68;
position:relative;
margin:0 auto;
}
Another div second with position fixed
.second
{
position:fixed;
background-color:black;
color:white;
left:input;
}
Html
<div class="first">content</div>
<div class="second">Left Value</div>
i want this second div to position according to first div.The Problem here is second div position is fixed so it is positioning according to screen width so i tried this script to position it according to first div.
$(document).ready(function(){
var input=0;
var first_width = $(".first").width() / $('.first').parent().width() * 100;
var pos = (100-first_width)/2;//getting the empty part
var ex_pos=pos+input;
$('.second').css("left",ex_pos+"%");
});
Here when the input is zero it should start at the start of first div this is fine but when we changed the input value am not getting accurate percentage positioning according to first div.
Let say for example if i give 50 as input then i'll place it on 65 but this way am not perfectly positioning in 50 of first div.Also if i give 100% as input this will go outside.
How to do this if input is 100 then the second div should be at the end of first div.
if the input is 50 it should be at middle of first like that.
Output With 0% left position
Output With 50% left position
Output With 100% left position
NOTE-I don't want to change or edit the css. i would like to do it in script alone.
Check Fiddle
Here you go :
$(document).ready(function () {
var input = 0,
firstWidth = $('.first').width(), // width of first div
secondWidth = $('.second').width(), // width of second div
offset = (input * (firstWidth - secondWidth)) / 100, // % to shift
leftPos = $('.first').offset().left; // left position of first div
$('.second').css("left", leftPos + offset);
});
JSFiddle
From jQuery API Documentation : Link
The .offset() method allows us to retrieve the current position of an element relative to the document.
It returns an object containing the properties top and left.
So :
leftPos = $('.first').offset().left;
This gives us the left co-ordinates for the .first div i.e the point where it starts.
I guess, you are looking for scenarios for 50% and 100% .
This should do it :
JS :
if(input===100){
ex_pos = ex_pos - 43;
}else if(input===50){
ex_pos = ex_pos - 13;
}
FIDDLE
I am trying get this background to fade in on click. I found one tutorial that was helpful, and I ended up created the code so it has two images, and they fade in and out on click to bring up the picture.
Here's the work: http://www.mccraymusic.com/bgchangetest.html
Only a couple of issues though:
How do I make this work without the images getting selected at random? I'd like it to just switch from the plain black image to the image with the drum set. (And cross-fade to if possible, but not necessary)
How do I center the image on the page, so the image of the drums are centered?
I'm guessing this is what you're after:
$(function() {
var images = ["black.jpg","bg.jpg"];
$('<img>').attr({'src':'http://www.mccraymusic.com/assets/images/'+images[0],'id':'bg','alt':''}).appendTo('#bg-wrapper').parent().fadeIn(0);
$('.entersite').click(function(e) {
e.preventDefault();
var image = images[1];
$('#bg').parent().fadeOut(200, function() {
$('#bg').attr('src', 'http://www.mccraymusic.com/assets/images/'+image);
$(this).fadeIn(1000);
});
$(this).fadeOut(1000, function() {
$(this).remove();
});
});
});
DEMONSTRATION
Also added :
display: block;
margin-left: auto;
margin-right: auto;
to your #bg element to center the image.
Alright, assuming you use JQuery
You have #backgroundid and #imageid
Begin by setting
$('#backgroundid').css('opacity',1);
$('#imageid').css('opacity',0); // setting opacity (transparency) to 0, invisible
Now you have #buttonid.
Set up a jquery event so that when it's clicked, you fade out the background, and fade in the image using JQuery's animate.
$('#buttonid').click(function() {
$('#backgroundid').animate(function() {
opacity : 0 // fade it to 0 opacity, invisible
}, 1000); // animation will take 1000ms, 1second
$('#imageid').animate(function() {
opacity : 1 // fade it to full opacity, solid
}, 1000);
});
Now about that image centering.
You can either let css manage it with
body { /* Body or #imageid parent */
text-align : center;
}
#imageid {
margin: 0px auto;
}
Or you can stick to a JQuery solution, using absolute/fixed positioning.
First, use some css to fix the position of your image
#imageid {
position: absolute; // or fixed, if you want
}
Now use JQuery to reposition it
function positionImage() {
var imagewidth = $('#imageid').width();
var imageheight = $('#imageid').height();
$('#imageid').css('left', ($(window).width() - imagewidth) / 2);
$('#imageid').css('top', ($(window).height() - imageheight) / 2);
}
$(document).ready(positionImage); // bind the ready event to reposition
$(window).resize(positionImage); // on window resize, reposition image too
if you keep a div element with height and width as 100% and bgcolor as black. And then change the opacity of the div as desired to get the fade in/out effect, that should generate the same effect. I guess..
You are better off using any available jQuery plugin as they would have optimized and fixed bugs for multiple browsers.
Try lightBoxMe plugin
http://buckwilson.me/lightboxme/
This is the simplest plugin available!
In my project I have a webpage which has 2 div areas right and left. The left div takes almost 60% of the whole page width and the right one takes around 36% of the page. I wanted to resize the both div areas in a proper ratio when I shrink the browser from the right side or left side. The UI is getting generated from Javascript. This is the code.
boardHolderPadding = $board.outerHeight() - $board.height();
$board.height(viewportHeight - siblingsHeight - boardHolderPadding);
this.$('#board .droptarget').setWidthAsRatioOfHeight(this.options.ratio);
$('#sidebar').width($(window).width() - $board.find('#board').width() - 50);
I tried with JQuery resize plugin but couldnt get the proper result I'm looking for. Anyone have suggestion?
Thanks
See jsfiddle example but I think you just need to set your widths as percentages rather than trying to calculate them - note display is set to inline-block
<div>
<div class="small-left-column">this is the left column</div>
<div class="large-right-column">this is the right column</div>
</div>
<style>
.small-left-column {
width: 30%;
background-color: #aeaeae;
display: inline-block;
}
.large-right-column {
width: 60%;
background-color: #aeaeae;
display: inline-block;
}
</style>
So I think for your example your would have something like this
$(document).ready(function () {
$('#sidebar').addClass('small-left-column');
$('#board').addClass('large-right-column');
});
Maybe you're looking for the pure-Javascript version of the above:
$(document).ready(function () {
$('#sidebar').css( {
width: '30%'
backgroundColor: '#aeaeae',
display: 'inline-block'
});
$('#board').css({
width: '60%',
backgroundColor: '#aeaeae',
display: 'inline-block'
});
});
I did it in a different way in Javascript and I hope this will help someone to fix if they come across an issue like that
relativeSize : function(width, height){
var boardWidth = this.$("#board").width(),
boardHeight = this.$("#board").height(),
newcard = this.$("#newCard").width(),
space = width - boardWidth - newcard;
ratio = space / width * 3; //used to increment the ratio with 3 as the ratio is very tiny value, this will help to increase minimizing size
bheight = boardHeight - 25; // used to reduce the height by 25px, u can use any amount to match ur ratio
var relHeight = (space < ratio) ? bheight : height;
return relHeight;
}
Thanks