Fade an Image Using JavaScript (NOT JQuery!) - javascript

Hey everyone I have a homework question,
I need to fade in and out an image "gallery-style" using JavaScript. Note: NOT JQuery. I cannot use JQuery, per the assignment outline.
So there's a grid of images (32 of em if you care) they're all 100x100px thumbnails. Each one is in its own div, and the whole thing is nested inside another div, like so:
gallery.html
<div id="imageContent">
<div id="img" class="imageWhite"
onclick="fade(1984)"
onmouseover="highlightWhiteFunction(this)"
onmouseout="unHighlightFunction(this)">
<img src="../Media/Thumbs/1984.jpg"/>
</div>
...31 others just like that
</div> //End of the whole container
So when you click on one of these images, it should fade that image in over the top of everything else. The width of this picture should be 500px, but the height can vary so distortion doesn't occur. Again, I CANNOT use JQuery for this...and yes, I know that'd make life a lot easier.
So far I only have a debug thing to detect that I can at least find which one is clicked on:
gallery.js
function fade(name) {
var theName = name;
console.debug("Clicked " + theName);
}
If the user clicks anywhere on this image, it needs to fade out. If the user clicks another thumbnail, it doesn't need to fade out, it can just disappear, but the other one needs to start fading in.
My thoughts:
Obviously I need a hidden div with width 500, and when these actions occur, I hide/unhide the div as necessary. The gist I've gotten from the professor is that to use JavaScript, you change the opacity in relation to a passage of time that you get from the system.
What I'm looking for in an answer here is maybe some clearer (more detailed) hints on how to go about this. I know how it needs to look, and I'm pretty sure I know the high-level of how to do it, I just don't know how to start doing it with code.
Any help would be appreciated, and I'll be around to answer any follow-up questions.
Again: NO JQuery! :)

Something like this should work
function fadeIn(el, time) {
el.style.opacity = 0;
el.style.display = "block";
var last = +new Date();
var tick = function() {
el.style.opacity = +el.style.opacity + (new Date() - last) / time;
last = +new Date();
if (+el.style.opacity < 1) {
(window.requestAnimationFrame && requestAnimationFrame(tick)) || setTimeout(tick, 16)
}
};
tick();
}
Here is an example:
http://jsfiddle.net/cEDbs/
Just bind the image onclick to call that method with the element.

Here is a CSS based solution. The fade may not be exactly like you want, but can easily be adjusted. Try out the JSFiddle and click an image to see a css transition-- clicking an image fades it larger. Click again fades it back.
http://jsfiddle.net/Rh976/
<img src="http://tippvet.com/wp-content/uploads/2013/05/cat-vet.jpg" class="img img1"/>
<img src="http://tippvet.com/wp-content/uploads/2013/05/cat-vet.jpg" class="img img2"/>
<img src="http://tippvet.com/wp-content/uploads/2013/05/cat-vet.jpg" class="img img3"/>
<img src="http://tippvet.com/wp-content/uploads/2013/05/cat-vet.jpg" class="img img4"/>
JS
var imgs = document.getElementsByTagName('img');
for(var i = 0; i < imgs.length; i++){
var img = imgs[i];
img.addEventListener('click',function(e){
if(!this.className.match(/big/)){
this.className += ' big';
} else {
this.className = this.className.replace(/big/,'');
}
});
}
CSS
.img {
-webkit-transition: all 1.0s ease-out;
-moz-transition: all 1.0s ease-out;
-o-transition: all 1.0s ease-out;
position:absolute;
width:150px;
height:100px;
z-index:1;
}
.img.img1 { top: 10px; left: 10px; }
.img.img2 { top: 10px; left:170px; }
.img.img3 { top:120px; left: 10px; }
.img.img4 { top:120px; left:170px; }
.img.big {
position:absolute;
width:450px;
height:300px;
top:10px;
left:10px;
z-index:20;
}

Related

How to fade out text using JavaScript or jQuery and then bring it back

I am new to JavaScript/jQuery and what I want to do is to fade out text and when the opacity is zero, I want to bring back the text with the same effect. I am leaning towards some kind of if statement and the fade in effect, but don't manage to understand how to put it all together. Any tips for how this could be done using jQuery would be appreciated.
function hideText() {
var fadeText = document.getElementById("fadeTextp");
fadeText.style.opacity = 0;
fadeText.addEventListener("transitionend", function(e) {
alert("The text is hidden, but how can I now get it back with same effect?")
}, false);
}
.fade {
opacity: 1;
transition: opacity 2.25s ease-in-out;
-moz-transition: opacity 2.25s ease-in-out;
-webkit-transition: opacity 2.25s ease-in-out;
}
<p id="fadeTextp" class="fade" onclick="hideText();">
Fade out this text and then bring it back when clicked again.
</p>
I'm not sure what your overall goal is, but there are lots of ways to do this kind of thing. Some could use only CSS, some could use JavaScript, some could use both. I'll do a "both" example.
Note: It would probably be better to use one or the other - so you don't define the transition time in both places.
Note: jQuery has animation support built in. See the answer from #Twisty for a jQuery example and links to their docs.
var transitionTime = 2250;
var faderTimeout = null; // keep track of this to cancel it if multiple events happen
var fadeText = document.getElementById("fadeTextp");
function hideText() {
fadeText.classList.remove('out');
fadeText.classList.add('out');
window.clearTimeout(faderTimeout);
faderTimeout = window.setTimeout(() => {
fadeText.classList.remove('out');
}, transitionTime);
}
.fade {
opacity: 1;
transition: opacity 2.25s ease-in-out;
-moz-transition: opacity 2.25s ease-in-out;
-webkit-transition: opacity 2.25s ease-in-out;
}
.fade.out {
opacity: 0;
}
<p id="fadeTextp" class="fade" onclick="hideText();">
Fade out this text and then bring it back when clicked again.
</p>
Here's a jQuery example since you asked for jQuery. You need a container with some height to be able to click again for the text to come back. If you don't have this container then the thing you add a "click" event listener to is not available to click anymore.
I use the :visible selector to see if the text is visible and if so fadeOut and if it's not visible then fadeIn.
let fadeTextp = $("#fadeTextp");
$("#fadeTextContainer").on("click", () => {
if (fadeTextp.is(":visible")) {
fadeTextp.fadeOut()
} else {
fadeTextp.fadeIn()
}
});
#fadeTextContainer {
height: 50px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="fadeTextContainer">
<p id="fadeTextp">
Fade out this text and then bring it back when clicked again.
</p>
</div>
Here is a quick jQuery Example.
$(function() {
$(".fade").click(function() {
var $this = $(this);
$this.fadeOut(600, function() {
$this.fadeIn(600);
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id="fadeTextp" class="fade">
Fade out this text and then bring it back when clicked again.
</p>
This uses .fadeOut() and cascades a callback to .fadeIn().
See more:
https://api.jquery.com/fadeout/
https://api.jquery.com/fadein/
You can also animate the visibility.
$(function() {
$(".fade").click(function(e) {
var t = $(this);
if (t.hasClass("out")) {
t.animate({
opacity: 1
}, 600);
t.removeClass("out");
} else {
t.animate({
opacity: 0
}, 600);
t.addClass("out");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p id="fadeTextp" class="fade">Fade out this text and then bring it back when clicked again.</p>

How can I figure out what size an HTML Element will be? (tween size as element added)

I'm pretty sure this is currently infeasable.
I have an animation that involves an element moving from an absolute position to an inline one. For reasons, I can not know how the container is sized, nor how the element I'm animating is sized.
What I need to know is what the size of the HTML Element will be after the transformation, without any jittery drawing.
This makes the problem very difficult (likely undoable) because I have no way to know if adding the element will resize the parent, or resize the element itself.
What I need is a means of looking into the future.
const byId = (id) => document.getElementById(id);
#container {
height: 3em;
min-width: 50%;
background: teal;
}
#mystery {
background: purple;
}
<div id="container">
<div id="mystery">Some Text</div>
</div>
<button onClick='byId("mystery").style.position = "relative"'>Position Relative</button>
<button onClick='byId("mystery").style.position = "absolute"'>Position Absolute</button>
Currently, these are the only solutions I can imagine (they're all absurd):
Clone the entire webpage HTML, make the clone have opacity: 0; pointer-events: none and render what the future will be secretly.
Capture the paint data of the current page (basically screenshot), overlay that while secretly modifying the page, get my future, revert, and remove the screenshot overlay.
Similar to number 2, is there a way to ❄️freeze❄️ rendering of a page for 3-4 frames?
I remember seeing a "sizing worker" something-or-rather a long time ago. Couldn't find any information on it now, but it seems like it might be useful?
You can simply change the property, measure the sizes you want and then change the property back. JS is fast enough to do it all between renderings, as long as you keep it all in the same thread. Have you tried that at all?
Asker Edit:
Here's the code to prove it works.
function byId(id){ return document.getElementById(id); }
const tweenyEl = byId("tweeny");
function appendTweeny() {
tweenyEl.style.opacity = "1";
const startingWidth = tweenyEl.clientWidth + "px"
tweenyEl.style.position = "relative";
const targetWidth = tweenyEl.clientWidth + "px";
console.log(startingWidth, targetWidth);
tweenyEl.style.width = startingWidth;
requestAnimationFrame(() =>
requestAnimationFrame(() =>
tweenyEl.style.width = targetWidth
)
);
}
function resetTweeny() {
tweenyEl.style.position = "";
tweenyEl.style.width = "";
tweenyEl.style.opacity = "0.1";
}
#container {
display: inline-block;
height: 3em;
min-width: 150px;
background: teal;
}
#tweeny {
font-family: arial;
color: white;
position: absolute;
background: purple;
transition: all 0.5s ease;
opacity: 0.1;
}
<div id="container">
<div id="tweeny">I'm Tweeny</div>
</div>
<br>
<button onClick='appendTweeny()'>Append Tweeny</button>
<button onClick='resetTweeny()'>Reset Tweeny</button>
I would suggest cloning the page into an iframe and then positioning the iframe off the screen.
<iframe style="width:100vw;height:100vh;left:-101vw;positionabsolute"><iframe>
Also bear in mind that the user can zoom in-and-out at will! Different browsers might render the same thing in different ways. You really don't know how big an element will be until it does so.
I don't know if you can get anywhere by specifying display: none; ... whether or not the browser would bother to make these calculations for an object that isn't visible.
You can clone on the fly an element with same transformation with delay 0 and then calculate it's width and height, then do what you want with your actual element it's still animating

Hover(), mouseenter(), mouseover(), etc jumping back and forth

I am trying to make a situation when you hover over an image then it will hide an image and show another. and the other way around when you hover out.
I have tried using all the various hover effects that comes to mind like mouseenter, mouseover, hover, etc.
They all cause the same problem. If i very firmly and quickly drag my cursor into the field of action then it will give me the desired effect. however if i slowly drag my cursor into the field of action then it will jump between the images a couple of times before finally stopping at the correct image.
this looks very unprofessional and i want it to be much more consequent doing this action so that no matter if i do it slow or fast then it will only jump once.
this is my script:
$("#DenmarkMap").hide();
$("#InfoBadge1").hover(function(){
$("#InfoLogo").hide("puff");
$("#DenmarkMap").show("puff");
}, function(){
$("#DenmarkMap").hide("puff");
$("#InfoLogo").show("puff");
});
this is a non working fiddle
https://jsfiddle.net/ydeLvxx2/
hope you guys can help me figure this out.
Here is a pure Javascript solution (no jQuery needed)
https://jsfiddle.net/uL0hpxbu/
Update: version with CSS3 "puff" effect: https://jsfiddle.net/230ta4tk/2/
Here is how the main script looks like:
var InfoBadge1 = document.getElementById("InfoBadge1");
var InfoLogo = document.getElementById("InfoLogo");
var DenmarkMap = document.getElementById("DenmarkMap");
InfoBadge1.addEventListener("mouseover", function() {
InfoLogo.classList.toggle("puff");
DenmarkMap.classList.toggle("puff");
});
InfoBadge1.addEventListener("mouseout", function() {
InfoLogo.classList.toggle("puff");
DenmarkMap.classList.toggle("puff");
});
and CSS part (just an example, change it as you want)
#DenmarkMap {
position: absolute;
left: 0;
top: 0;
transition: .5s all;
}
#InfoLogo {
position: absolute;
left: 250px;
top: 120px;
transition: .5s all;
}
#InfoBadge1 {
position: absolute;
left: 0px;
top: 120px;
}
.puff {
transform: scale(1.2);
opacity: 0;
}
and HTML:
<img id="InfoBadge1" src="http://dummyimage.com/200x100/803580/ffffff&text=InfoBadge1" alt="" />
<img id="InfoLogo" src="http://dummyimage.com/200x100/803580/ffffff&text=InfoLogo" alt="" />
<img id="DenmarkMap" class="puff" src="http://dummyimage.com/200x100/3c8036/ffffff&text=DenmarkMap" alt="" />
You should not bind your hover's mouseleave/mouseout event to the same image, because you've just hidden it.
Instead, consider binding the hover functions to the parent DOM node (a DIV for example):
<div id="images">
<img id="InfoBadge1" src="./Photos/DenmarkInfoBadge.png">
<img id="InfoLogo" src="./Photos/InfoLogo.png">
<img id="DenmarkMap" src="./Photos/DenmarkMap.png">
</div>
Your javascript can then become:
$("#DenmarkMap").hide();
$("#images").hover(function(){
$("#InfoLogo").hide("puff");
$("#DenmarkMap").show("puff");
}, function(){
$("#DenmarkMap").hide("puff");
$("#InfoLogo").show("puff");
});

How to initialize an Angularjs css3 animation using Javascript

I am currently trying to do a CSS3 animation in Angular.js.
Before animating I try to set the initial css properties using Javascript.
So, is there a way to initialize an animation using Javascript and then continue the animation using CSS3?
My situation:
When the user clicks on a div, a dialog should appear.
The dialog should start out exactly over the original div (same size, same position), and then grow to a larger size.
I am able to animate the dialog from a predefined position and size:
CSS:
.dialog {
position: absolute;
z-index: 10;
width:600px;
height:400px;
margin-left: -300px;
left:50%;
margin-top: 50px;
}
.dialogHolder.ng-enter .dialog {
transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1s;
width:0;
height:0;
margin-left: 0px;
}
.dialogHolder.ng-enter-active .dialog {
width:600px;
height:400px;
margin-left: -300px;
}
I would like to animate the dialog starting at the size of the clicked div.
So far my code (not working yet) looks like this:
HTML:
<div ng-repeat="course in data.courses" ng-click="showDialog($event)">
{{ course.cursus }}
</div>
<!-- Placeholder for blokDialogs -->
<div class="dialogHolder" ng-include="dialogTemplate.url">
DIALOG WILL BE LOADED HERE
</div>
Javascript:
app.controller('blockController', function($scope) {
$scope.showDialog = function(evt) {
// get position and size of the course block
$scope.dialogTemplate.clientRect = evt.target.getBoundingClientRect();
// load the html to show the dialog
$scope.dialogTemplate.url = 'partials/blokDialog.html';
// SHOULD I DO SOMETHING HERE?
};
});
// OR SHOULD I DO SOMETHING LIKE THIS?
app.animation('.dialogHolder', function(){
return {
// SOMEHOW SET THE WIDTH, HEIGHT, TOP, LEFT OF .dialog
};
});
I'd prefer to do this without jQuery to keep the page weight low.
Regards,
Hendrik Jan
You want to use ng-animate http://docs.angularjs.org/api/ngAnimate
If you are using ng-repeat, you can animate when elements enter, leave and move around your repeater. The magic is that you don't even have to put an extra directive in your html, just define your CSS animations accordingly.
So in your case something like this
.repeater.ng-enter, .repeater.ng-leave, .repeater.ng-move {
-webkit-transition:0.5s linear all;
transition:0.5s linear all;
}
.repeater.ng-enter { }
.repeater.ng-enter-active { }
.repeater.ng-leave { }
.repeater.ng-leave-active { }
.repeater.ng-move { }
.repeater.ng-move-active { }
and your HTML
<div ng-repeat="..." class="repeater"/>
In the end, I found the following solution:
HTML:
Create an onClick handler and a placeholder where the dialog is loaded.
<!-- Element on which the user clicks to initialize the dialog -->
<div ng-repeat="course in data.courses"
ng-click="showDialog($event, course)">
{{ course.name }}
</div>
<!-- Placeholder for blokDialogs -->
<div class="dialogHolder"
ng-include="dialogTemplate.url"
onload="showDialogLoaded()">
</div>
HTML Template:
partials/blokDialog.html sets it's style using ng-style.
<div ng-style="dialogTemplate.initialStyle">
...
</div>
Javascript:
The onClick handler sets the initial CSS before the animation starts.
$scope.showDialog = function(evt, course) {
// Load the dialog template
$scope.dialogTemplate.url = 'partials/blokDialog.html';
// set the css before the animation starts
// get position and size of the course block
var clientRect = evt.target.getBoundingClientRect();
$scope.dialogTemplate.initialStyle = {
left: clientRect.left + 'px',
top: clientRect.top + 'px',
width: clientRect.width + 'px',
height: clientRect.height + 'px',
backgroundColor: getComputedStyle(evt.target).backgroundColor
};
};
The style needs to be removed before the animation ends but after the animation started.
The animation starts at the end of the onLoad handler. If we remove the style in the onLoad handler (i.e. in showDialogLoaded), then we are to early.
We use setTimeout to make sure that the removal of the style is done after the animation was started.
$scope.showDialogLoaded = function() {
// remove the style that we set in showDialog
setTimeout(function(){
$scope.dialogTemplate.initialStyle = {};
// we need to $apply because this function is executed
// outside normal Angular handling, so Angular does not know
// that it needs to do a dirty check
$scope.$apply();
}, 0);
};
I hope this can be helpful for others.
Regards,
HJ

CSS transform: rotate only works on image

I have this code:
<html>
<head>
<script type = "text/javascript" src = "jquery-1.7.1.js"></script>
<script type = "text/javascript" src = "jquery-ui-1.8.18.custom.min.js"></script>
</head>
<body>
<div id = "div" onclick = "Rotate()">
<img src="image.png" height="40" width="160">
</div>
<script type="text/javascript">
var x = 1;
function Rotate() {
var angle = (90 * x);
$("div").css("-moz-transform",
"rotate(" + angle + "deg)");
x++;
}</scipt></body></html>
when using Rotate() script, the div seems like been rotated, but when viewd with Firebug, I can see that div is still in the same position. Am I doing something wrong or I am using wrong thing for the task I'm trying to accomplish?
Edit:
Thanks for the responses! I set the background to yellow and it turned the yellow box but when clicking on the div name in Firebug it shows that the div is still in its original position.
It's definitely being applied to the <div>. Just add a width and a background color to the div to see that it's working correctly.
Here's an example I threw together that rotates on hover:
HTML:
<div id="awesome">
<img src="/img/logo.png">
</div>
CSS:
body {
margin: 100px;
}
div {
background: blue;
width: 200px;
-webkit-transition: all ease-in 1s;
-moz-transition: all ease-in 1s;
transition: all ease-in 1s;
}
div:hover {
background: yellow;
-moz-transform: rotate(30deg);
-webkit-transform: rotate(30deg);
transform: rotate(30deg);
}
Here's some more info how to use the css3 transform property
There is a jQuery plugin I found that has an example of doing exactly what you're doing, but in a cross-browswer way. Check out:
https://github.com/heygrady/transform
This plugin let's you do things like this:
$('div').click(function() {
$(this).animate({rotate: '+=45deg'});
});
Edit:
Hey, here's a slightly cleaned up version of your original that works fine:
var x = 1;
$("#box").click(rotate);
function rotate() {
var angle = (90 * x);
$(this).css("-moz-transform", "rotate(" + angle + "deg)");
x++;
if (x > 4) x = 0;
}
http://jsfiddle.net/UdYKb/1/
The reason firebug doesn't show the change is because of the spec, which says: "the transform property does not affect the flow of the content surrounding the transformed element." http://dev.w3.org/csswg/css3-transforms/
Look at this example with 3 rotating pics
HTML:
<div id = "div">
<img src="http://dummyimage.com/100" class="rp" data-rotate="0">
<img src="http://dummyimage.com/100" class="rp" data-rotate="0">
<img src="http://dummyimage.com/100" class="rp" data-rotate="0">
</div>
JAVASCRIPT:
$().ready(function() {
$(".rp").click(function() {
var rot = (parseInt($(this).attr("data-rotate"))+90)%360;
$(this).attr("data-rotate",rot);
$(this).css("-webkit-transform", "rotate("+rot+"deg)");
$(this).css("-moz-transform", "rotate("+rot+"deg)");
});
});​
I Save the last rotation in the attribute data-rotate. Please read about CSS Selectors if you do not understand why using .rp :) Hope it helps.
PS: I used the Google Chrome css attribute -webkit-transform too :)

Categories