難易度:★★★★★ MAX
概要
今回は、
① CSSのグリッドレイアウト
② CSSのキーフレーム
③ JavaScriptのsetTimeout()メソッド
の3本立てで、汎用的な「フェードイン」の動きをご紹介したいと思います。
今回は、見易いように角丸要素にアニメーションを加えていますが、
CSSの値を変える事で、長方形の要素にも応用可能です。
製作したもの
Click here!
製作手順と解説
以下のパターンA,B,Cを、順を追って見ていくと、より一層理解が深まります。
パターンA グリッドで作図
HTML
<div class="figure">
<div class="area-1"><span>1</span></div>
<div class="area-2"><span>2</span></div>
<div class="area-3"><span>3</span></div>
<div class="area-4"><span>4</span></div>
</div>
CSS
.figure {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 1fr;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"area-1 area-2"
"area-3 area-4";
aspect-ratio: 1;
margin-right:40%;
border:solid;
}
.figure > div{
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 4vw;
}
.figure .area-1 {
grid-area: area-1;
background-color: #00ff00;
}
.figure .area-2 {
grid-area: area-2;
background-color: #ffff00;
}
.figure .area-3 {
grid-area: area-3;
background-color: #ff0000;
}
.figure .area-4 {
grid-area: area-4;
background-color: #ff00ff;
}
解説
グリッドレイアウトで4つのエリアを作ります。
グリッドレイアウトは、そのままではCSSの設定が難しいので、
Layoutit Gridを使用しています。
これにより視覚的なグリッドレイアウトが可能になります。
パターンB グリッドエリアを回転させる
試作
試作①
試作②
HTML
試作①
<div class="figure rotate">
<div class="area-1">
<span>1</span>
<span class="point _a">A</span>
<span class="point _b">B</span>
<span class="point _c">C</span>
<span class="point _d">D</span>
</div>
<div class="area-2"><span>2</span></div>
<div class="area-3"><span>3</span></div>
<div class="area-4"><span>4</span></div>
</div>
試作②
<div class="figure rotate" style="border-radius:50%; overflow:hidden;">
<div class="area-1">
<span>1</span>
</div>
<div class="area-2"><span>2</span></div>
<div class="area-3"><span>3</span></div>
<div class="area-4"><span>4</span></div>
</div>
CSS(試作①②共通)
.figure {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 1fr;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"area-1 area-2"
"area-3 area-4";
aspect-ratio: 1;
margin:0 30% 0 10%;
border:solid;
}
.figure > div{
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 4vw;
/* 追加 */
position: relative;
}
.figure .area-1 {
grid-area: area-1;
background-color: #00ff00;
}
.figure .area-2 {
grid-area: area-2;
background-color: #ffff00;
}
.figure .area-3 {
grid-area: area-3;
background-color: #ff0000;
}
.figure .area-4 {
grid-area: area-4;
background-color: #ff00ff;
}
/* 追加 */
.figure.rotate{
margin-top: calc(50% * calc(sqrt(2) - 1));
margin-bottom: calc(50% * calc(sqrt(2) - 1));
}
.figure.rotate .area-1{
animation:spin-r 12s linear infinite;
transform-origin: bottom right;
z-index: 1;
}
.figure.rotate .area-1 span{
animation:spin-l 12s linear infinite;
}
.figure > div .point{
position: absolute;
color: #000;
font-size: 3vw;
line-height: 3vw;
z-index: 1;
background-color: #00ffff;
padding: 1vw;
}
.figure > div ._a{
top: -5vw;
left: -5vw;
}
.figure > div ._b{
top: -5vw;
right: -5vw;
}
.figure > div ._c{
bottom: -5vw;
right: -5vw;
}
.figure > div ._d{
bottom: -5vw;
left: -5vw;
}
/* キーフレーム */
@keyframes spin-l {
from {transform: rotate(360deg);}
to {transform: rotate(0);}
}
@keyframes spin-r {
from {transform: rotate(0);}
to {transform: rotate(360deg);}
}
解説
これらは、グリッドアイテムそのものを回転させています。
正方形A,B,C,Dの回転中心を点Cとします。
試作①により、図形をスライドさせなくても、回転の動きだけで、
他の図形に重ねる事が出来ます。
プロパティと値のtransform-origin: bottom right;は、
図形1の右下部分が、基礎図形の中心点と同一になっている為です。
図形1を回転させているキーフレームは@keyframes spin-rです。
rotateの値(角度)は0(0deg)~360degを設定出来、正の値では右回転となります。
from {transform: rotate(0);}
to {transform: rotate(360deg);}
fromとtoのプロパティで、開始点と終了点の値を簡易的に設定します。
animation:spin-r 12s linear infinite;の3番目の値は
animation-timing-functionという関数であり、
その名の通り、アニメーションのタイミングを設定する関数ですが、
実際に使ってみた方が理解するのが早いでしょう。
2番目の値はアニメーションのループの長さで、1sは1秒であり、
4番目の値はインフィニティで、無限に繰り返す事を意味しています。
パターンC 扇形を折り畳む
試作
試作①
Click here!
試作②
Click here!
HTML
試作①
<div class="arc-figure arc-figure-1">
<div class="area-1">
<div class="quarter"><span>1</span></div>
</div>
<div class="area-2">
<div class="quarter"><span>2</span></div>
</div>
<div class="area-3">
<div class="quarter"><span>3</span></div>
</div>
<div class="area-4">
<div class="quarter"><span>4</span></div>
</div>
</div>
試作②
<div class="arc-figure arc-figure-2">
<div class="area-1">
<div class="quarter"><span>1</span></div>
</div>
<div class="area-2">
<div class="quarter"><span>2</span></div>
</div>
<div class="area-3">
<div class="quarter"><span>3</span></div>
</div>
<div class="area-4">
<div class="quarter"><span>4</span></div>
</div>
</div>
CSS(試作①②共通)
.arc-figure {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 1fr;
gap: 0px 0px;
grid-auto-flow: row;
grid-template-areas:
"area-1 area-2"
"area-4 area-3";
aspect-ratio: 1;
margin: 0 30% 0 10%;
border: solid;
border-radius: 50%;
overflow: hidden;
}
.arc-figure > div{
overflow: hidden;
}
.arc-figure > div > div{
height: 100%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
font-size: 4vw;
}
.arc-figure > div > div.active{
animation:arc-fold .5s linear forwards;
}
.arc-figure .area-1 {grid-area: area-1;}
.arc-figure .area-2 {grid-area: area-2;}
.arc-figure .area-3 {grid-area: area-3;}
.arc-figure .area-4 {grid-area: area-4;}
.arc-figure .area-1 > div {
background-color: #00ff00;
transform-origin: bottom right;
}
.arc-figure .area-2 > div {
background-color: #ffff00;
transform-origin: bottom left;
}
.arc-figure .area-3 > div {
background-color: #ff0000;
transform-origin: top left;
}
.arc-figure .area-4 > div {
background-color: #ff00ff;
transform-origin: top right;
}
@keyframes arc-fold{
from{
transform:rotate(0);
}
to{
transform:rotate(90deg);
display:none;
}
}
JavaScript(試作①②共通)
const arc_1 = document.querySelector(".arc-figure-1");
const arc_1_quarter = arc_1.querySelectorAll(".quarter");
const arc_2 = document.querySelector(".arc-figure-2");
const arc_2_quarter = arc_2.querySelectorAll(".quarter");
function FoldTimeInterval(quarter,time){
if(!time){time = 0}
if(quarter.length == 4){
for(let i = 0; i < 4; i++){
window.setTimeout(function(){
quarter[i].classList.add("active");
},i * time);
}
}
}
arc_1.addEventListener("click",function(){
FoldTimeInterval(arc_1_quarter,500);
});
arc_2.addEventListener("click",function(){
FoldTimeInterval(arc_2_quarter,0);
});
解説
これが完成形で、後はquarterクラスセレクタの背景色を、
バックと同化させ、span要素を取り除き、
一番上の要素に背景画像などを設定してください。
また、要素を折り畳む順番の関係上これまでのパターンA,Bとは、
3と4の位置が反転しています。
これらはCSSのキーフレームとJavaScriptのイベントリスナー、
window.setTimeout()メソッドを用いて、各エリアを連続的、
または同時にCSSのtransformプロパティで動かします。
★ overflow:hidden; について
パターンBの試作②で角を丸める為に、
overflow:hidden;のプロパティ値を設定しましたが、こちらで説明します。
パターンB以前はグリッドアイテムそのものを動かしていましたが、
quarterクラスを持つ要素をそれぞれ入れます。
transformプロパティを使えば、子要素が親要素の領域外に出ても
表示されますが、親要素または祖先要素がoverflow:hidden;を指定している場合、
要素からはみ出た部分が遮蔽されるのです。
/* キーワード値 */
overflow: visible;
overflow: hidden;
overflow: clip;
overflow: scroll;
overflow: auto;
overflow: hidden visible;
/* グローバル値 */
overflow: inherit;
overflow: initial;
overflow: revert;
overflow: unset;
ovarflowプロパティは直下の要素のみならず、子孫全てに影響します。
その為、プロパティを設定する際は、後で忘れない事が重要です。
具体的に、グリッドアイテムにoverflowプロパティを設定しなかった場合、
動かしたい子要素が隣へとはみ出してしまいます。
Click here!
ちなみにアニメーションのforwardsとは、インフィニティの逆で、
1回のみ動作を実行します。
まとめ
グリッドレイアウトにより、扇形を作る技術を応用すれば、
このような円グラフを作成する事も可能になると思います。
※イメージ
今回は、お付き合い頂きありがとうごじます。
また次回、よろしくお願いします。
HTML/CSS/JavaScript (完成品)
HTML
<div class="square-circle">
<div class="area-1"><div class="quarter"></div></div>
<div class="area-2"><div class="quarter"></div></div>
<div class="area-3"><div class="quarter"></div></div>
<div class="area-4"><div class="quarter"></div></div>
</div>
CSS
.square-circle,
.square-circle::after{
width: 75vmin;
height: 75vmin;
border-radius: 50%;
}
.square-circle {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
grid-auto-columns: 1fr;
grid-auto-flow: row;
grid-template-areas:
"area-1 area-2"
"area-4 area-3";
background-image: url(https://mf-ken.com/note/wp-content/uploads/2024/04/IMG_2840-scaled.jpg);
background-size: cover;
background-position: center;
}
.square-circle::after{
position:absolute;
content:"";
border:solid;
border-radius:50%;
box-sizing:border-box;
}
.square-circle > div{overflow:hidden;}
.square-circle .area-1 { grid-area: area-1; }
.square-circle .area-2 { grid-area: area-2; }
.square-circle .area-3 { grid-area: area-3; }
.square-circle .area-4 { grid-area: area-4; }
.cn-j-j .square-circle > div > div{
height:100%;
background-color:#fff;
}
.square-circle > div > div.active{
animation:square-circle .15s linear forwards;
}
.square-circle .area-1 > div{
transform-origin:bottom right;
}
.square-circle .area-2 > div{
transform-origin:bottom left;
}
.square-circle .area-3 > div{
transform-origin:top left;
}
.square-circle .area-4 > div{
transform-origin:top right;
}
@keyframes square-circle{
from{
transform:rotate(0);
}
to{
transform:rotate(90deg);
display:none;
}
}
JavaScript
const circle = document.querySelector(".square-circle");
const circle_quarter = circle.querySelectorAll(".quarter");
circle.addEventListener("click",function(){
for(let i = 0; i < 4; i++){
window.setTimeout(function(){
circle_quarter[i].classList.add("active");
},i * 150);
}
});