jQuery animate background image on timeout up-down float effect - javascript

I have this element with background images:
background-image: url(../img/Icons/about-stars-bg2.svg),
url(../img/about-planet-1.svg),
url(../img/about-planet-2.svg),
url(../img/about-planet-3.svg);
background-position: top 5px center, -115px 200px, left 1055px top 450px,
right -45px top 350px;
background-repeat: no-repeat;
background-size: auto, auto, auto, 100px;
Now I want the planets (every picture except the first one) to move a little bit up, then down. (Float effect).
In jQuery I created a setInterval so I have a loop every 2s. Inside I tried to change the background position. It works if I put
.css('background-position','top 5px center, -155px 200px, left 1255px top 250px, right -15px top 350px');
But this just blinks the planets in 2 sec.
Then I tried:
$('.header').animate({backgroundPosition: '(0px -400px)'}, 1000 );// space here
But nothing happened.
How can I achieve the hover effect up/down ?
Here is the jQuery:
// Move planets up down
$(document).ready(function(){
var i = 0;
setInterval(function(){
//JUST BLINKS, CHANGES LOCATION
//$('.header').css('background-position','top 5px center, -155px 200px, left 1255px top 250px, right -15px top 350px');
//DOESN'T WORK
$('.header').animate({backgroundPosition: '(0px -400px)'}, 1000 );
i++;
},2000);
});

#planets {
height: 90vh;
background-image:
url(//placehold.it/40x40/f0b),
url(//placehold.it/40x40/0bf),
url(//placehold.it/40x40/bf0),
url(//placehold.it/40x40/0fb);
background-position:
50% 15%,
25% 35%,
10% 19%,
80% 60%;
background-repeat: no-repeat;
background-size:
3%,
4%,
5%,
6%;
animation: planets 1s 0.5s ease-in-out alternate infinite;
}
#keyframes planets {
to {
background-position:
50% 45%,
25% 65%,
10% 69%,
80% 20%;
}
}
<div id="planets">
</div>

Related

How to make image opacity respond to cursor position

I have a cartoon of an antique "detour" sign that has cataphote reflectors embedded in the letters. I want the reflectors to brighten as the image is hovered. That's easily done, I know, simply by swapping out a version of the image with the reflectors darkened with an image of them brightened on hover (per the markup below). However, doing it this way makes the reflectors appear to blink on or off. I want them to get increasingly bright as the cursor nears the center of the image and, of course, dim as the cursor moves away from it, as would occur in real life. (If your headlights beamed at the reflectors at an oblique angle, the light they reflect back would be dimmer than if your headlights hit them straight on.)
My thought is just to increase the opacity of the brightened version of the image in response to the position of the hovering cursor. So, what I need (I think) is a script that detects the cursor position and increases or decreases the opacity accordingly: opacity: 0; at the edge and opacity: 1; at the center. Probably not too challenging for someone adept in javascript/jquery. I've hunted around for a script that does that or something very close to it but haven't been able to locate one that is close enough for me to modify.
I have an additional issue in that in Firefox, at least, the hover image "flicks" the first time it is invoked. I've tried all of the preloading suggestions I could find here on stackoerflow but none of them work. I found that a sprite solved the flicking problem, but wasn't sure how that would work with the way I want the image to animate. Presuming non-sprite images are the way to go maybe if the script invokes the "bright" version of the image at an initial opacity of 0 as the cursor crosses the threshhold, it will also hide the loading "flick...?" Just a guess. Alternatively, I could redesign the hovered version so that it is just the reflectors if that would solve everything else.
Finally, as you can see, the sign is a button that returns a random page. Assuming what I need to solve this problem is a script, can I run both scripts off of the same id (#detour) or should this script use a class name instead? (I am clearly an example of a little knowledge being a dangerous thing.)
Anyway, here's what I've got.
.detour-box {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#detour {
position: absolute;
background: transparent url(https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3.png) no-repeat center center;
background-size: 100%;
clip-path: polygon(48% 0%, 49% 1%, 50% 0%, 69% 19%, 81% 31%, 94% 42%, 100% 48%, 100% 49%, 85% 65%, 76% 75%, 63% 88%, 53% 99%, 52% 100%, 48% 97%, 37% 87%, 28% 79%, 16% 67%, 8% 59%, 0 49%, 3% 45%, 14% 35%, 28% 20%);
width: 300px;
height: 295px;
}
#detour:hover {
background: transparent url(https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3on.png) no-repeat center center;
background-size: 100%;
cursor: pointer;
}
<div class="detour-box">
<button id="detour" class="detour" onclick="randomlink()"></button>
</div>
It's not possible to transition from one image to another on the same element by changing the src or background-image value. But you can do it by having both images, and hiding one by default.
Having one image hidden opens the possibility to fade or crossfade between the images. Lay them on top of each other, with the hidden image on top, and show the hidden image on hover.
The image on top can now fade-in by changing the opacity value. With the transition property you can control the transition.
.detour-box {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
#detour {
position: absolute;
display: grid;
grid-template: 1fr / 1fr;
clip-path: polygon(48% 0%, 49% 1%, 50% 0%, 69% 19%, 81% 31%, 94% 42%, 100% 48%, 100% 49%, 85% 65%, 76% 75%, 63% 88%, 53% 99%, 52% 100%, 48% 97%, 37% 87%, 28% 79%, 16% 67%, 8% 59%, 0 49%, 3% 45%, 14% 35%, 28% 20%);
width: 300px;
height: 295px;
cursor: pointer;
}
#detour img {
grid-area: 1 / 1 / 2 / 2;
width: 100%;
height: 100%;
}
#detour img:last-child {
opacity: 0;
transition: opacity 250ms ease-in-out;
z-index: 1;
}
#detour:hover img:last-child {
opacity: 1;
}
<div class="detour-box">
<button id="detour" class="detour" onclick="randomlink()">
<img src="https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3.png" alt="Detour sign off"/>
<img src="https://sodyot.com/wp-content/uploads/2021/03/detour-sign_3on.png" alt="Detour sign on"/>
</button>
</div>
If we punch holes in the detour sign we only need one image.
The background image can have a linear gradient put behind it, the color(s) of which are changed as the mouse moves. In this snippet the color is always some gray, going up to white, and is changed depending on the y movement of the mouse. It would be easy to change it to take x into account as well. And there could be a real gradient to the background to give different effects - depends just what effect is wanted.
The JS alters a CSS variable, --col, depending on the distance from the center.
function makeColor(d) {
d = Math.floor(d);
return 'rgb(' + d + ',' + d + ',' + d + ')';//could use rgba to get opacity also
}
const detour = document.getElementById("detour");
const dimCol = 128;//set this to the initial (switched off) r, g and b gray
detour.style.setProperty('--col', makeColor(dimCol));
detour.addEventListener('mouseout', function () {
detour.style.setProperty('--col', makeColor(dimCol));
});
detour.addEventListener('mousemove', function () {
const rect = detour.getBoundingClientRect();// this should be in a window resize function if you have one
const h = rect.height;// ditto
const y = event.clientY - rect.top; //ditto
const distanceY = Math.abs(y - h/2)/h;
const d = 255 * (1 - 2 * distanceY);
detour.style.setProperty('--col', makeColor(dimCol + (d * (255 - dimCol) / 255)));
});
.detour-box {
position: relative;
width: 100%;
height: 100vh;
display: flex;
justify-content: center;
align-items: center;
}
div#detour {
position: absolute;
background-color: transparent;
background-image: url(https://ahweb.org.uk/detour-with-holes.png), linear-gradient(to bottom, transparent 0%, transparent 40%, var(--col) 40%, var(--col) 60%, transparent 60%, transparent 100%);
background-repeat: no-repeat;
background-position: center center;
background-size: 100%, 70%;
clip-path: polygon(48% 0%, 49% 1%, 50% 0%, 69% 19%, 81% 31%, 94% 42%, 100% 48%, 100% 49%, 85% 65%, 76% 75%, 63% 88%, 53% 99%, 52% 100%, 48% 97%, 37% 87%, 28% 79%, 16% 67%, 8% 59%, 0 49%, 3% 45%, 14% 35%, 28% 20%);
width: 300px;
height: 295px;
margin: 0;
padding: 0;
}
<div class="detour-box">
<div id="detour" class="detour" onclick="randomlink()"></div>
</div>
It is fine to have more than one event listener on an element, so the existing onclick remains.

How can i make a gradient background without changing background size? [duplicate]

I am creating an interactive touchscreen display using a program called Intuiface and have created some background tiles/squares that I want to make look 'alive' by transitioning slowly between colours.
I have used a linear-gradient transition in CSS to do it but the problem is that the transition looks choppy. The program is running 12 visible tiles (it is a very large touchscreen).
I have tried using fewer colours and running on more powerful GPUs (I think it is CPU run anyway) but this hasn't helped.
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s ease infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
At the moment the animations are noticeably choppy. I would like the transition to be much smoother. Does anyone know how I can achieve this?
Here is the code snippet.
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s ease infinite;
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body>
</body>
</html>
Animating background-* properties can be resource intensive - you can try animating transform for relatively better performance - see demo below using traslate for the animation:
body {
margin: 0;
}
div {
height: 100vh;
overflow: hidden;
}
div:after {
content: '';
display: block;
width: 400vw;
height: 400vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
animation: gradient 15s ease infinite;
}
#keyframes gradient {
50% {
transform: translate(-300vw, -300vh);
}
}
<div></div>
Since your animation lasts 15 seconds, trying to run it at full 60fps would mean calculating 15*60 = 900 frames.
Since the difference between a frame and the next is quite small, you can make the CPU work quite less asking for a stepped animation, for instance with steps(75)
It could be also good to set slight delays between animations, so that they don't execute at the same time
body {
width: 100wh;
height: 90vh;
background: linear-gradient(-45deg, #EE7752, #E73C7E, #23A6D5, #23D5AB);
background-size: 400% 400%;
animation: Gradient 15s infinite steps(75);
}
#keyframes Gradient {
0% {
background-position: 0% 50%
}
50% {
background-position: 100% 50%
}
100% {
background-position: 0% 50%
}
}
<html>
<body>
</body>
</html>

Opposite side border radius

I don't know if this exists but I am making for myself a little web builder where I add new HTML element give it attributes I want and their values.
After than I made some CSS changes via Javascript and for border-radius I use this:
function borderRadius(){
var dr = document.getElementById("displayColor");
var rv = document.getElementById("radiusValue");
var tl = document.getElementById("tl").value;
var tr = document.getElementById("tr").value;
var bl = document.getElementById("bl").value;
var br = document.getElementById("br").value;
rv.innerHTML = 'Top-Left: '+tl+'%; Top-Right: '+tr+'%; Bottom-Left: '+bl+'%; Bottom-Right: '+br+'%;';
dr.style.borderTopLeftRadius = tl+'%';
dr.style.borderTopRightRadius = tr+'%';
dr.style.borderBottomLeftRadius = bl+'%';
dr.style.borderBottomRightRadius = br+'%';
}
This code isn't important and it looks like ..
Now my question is can I make trough CSS something like
without make additional elements around?
UPDATE:
As GabyakaG.Petrioli commented, this maybe a solution and with it I am half way there:
.round {
background:
radial-gradient(circle at 0 50%, rgba(204,0,0,0) 40%, #c00 10%),
radial-gradient(circle at 100% 50%, rgba(204,0,0,0) 40%, #c00 10%),
radial-gradient(circle at 100%, rgba(204,0,0,0) 40%, #c00 10%),
radial-gradient(circle at 0, rgba(204,0,0,0) 40%, #c00 10%);
background-position: bottom left, bottom right, top right, top left;
background-size: 50% 100%;
background-repeat: no-repeat;
padding: 10%;
padding-left: 22%;
padding-right: 22%;
}
<div class="round">By using radial gradients, you can simulate rounded corners with a negative radius. Just in this case, don't put the color stops at the exact same position, since the result will be too aliased in most browsers (and kinda still is in Webkit).</div>
Also here I found the answer and solution but still I have some margins or something:
*{margin: 0; outline:0; border: 0;}
.round {
background:
radial-gradient(circle at 0 100%, rgba(204,0,0,0) 70%, #c00 71%),
radial-gradient(circle at 100% 100%, rgba(204,0,0,0) 70%, #c00 71%),
radial-gradient(circle at 100% 0, rgba(204,0,0,0) 70%, #c00 71%),
radial-gradient(circle at 0 0, rgba(204,0,0,0) 70%, #c00 71%);
background-position: bottom left, bottom right, top right, top left;
background-size: 50% 50%;
background-repeat: no-repeat;
width: 300px;
height: 300px;
padding: 10%;
transform: rotate(45deg);
}
p{
transform: rotate(-45deg);
width: 100px;
margin: 100px;
}
<div class="round"><p>
By using radial gradients, you can simulate rounded corners with a negative radius. Just in this case,</p></div>
No, there are no inset or inverse border-radius in CSS as of now. But there are very many ways to create this shape. I've answered your radial-gradient question in the other thread but think this is a good enough shapes question to stand on its own and hence giving a detailed answer here with all the different possible methods to create this shape.
Using Radial Gradient:
Just adding here for the benefit of others. It's a repeat but makes the answer complete. We can use four ellipses (or circles) created using radial-gradient background images and place them at their appropriate position to create this effect. The output shape is responsive but it cannot be used when the shape should have :hover effects restricted to the shape boundaries or have anything other than a solid color as the fill/background. It also needs a square shaped container (not a rectangle).
div {
width: 300px;
height: 300px;
}
.radial-grad {
background: radial-gradient(circle at 0 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 0, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 0 0, rgba(204, 0, 0, 0) 70%, #c00 71%);
background-position: bottom left, bottom right, top right, top left;
background-size: 50% 50%;
background-repeat: no-repeat;
transform: rotate(45deg);
backface-visibility: hidden;
}
/* just for demo */
div {
transition: all 1s ease;
}
div:hover {
width: 350px;
height: 350px;
}
<div class='radial-grad'></div>
Using SVG:
SVG is the recommended tool for creating such complex shapes. We can easily create the required shape using path element and its various commands. SVG is scalable (responsive), is very easy to create and maintain, allows greater control over the shape like its slope etc. It can support gradient or image backgrounds too. Unlike radial-gradient, this works well with rectangular containers too.
By modifying the control point of the quadratic curve (first coordinate provided after the Q command), we can control the slope/curve of the cut-off area. The d attribute of the path element can be set or modified via JS just like we do for any other HTML attributes.
But we have to remember that SVG is a graphic (image). We can't control a HTML element that you're adding to the page through pure SVG alone. That would need clip-paths or something like that.
svg {
height: 300px;
width: 300px;
}
/* just for demo */
svg {
transition: all 1s;
}
svg:hover {
height: 200px;
width: 250px;
}
<svg viewBox='0 0 200 200'>
<defs>
<pattern id='bg' width='200' height='200' patternUnits='userSpaceOnUse'>
<image xlink:href='https://placeimg.com/200/200/nature' height='200' width='200' />
</pattern>
</defs>
<path d='M0,0 Q100,60 200,0 Q140,100 200,200 Q100,140 0,200 Q60,100 0,0z' fill='url(#bg)'/>
</svg>
Using Clip-path:
This is similar to the pure SVG version but unlike that one where the shape is created and then placed behind or inside the container, here we cut the container element itself into the required shape.
Pure CSS method (without SVG) is available but it doesn't support complex paths yet. It supports only basic shapes and so we have to use clip-path along with a SVG definition. Moreover, Firefox supports it only when used with SVG (like url(#id)). IE still doesn't support clip-path and that's one reason why this is not yet good for production implementations.
This is good when the shape has background as an image or a gradient instead of a solid color and it can also work well when :hover effects are needed because we are cutting out the required paths.
This is more like an inset border-radius because the element doesn't exist outside the clipped area.
div {
height: 300px;
width: 300px;
background-image: url(https://placeimg.com/200/200/nature);
}
.clip-path {
-webkit-clip-path: url(#clipper);
clip-path: url(#clipper);
}
/* just for demo */
div {
transition: all 1s ease;
}
div:hover {
height: 350px;
width: 325px;
}
<svg width='0' height='0'>
<defs>
<clipPath id='clipper' clipPathUnits='objectBoundingBox'>
<path d='M0,0 Q0.5,0.3 1,0 Q0.7,0.5 1,1 Q0.5,0.7 0,1 Q0.3,0.5 0,0z' />
</clipPath>
</defs>
</svg>
<div class='clip-path'></div>
Using Masks:
This feature is currently supported only by WebKit powered browsers and hence isn't recommended now but it is a very good option for the future. This approach is especially useful when the shape's background would be an image or a gradient and not just a solid color.
The working of masks is very similar to the radial-gradient approach but the difference lies in the fact that unlike radial-gradient which fills the remaining space with solid color, this would just mask out the unwanted portions and not add any fill of its own. So, the background image that is assigned to the element originally will be preserved.
This method is not good if we want to have :hover effects that is restricted to the boundaries of the shape as it doesn't cut out the unwanted portions, it just masks them out or make it transparent.
Similar to the radial-gradient approach, this also needs a square shaped container to work but it is otherwise responsive.
div {
height: 300px;
width: 300px;
background-image: url(https://placeimg.com/200/200/nature);
}
.mask {
-webkit-mask-image: radial-gradient(circle at 0 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 100%, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 100% 0, rgba(204, 0, 0, 0) 70%, #c00 71%), radial-gradient(circle at 0 0, rgba(204, 0, 0, 0) 70%, #c00 71%);
-webkit-mask-position: bottom left, bottom right, top right, top left;
-webkit-mask-size: 50% 50%;
-webkit-mask-repeat: no-repeat;
transform: rotate(45deg);
backface-visibility: hidden;
}
/* just for demo */
div {
transition: all 1s ease;
}
div:hover {
height: 350px;
width: 350px;
}
<div class='mask'></div>
Using Pseudo element and Box shadows:
I don't recommend this approach as it has a lot of drawbacks but is still an option. If we just need to create the shape, don't require :hover effects, don't require the cut off areas to be transparent (that's the cut-off areas can be a solid color, like white in this snippet) then we can try this approach.
It involves placing 2 elliptical pseudo-elements on the top, left side and then getting their shadows to do the work on their opposite sides.
div {
position: relative;
height: 300px;
width: 300px;
background: #c00;
}
div:before {
position: absolute;
content: '';
height: 50%;
width: 110%;
top: -35%;
left: -5%;
background: white;
border-radius: 50%;
box-shadow: 0px 360px 0px 0px white;
}
div:after {
position: absolute;
content: '';
width: 50%;
height: 110%;
left: -35%;
top: -5%;
background: white;
border-radius: 50%;
box-shadow: 360px 0px 0px 0px white;
}
<div></div>

Is it possible to animate background: linear-gradient using CSS 3 Animations? [duplicate]

I have several animations on my site that I just realized do not even show up in Firefox or Internet Explorer. I have the background-image within the keyframes. I do this because I have different images in different percentages with the animation.
Why doesn't the background-image display within the keyframes in Firefox and Internet Explorer and is there a way to make this work?
As per the specs, background-image is not an animatable or a transitionable property. But it does not seem to say anything about what or how the handling should be when it is used as part of transition or animation. Because of this, each browser seem to be handling it differently. While Chrome (Webkit) is displaying the background image, Firefox and IE seem to do nothing.
The below quote found in an article at oli.jp provides some interesting information:
While CSS Backgrounds and Borders Module Level 3 Editor’s Draft says “Animatable: no” for background-image at the time of writing, support for crossfading images in CSS appeared in Chrome 19 Canary. Until widespread support arrives this can be faked via image sprites and background-position or opacity. To animate gradients they must be the same type.
On the face of it, it looks like Firefox and IE are handling it correctly while Chrome is not. But, it is not so simple. Firefox seems to contradict itself when it comes to how it handles transition on background image as opposed to animation. While transitioning background-image, it shows up the second image immediately (hover the first div in the snippet) whereas while animating, the second image doesn't get displayed at all (hover the second div in the snippet).
So, conclusion is that it is better to not set background-image inside keyframes. Instead, we have to use background-position or opacity like specified # oli.jp.
div {
background-image: url(https://placehold.it/100x100);
height: 100px;
width: 100px;
margin: 10px;
border: 1px solid;
}
div:nth-of-type(1) {
transition: background-image 1s ease;
}
div:nth-of-type(1):hover {
background-image: url(https://placehold.it/100/123456/ffffff);
}
div:nth-of-type(2):hover {
animation: show-img 1s ease forwards;
}
#keyframes show-img {
to {
background-image: url(https://placehold.it/100/123456/ffffff);
}
}
<div></div>
<div></div>
If you have multiple images that should be shown at different percentages within the keyframe then it would be a better idea to add all those images on the element at start and animate their position like in the below snippet. This works the same way in Firefox, Chrome and IE.
div {
background-image: url(https://placehold.it/100x100), url(https://placehold.it/100/123456/ffffff);
background-size: 100% 100%;
background-repeat: no-repeat;
background-position: 0px 0px, 100px 0px;
height: 100px;
width: 100px;
margin: 10px;
border: 1px solid;
}
div:hover {
animation: show-img 1s steps(1) forwards;
}
#keyframes show-img {
to {
background-position: -100px 0px, 0px 0px;
}
}
<div></div>
Or, like in the below snippet. Basically each image is the same size as the container as background-size is set as 100% 100% but only one image is shown at any given time because of them being the same size as container. Between 0% to 50% the first image is shown because it is at 0px,0px (left-top) whereas the second image is at 100px,0px (outside the right border). At 50.1%, the first image is at -100px,0px (outside left border) and second image is at 0px,0px and so it is visible.
div {
background-image: url(https://picsum.photos/id/0/367/267), url(https://picsum.photos/id/1/367/267);
background-size: 100% 100%; /* each image will be 100px x 100px */
background-repeat: no-repeat;
background-position: 0px 0px, 100px 0px;
height: 100px;
width: 100px;
margin: 10px;
border: 1px solid;
animation: show-img 5s ease forwards;
}
#keyframes show-img {
0%, 50%{
background-position: 0px 0px, 100px 0px; /* initially 1st image will be shown as it it as 0px 0px */
}
50.1%, 100% {
background-position: -100px 0px, 0px 0px; /* at 50.1% 2nd image will be shown as it it as 0px 0px */
}
}
<div></div>

Responsive Animated Background in Bootstrap?

After following the instructions here: https://davidwalsh.name/background-animation-css
I can make the picture move, but I cannot figure out how to make it responsive. Any ideas on how to make this possible? I have added following css code:
#keyframes animatedBackground{
from {background-position: 0 0;}
to {background-position: -1920px 0;}
}
#animate-area{
width: 560px;
height: 400px;
background-image: url("images/japan.jpg");
background-position: 0px 0px;
background-repeat: repeat-x;
animation: animatedBackground 40s linear infinite;
}
Within the demo, the width of <div id="animate-area"> is explicitly set to 560px. Try setting it to width: auto;. This should scale the div width to that of it's container/parent.

Categories