CSS scale triggered by mouseover or onclick? - javascript

I have some CSS that scales images, which works fine.
The problem is it gets applied to every image on the page. What I want is to apply it ONLY to an image if I mouseover or onclick.
Because images are inserted by a CMS used by non-tech writers, they don't have the skills to get into the image tag itself to insert a class. This is why I want the scaling CSS triggered by mouseover or onclick.
I've struggled to get a piece of javascript to do the job and would appreciate some help

You just bind the event to the tag and use this:
var images = document.getElementsByTagName("img");
for (var i=0;i<images.length;i++) {
images[i].onmouseover = imgScale;
images[i].onclick = imgScale;
}
function imgScale(e) {
this.style.width = 500px; //whatever
this.setAttribute("class", "image-scale");
}
If jQuery:
$('img').on('hover click', function() {
$(this).css('width','500px');
$(this).addClass('image-scale');
});
Even better, if you only need on hover you can use just CSS:
img:hover {
width: 500px;
}
You could try using
img:active
To detect a click, but I believe it will only make changes while the mouse is pressed down, as soon as they let up it is no longer :active

You may try using CSS 3 for scaling. Have a look at this fiddle.
HTML:
<img src="http://lorempixel.com/200/200/sports"/>
<img src="http://lorempixel.com/200/200/nature"/>
<img src="http://lorempixel.com/200/200/city"/>
<img src="http://lorempixel.com/200/200/sports"/>
<img src="http://lorempixel.com/200/200/animals"/>
CSS:
img {
-webkit-transition: all 300ms 0ms ease-in-out;
transition: all 300ms 0ms ease-in-out;
width: 50px;
}
img:hover {
-webkit-transform: scale(1.4);
transform: scale(1.4);
}

Related

Fade between multiple images from same URL without refreshing page

By cobbling together bits and pieces of various other answers from SO and elsewhere I have something that almost does what I want, but not quite:
I have to reload the page to get a new image.
Each new image fades in, but the previous image cuts out instantly rather fading across
Clicking on the image skips to the next one the same way.
The url I'm using returns a different image each time the server receives a request. I can change the URL to something else and it will still work. Is there a way to fade smoothly between images served in this way without refreshing the page? The other solutions I've found for this involve specifying a list of images somewhere in the page and rotating through them, which doesn't seem to work when every image has the same url.
I am trying to do this using only html + css + js.
<html>
<head>
<script type = "text/JavaScript">
<!--
function AutoRefresh( t ) {
setTimeout("location.reload(true);", t);
}
//-->
</script>
<style>
* {
margin: 0;
padding: 0;
}
.fade-in{
-webkit-animation: fade-in 2s ease;
-moz-animation: fade-in ease-in-out 2s both;
-ms-animation: fade-in ease-in-out 2s both;
-o-animation: fade-in ease-in-out 2s both;
animation: fade-in 2s ease;
visibility: visible;
-webkit-backface-visibility: hidden;
max-width: 100%;
max-height: 100vh;
margin: auto;
}
.imgbox {
display: grid;
height: 100%;
}
#-webkit-keyframes fade-in{0%{opacity:0;} 100%{opacity:1;}}
#-moz-keyframes fade-in{0%{opacity:0} 100%{opacity:1}}
#-o-keyframes fade-in{0%{opacity:0} 100%{opacity:1}}
#keyframes fade-in{0%{opacity:0} 100%{opacity:1}}
</style>
</head>
<body onload = "JavaScript:AutoRefresh(10000);">
<div class="imgbox">
<a href="javascript:location.reload(true)">
<img class = "fade-in" src="http://192.168.1.151:6600" style="object-fit:contain;display:block;margin-left:auto;margin-right: auto;" />
</a>
</div>
</body>
</html>
It is quite possible to use just JS/CSS/HTML to fade in and out between images without needing to reload the page.
To fade in and out between two images you'll need to have them both loaded. But in this case we cannot have two img elements with the same URL as the browser would assume the images were the same and therefore not ask the server for another one.
We get round this by adding a random query string to the end of the URL each time to persuade the browser to get another img. I'm using picsum and using their way of doing this, the method may differ for your service, though normally adding a random query to a URL doesn't upset the server, and it's only the browser we need to convince to send another request.
We load a new img with opacity: 0 so there isn't a sudden jump, and then we gradually fade it in while fading the other one out using your animation.
I have put the inline img styling into the head to tidy things up as we now have two images. I've removed the system-dependent prefixes just to make things easier to read, but of course put them back if you need them.
UPDATE: there was an additional requirement to not send requests to the image server too often. A pause flag has been added to indicate we cannot respond to the user's click which is unset after 2 seconds.
const imgs = [document.getElementById('img1'),document.getElementById('img2')];
let back=0; //0 or 1 depending on which img is faded out
let pause = false; //a flag to say it's too soon to get another image
let randomiser = 1;//we add this to the end of the img src to persuade the browser it really does need to get another image from the image server
function imgLoaded() {
imgs[back].style.animationDirection = 'normal';// will now fade in
back = (back + 1)%2;//make the other img the back
imgs[back].style.animationDirection = 'reverse'; // will now fade out
imgs[0].style.animationName = 'fade-in';
imgs[1].style.animationName = 'fade-in';
}
function next() {
if (pause) { return; }
imgs[0].style.animationName ='nothing';
imgs[1].style.animationName = 'nothing';
imgs[back].style.opacity = 0;// these should already be there, but just in case animation still on the go
imgs[(back+1)%2].style.opacity = 1;
randomiser++;
imgs[back].src = 'https://picsum.photos/1024/768.jpg?random='+ randomiser;
pause = true;
setTimeout(function () { pause = false; },2000);//dont ask for another image until 2 seconds is up
}
* {
margin: 0;
padding: 0;
}
body {
width:100vw;
height: 100vh;
}
.imgbox {
display: grid;
height: 100%;
}
#keyframes fade-in{0%{opacity:0} 100%{opacity:1}}
#keyframes nothing {}
.imgbox img {
object-fit:contain;
display:block;
animation-fill-mode: forwards;
animation-duration: 2s;
animation-iteration-count: 1;
position: absolute;
opacity:0;
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
<div class="imgbox" onclick="next();">
<img id="img1" onload="imgLoaded();" src="https://picsum.photos/1024/768.jpg?random=0"/>
<img id="img2" onload="imgLoaded();" src="https://picsum.photos/1024/768.jpg?random=0"/>
</div>

How to make my CSS transition smoother/work on different browsers?

I'm trying to make a page that changes background image when you click a button. Code pen: http://codepen.io/meek/pen/EPLZpW
body {
background: url('https://s3.eu-central-1.amazonaws.com/meek-img/1.jpg') no-repeat center center fixed;
background-size: cover;
-webkit-transition: background .5s ease-in-out;
-moz-transition: background .5s ease-in-out;
-o-transition: background .5s ease-in-out;
transition: background .5s ease-in-out;
}
The two big problems with the way I'm doing this currently are:
It flat out doesn't work in Mozilla Firefox.
The animation isn't smooth at all. It switches to a blank background for an instant, then the animation runs. Is there a way to prevent this, or is it unavoidable due to loading times? If so are there other ways to implement this function that would circumvent this? At first, I thought of animating with jQuery, but was told that this wasn't optimal.
Doing a transition on the full property background could possibly create some wonky effects. Especially when images are involved. Directly doing these transitions on background images is very demanding for your browser. And, as mentioned by you, does not behave consistently in different browsers.
A better idea is to do a transition or animation on opacity of an element (like a div) having that background property. This way the browser would not have to worry about transitioning the image, only about transitioning the div, which would result in a much easier task for your browser. If you want to change the background of your page, you would then simply add a div with that background image.
I've included a snippet, base on your code, to demonstrate the general idea. You'll also notice, I only preload the image when the image is requested as background image. This way the user only downloads the images he gets to see. My demo uses jQuery, but it could easily be integrated using vanilla JS.
function preload_img (src, callback) {
var img = new Image();
img.onload = function() {
if( callback && typeof callback === 'function' ) {
callback( img );
}
};
img.src = src;
}
var imgs = [
"https://s3.eu-central-1.amazonaws.com/meek-img/1.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/2.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/3.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/4.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/5.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/6.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/7.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/8.jpg",
"https://s3.eu-central-1.amazonaws.com/meek-img/9.jpg"
];
function change_bg() {
var random_index = Math.floor(Math.random() * imgs.length);
preload_img( imgs[random_index], function( img ) {
$('<div>')
.addClass('bg-image')
.css('background-image', 'url(' + img.src + ')')
.appendTo('body')
;
} );
}
$( 'button' ).click( function() {
change_bg();
} );
change_bg();
#keyframes fadein
{
from { opacity: 0; }
to { opacity: 1; }
}
.bg-image
{
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
animation: fadein 1s;
background-size: cover;
}
.mimi
{
z-index: 1;
bottom: 0;
height: 100px;
left: 0;
margin: auto;
position: absolute;
top: 0;
right: 0;
width: 100px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<body>
<div class="mimi">
<button class="btn btn-default btn-lg">click me</button>
</div>
</body>
I'd consider loading the new image on top of the current image with 0 opacity and then transition the opacity to 1. After that you can remove the image below.
Also make sure that the image is fully loaded before starting the transition.
Adding the new image on change can be done with append() and then when the new image has loaded you can add a class to it with opacity 1.

Fading in page on load

I am trying to use j-query to fade in my pages body upon load, however for some reason the body's background image is not being affected by the j-query. Please see the code I have below:
J-Query Code in head section:
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function(){
$('body').fadeIn(2000);
});
</script>
CSS Code:
body
{
overflow:hidden;
background:url('body.png') no-repeat;
background-size:100%;
display:none;
}
Everything contained within the body (div's / paragraphs / headings etc) fade in on load as per the j-query code, however the body's background image (body.png) loads instantly with the page. Please can anyone suggest what I'm doing wrong with the above code?
body behaves funny. You would need to wrap the contents of the entire page in another div and fade that in.
<body>
<div id="wrapper">
# Page Contents #
</div>
</body>
CSS:
#wrapper{
background-image:url('some-image.jpg');
display:none;
}
jQuery:
$(document).ready(function(){
$('#wrapper').fadeIn();
});
See this JSFiddle.
Like the #ITFarmer wait, you can do it in CSS3, but you could probably also animate the background-image with CSS3 too.
#keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
#keyframes fadeinbg {
from {
background-image: none;
}
to {
background:url('body.png') no-repeat;
}
}
.container {
animation: fadein 2s;
}
.body {
animation: fadeinbg 2s;
I'm not sure if it would also affect the background image, but you could do the fade-in effect also without jQuery. At least in browsers which support CSS3:
#keyframes fadein{
from{opacity:0;}
to{opacity:1;}
}
.someElement{
animation: fadein 2s;
}

How to prevent transition on carousel container when reseting its position?

I have applied CSS transition to translateX on the parent element of my carousel which I animate from 0 to 100% when clicking the next button, what I want to do however is prevent the animation kicking in when I reset the translate position back to 0 inside my setTimeout. Ideally I would like to set transition to none then quickly remove this when my carousel has reset. Can anyone recommend how I would do this?
CSS
.carousel {
height: 100%;
-webkit-transition: -webkit-transform .1s ease-in-out;
-webkit-transform: translate(0, 0);
}
JS
btnNext.on('click', function (e) {
e.preventDefault();
//move carousel to right 100%
carousel.css('transform', 'translateX(-100%)');
$('.slide:first').insertAfter('.slide:last');
setTimeout(function () {
resetSlides();
resetCarousel();
}, 5000);
});
function resetCarousel() {
$('.carousel').css({
'transform': 'translateX(0%)',
'transition': 'none'
});
//now remove inline transition:none style without a transition occurring?
}
JSFiddle: http://jsfiddle.net/GKv4p/22/
You could use a second css class, "animated". In your CSS you could then have:
.carousel {
height: 100%;
}
.carousel.animated {
-webkit-transition: -webkit-transform .1s ease-in-out;
-webkit-transform: translate(0, 0);
}
In your JavaScript you would then add or remove this extra class in order to add or remove the animation.
Ok, so I think I got it working as you want.
The main changes I made were to add the -webkit-transition: all .1s ease-in-out; to the .expose-* classes, and add a delay into $('.carousel').attr('style', '');
Ended up with this Fiddle

Need help to add/modify to my script to include some rotation using jquery and css

Here is the fiddle:
http://jsfiddle.net/7txt3/29/
I want to have the record needle on the record like you see in my image below rotate on to the record when the user clicks the play button(see the fiddle)
The needle placement is not necessarily final and I might want it to be in the top right corner.(I've included the image needed for that and the css at the bottom)
Right now if you click play(see the fiddle, hover over on one of the record covers, click play) the record needle comes in from the left and then if you click stop on the same record it goes back out to the left. If you click play on another record before stopping the playing one it just stays in the same place.
I want it to be like the image below where it is always showing but not on the record unless you click the play button and then it rotates on. Then if you click play on another record while one is currently playing it just shifts/moves like its changing. Then of course if you click stop it goes off the record.
Here is my current script:
$(function(){
var station = $('.player-station'),
record = $('.record2:first'),
playBtns = $('.play'),
info = $('.nprecinfo');
var isPlaying = false;
playBtns.click(function()
{
var btn = $(this);
if(btn.text() == 'STOP')
{
btn.text('PLAY');
record.css({'-webkit-animation-play-state': 'paused',
'-moz-animation-play-state': 'paused'});
$('#needle').show().animate({"left": "-=120px"}, "slow");
isPlaying = false;
return;
};
playBtns.text('PLAY');
var album = btn.closest('.album');
station.text(album.find('h3').text());
info.text(album.find('.recordinfo').text());
record.css({'-webkit-animation-play-state': 'running',
'-moz-animation-play-state': 'running'});
if (isPlaying == false)
{
$('#needle').show().animate({"left": "+=120px"}, "slow");
isPlaying = true;
}
$('#lrvinyl').css("background-image","url("+btn.attr('rel')+")");
$('#lrvinyl').hide().fadeIn();
btn.text('STOP');
});
});
and here is the current css for the record needle:
#needle {
background-image:url(http://benlevywebdesign.com/somafm/images/recordneedle2.png);
background-repeat: no-repeat;
width:220px;
height:220px;
position:absolute;
left:-115px;
top:185px;
z-index:10;
overflow:hidden;
}
if you want to put the needle in the top right corner here is the image and css to use in the fiddle for that. You might have to move the record (.record2) a bit so just change the css to left:-4px;
#needle {
background-image:url(http://benlevywebdesign.com/somafm/images/recordneedle4.png);
background-repeat: no-repeat;
width:220px;
height:220px;
position:absolute;
left:205px;
top:10px;
z-index:10;
overflow:hidden;
}
+1 for detailed question! :)
You're already relying on css3 for the rotating disc, and since this is quite doable with css transitions, all you need to do with the javascript is to add/remove a class.
Demo: http://jsfiddle.net/7txt3/31/
This is essentially what I added (plus some vendor prefixes)
css
#needle
transition: all .2s ease;
}
#needle.playing {
transform: rotate(-10deg);
}
jquery
changed from .animate(...) to .removeClass() and .addClass() calls.
I also changed the #needle css a bit in order to rotate from the left of the needle hand, but you could look at https://developer.mozilla.org/en-US/docs/CSS/transform-origin instead.
edit
Sorry, I missed the part about animating between record changes. One thing you can do is to remove the class and then add it back after a delay, something like this:
http://jsfiddle.net/7txt3/53/
I think this should give the desired effect.
To have the needle rotate correctly you need to set the transform origin.
http://jsfiddle.net/7txt3/35/
You of course will want to modify the speeds/percentages.
#needle {
background-image:url(http://benlevywebdesign.com/somafm/images/recordneedle2.png);
background-repeat: no-repeat;
width:220px;
height:220px;
position:absolute;
top:185px;
z-index:10;
overflow:hidden;
}
#needle.playing {
-webkit-animation-name: needle_move;
-webkit-animation-duration:8s;
-webkit-animation-timing-function:linear;
-webkit-animation-iteration-count:infinite;
-webkit-animation-direction:normal;
-webkit-transform-origin: 0px 10px;
-webkit-transform: rotate(0deg);
-webkit-transition: all .2s;
-moz-transition: all .2s;
transition: all .2s;
}
#-webkit-keyframes needle_move {
0% {
-webkit-transform: rotate(0deg);
}
50% {
-webkit-transform: rotate(-15deg);
}
70% {
-webkit-transform: rotate(-15deg);
}
0% {
-webkit-transform: rotate(0deg);
}
}
Here's a demo using CANVAS to get the needle animation you wanted in your question.
http://jsfiddle.net/7txt3/46/
Because of the vender prefix spammed CSS3 and the lack of browser support for rotation-point. I think going CANVAS is a little cleaner.

Categories

Resources