I'd like to simulate a particle explosion, from the center of a screen out to the edges (In CSS, and I promise to not use this for nefarious purposes)
Here's a visual so you know what I'm talking about:
BEFORE:
AFTER:
I've tried using the following HTML/CSS/JS, but it doesn't work (dots stay still in the middle of the screen):
The HTML is just this:
<div id="animated"></div>
The CSS:
// SCSS
#animated {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
.particle {
position: absolute;
left: 50%;
top: 50%;
width: 10px;
height: 10px;
transition: transform 1s ease-in-out;
&.on {
transform: translate(-30vw, -30vh);
}
&::after {
position: absolute;
content: "";
width: 10px;
height: 10px;
border-radius: 50%;
background: red;
}
}
}
And the Javascript:
document.addEventListener('DOMContentLoaded', onLoad);
function onLoad() {
// animate
for(var i = 0; i < 360; i+=5) {
const particle = createParticle(animated, i);
}
}
function createParticle(parentElem, rotation) {
const particle = document.createElement('div');
particle.style.transform = `rotate(${rotation}deg)`;
particle.classList.add('particle');
particle.classList.add('on'); // turn on
parentElem.appendChild(particle);
return particle;
}
Here's a link to a CodePen: https://codepen.io/floatingrock/pen/KKpxpvJ
Here is an idea with CSS variable where it's easy to adjust with few code.
Run on full screen for better result:
document.addEventListener('DOMContentLoaded', onLoad);
function onLoad() {
let parentElem = document.querySelector('.container');
for (var i = 0; i < 360; i += 10) {
const particle = document.createElement('div');
particle.style = `--r:${i}deg`;
parentElem.appendChild(particle);
}
}
.container {
width: 20px;
height: 20px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.container>div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background: red;
transform: rotate(var(--r, 0deg)) translate(0);
animation: splash 1s infinite alternate 1s;
}
#keyframes splash {
to {
transform: rotate(var(--r, 0deg)) translate(44vmin);
}
}
<div class="container">
</div>
You can consider different delay for another kind of animation:
document.addEventListener('DOMContentLoaded', onLoad);
function onLoad() {
let parentElem = document.querySelector('.container');
for (var i = 0; i < 360; i += 10) {
const particle = document.createElement('div');
particle.style = `--r:${i}deg;--d:${(i/360)}s`;
parentElem.appendChild(particle);
}
}
.container {
width: 20px;
height: 20px;
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.container>div {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
border-radius: 50%;
background: red;
transform: rotate(var(--r, 0deg)) translate(0);
animation: splash 1s infinite alternate var(--d,0s);
}
#keyframes splash {
to {
transform: rotate(var(--r, 0deg)) translate(44vmin);
}
}
<div class="container">
</div>
We can still optimize the code with less CSS:
document.addEventListener('DOMContentLoaded', onLoad);
function onLoad() {
let parentElem = document.querySelector('.container');
for (var i = 0; i < 360; i += 10) {
const particle = document.createElement('div');
particle.style = `--r:${i}deg`;
parentElem.appendChild(particle);
}
}
.container > div {
position: fixed;
top: 50%;
left: 50%;
width: 20px;
height: 20px;
border-radius: 50%;
background: red;
transform:translate(-50%, -50%) rotate(var(--r, 0deg)) translate(0);
animation: splash 1s infinite alternate 1s;
}
#keyframes splash {
to {
transform:translate(-50%, -50%) rotate(var(--r, 0deg)) translate(calc(50vmin - 10px));
}
}
/* Irrelevant styles */
html {
height:100%;
border:1px solid blue; /* screen border*/
box-sizing:border-box;
background:linear-gradient(green,green) center/10px 10px no-repeat; /* the center of the screen */
}
body {
margin:0;
}
<div class="container">
</div>
The order of transformation is important. Related: Why does order of transforms matter? rotate/scale doesn't give the same result as scale/rotate
Related
I have the following overlay
<div id="overlay"></div>
#overlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2;
cursor: pointer;
}
Which pops up instantly. I would like to make this overlay cover the screen with an animation effect, appear from right to left within 1000 miliseconds.
I understand this is feasible with jQuery but I dont want to install it in my Angular app. Is it possible to make it with typescript together with CSS?
Thanks.
Yes, you can use animation with #keyframes:
#overlay {
position: fixed;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0,0,0,0.5);
z-index: 2;
cursor: pointer;
animation: slide-in 1s both;
}
#keyframes slide-in {
from {
transform: translateX(100%);
}
to {
transform: translateX(0);
}
}
<div id="overlay"></div>
On my website, I'm trying to make a simple white full-screen loader with one <div> element, but instead of going to the right at the end, the <div> element goes partially to the left, then snaps to the right. Any ideas on how to fix this? Here's a demo:
body {
background-color: #121212;
}
div#l {
position: absolute;
height: 100%;
top: 0;
background-color: white;
animation: loader 2s infinite;
}
#keyframes loader {
from {
left: 0;
width: 0;
}
49% {
width: 100%;
left: 0;
}
51% {
width: 100%;
right: 0;
}
to {
width: 0;
right: 0;
}
}
<div id='l'></div>
You should divide your keyframe in three equal parts.
from to 33%: the white div appear
from 33% to 66%: change the position of the div
from 66% to to: the white div disappear
Edit you keyframe like this:
#keyframes loader {
from {
left: 0;
width: 0;
}
33% {
width: 100%;
left: 0;
}
66% {
width: 100%;
right: 0;
}
to {
right: 0;
width: 0;
}
}
body {
background-color: #121212;
}
div#l {
position: absolute;
height: 100%;
top: 0;
background-color: white;
animation: loader 2s infinite;
}
#keyframes loader {
from {
left: 0;
width: 0;
}
33% {
width: 100%;
left: 0;
}
66% {
width: 100%;
right: 0;
}
to {
right: 0;
width: 0;
}
}
<div id='l'></div>
As you can see in this way the speed of the animation is not linear, and it is not the result we want.
I sugget you to divide the keyframe in two parts:
from to 50%: the white div appear
from 50% to to: the white div move itself to it's max left position
Therefore:
#keyframes loader {
from {
left: 0;
width: 0;
}
50% {
left: 0;
width: 100%;
}
to {
left: 100%;
width: 0;
}
}
body {
background-color: #121212;
}
div#l {
position: absolute;
height: 100%;
top: 0;
background-color: white;
animation: loader 2s infinite;
}
#keyframes loader {
from {
left: 0;
width: 0;
}
50% {
left: 0;
width: 100%;
}
to {
left: 100%;
width: 0;
}
}
<div id='l'></div>
I want to have two parts of one image to be join into one original image, where each one part should be a triangle form.
I've found a codepen where there are two elements with nested images, where i removed margins, but there is an ugly white border(gap) between elements.
How can i remove this one?
<div class='pageOption'>
<a href='#' class='option' data-inf='photo'>
<img src='http://imgsrc.hubblesite.org/hu/db/images/hs-2013-06-a-large_web.jpg'>
</a>
<a href='#' class='option' data-inf='cinema'>
<img src='http://imgsrc.hubblesite.org/hu/db/images/hs-2013-06-a-large_web.jpg'>
</a>
</div>
body { background: gainsboro; }
.pageOption {
overflow: hidden;
position: relative;
margin: 0 auto;
width: 40em; height: 27em;
}
.option, .option img { width: 100%; height: 100%; }
.option {
overflow: hidden;
position: absolute;
/* arctan(27 / 40) = 34.01935deg
* need to skew by 90deg - 34.01935deg = 55.98065deg
*/
transform: skewX(-55.98deg);
}
.option:first-child {
/* left: -.25em; */
transform-origin: 100% 0;
}
.option:last-child {
/* right: -.25em; */
transform-origin: 0 100%;
}
.option img { opacity: 1; transition: .5s; }
.option img:hover { opacity: 1; }
.option img, .option:after {
transform: skewX(55.98deg);
transform-origin: inherit;
}
.option:after {
position: absolute;
margin: .5em 1.65em;
color: white;
font: 500 1.25em Courier;
letter-spacing: .1em;
text-transform: uppercase;
content: attr(data-inf);
}
.option:first-child:after { top: 0; left: 0; }
.option:last-child:after { right: 0; bottom: 0; }
Change these styles
.option:first-child {
left: 0.1em;
transform-origin: 100% 0;
}
.option:last-child {
right: 0;
transform-origin: 0 100%;
}
I have two cascading layers, bottom layer's border color is red, top layer's border color is gray.
When added 'border-radius' property, bottom layer's red will overflow. When remove 'border-radius', it's ok.
I wonder how to clear it out?
.arc,
.cover {
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border: 25px solid #ccc;
border-radius: 50%;
box-sizing: border-box;
}
.arc {
border: 25px solid red;
}
<div class="cnt">
<div class="arc"></div>
<div class="cover"></div>
</div>
What I really want to do is a circle progress widget like below. You will see the overflow red in the first 1 seconds.
problem detail screenshot
$(function() {
var bottomDiv = $('.circle-progress-bottom');
var leftDiv = $('.circle-progress-left');
var rightDiv = $('.circle-progress-right');
var coverDiv = $('.circle-progress-cover');
var seconds = 5;
var intervalID = setInterval(function() {
if (seconds.toString().length === 1) {
bottomDiv.html(seconds + 's');
}
if (seconds === 5) {
leftDiv.addClass('circle-progress-left-rotate');
} else if (seconds === 2.5) {
rightDiv.css('opacity', 1);
coverDiv.css('opacity', 0);
rightDiv.addClass('circle-progress-right-rotate');
}
seconds = seconds - 0.5;
if (seconds < -1) {
clearInterval(intervalID);
}
}, 500);
});
.circle-progress-ring {
position: relative;
width: 80px;
height: 80px;
}
.circle-progress-bottom,
.circle-progress-left,
.circle-progress-right,
.circle-progress-cover {
position: absolute;
top: 0;
left: 0;
width: 80px;
height: 80px;
border: 3px solid #FA6B4E;
border-radius: 50%;
box-sizing: border-box;
}
.circle-progress-cover,
.circle-progress-bottom {
font-size: 20px;
text-align: center;
line-height: 80px;
color: #eee;
font-weight: bold;
border: 3px solid #ccc;
}
.circle-progress-left,
.circle-progress-right,
.circle-progress-cover {
clip: rect(0 40px 80px 0);
}
.circle-progress-right {
transform: rotate(180deg);
opacity: 0;
}
.circle-progress-left-rotate {
animation: leftRotate 2.5s linear;
animation-fill-mode: forwards;
}
.circle-progress-right-rotate {
animation: rightRotate 2.5s linear;
animation-fill-mode: forwards;
}
#keyframes leftRotate {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(180deg);
}
}
#keyframes rightRotate {
0% {
transform: rotate(180deg);
}
100% {
transform: rotate(360deg);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="circle-progress-ring">
<div class="circle-progress-bottom"></div>
<div class="circle-progress-left"></div>
<div class="circle-progress-right"></div>
<div class="circle-progress-cover"></div>
</div>
Fiddle: http://jsfiddle.net/y7d4kkxz/
HTML:
<div class="app">
<div class="content">
<div class="wrapper">
Content here.
<button class="doit">...</button>
</div>
</div>
</div>
CSS:
.app {
background: #003;
position: absolute;
left: 0;
top: 0;
bottom: 0;
right: 0;
width: auto;
height: auto;
}
.content {
background: #fff;
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
width: auto;
height: auto;
overflow-x: hidden;
overflow-y: auto;
transition: 500ms;
}
.menu-open .content {
transform: translate3d(40%, 0px, 0px) scale3d(0.85, 0.85, 0);
}
.wrapper {
margin: 5%;
}
JS:
$(function () {
$('.doit').on('click', function () {
$('.app').toggleClass('menu-open');
});
});
scale3d(0.85, 0.85, 0) will scale the Z axis of the element to 0, and it will disappear. You could use 1 instead, but it doesn’t look like you need 3D transformations at all up to this point:
.menu-open .content {
transform: translateX(40%) scale(0.85);
}
Updated fiddle