<div class="start-anim-01" id="js-start-anim-01">
<div class="start-anim-01__content">
<p class="start-anim-01__text"><span class="start-anim-01__count">0</span>%</p>
<div class="start-anim-01__progress">
<div class="start-anim-01__progress-val"></div>
</div>
</div>
</div>
<div><img src="https://picsum.photos/id/1000/1200/600" width="400px" /><img src="https://picsum.photos/id/1001/1200/600" width="400px" /><img src="https://picsum.photos/id/1002/1200/600" width="400px" /><img src="https://picsum.photos/id/1003/1200/600" width="400px" /><img src="https://picsum.photos/id/1004/1200/600" width="400px" /><img src="https://picsum.photos/id/1005/1200/600" width="400px" /><img src="https://picsum.photos/id/1006/1200/600" width="400px" /><img src="https://picsum.photos/id/1008/1200/600" width="400px" /><img src="https://picsum.photos/id/1009/1200/600" width="400px" /><img src="https://picsum.photos/id/1010/1200/600" width="400px" /></div>
.start-anim-01#js-start-anim-01
.start-anim-01__content
p.start-anim-01__text
span.start-anim-01__count 0
| %
.start-anim-01__progress
.start-anim-01__progress-val
div
each item in items
img(src=item.img, width='400px')
{
"items": [
{
"img": "https://picsum.photos/id/1000/1200/600"
},
{
"img": "https://picsum.photos/id/1001/1200/600"
},
{
"img": "https://picsum.photos/id/1002/1200/600"
},
{
"img": "https://picsum.photos/id/1003/1200/600"
},
{
"img": "https://picsum.photos/id/1004/1200/600"
},
{
"img": "https://picsum.photos/id/1005/1200/600"
},
{
"img": "https://picsum.photos/id/1006/1200/600"
},
{
"img": "https://picsum.photos/id/1008/1200/600"
},
{
"img": "https://picsum.photos/id/1009/1200/600"
},
{
"img": "https://picsum.photos/id/1010/1200/600"
}
]
}
$BLOCK_NAME: '.start-anim-01';
// 変数
$color_primary: #333;
$color_progress_bg: #666;
$color_progress_val: #fff;
$color_white: #fff;
$duration_default: 0.3s;
#{ $BLOCK_NAME } {
position: fixed;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
background: $color_primary;
&__content {
width: 100%;
}
&__text {
margin-bottom: 8px;
color: $color_white;
text-align: center;
}
&__progress {
position: relative;
width: 100%;
height: 2px;
background: $color_progress_bg;
}
&__progress-val {
position: absolute;
top: 0;
left: 0;
display: block;
width: 0;
height: 2px;
background: $color_progress_val;
transition: width $duration_default;
}
}
'use strict';
import { gsap } from 'gsap';
export const startAnim01 = () => {
const anim = new StartAnim01('js-start-anim-01');
anim.init();
}
class StartAnim01 {
el: HTMLElement;
imgEls: NodeListOf<HTMLElement>;
videoEls: NodeListOf<HTMLElement>;
totalElNum: number;
loadedElNum: number;
loadedPercent: number;
countEl: HTMLElement;
progressValEl: HTMLElement;
constructor(elId: string) {
this.el = document.getElementById(elId);
if (!this.el) return;
this.imgEls = document.querySelectorAll('img:not([loading="lazy"])');
this.videoEls = document.querySelectorAll('video');
this.totalElNum = this.imgEls.length + this.videoEls.length;
this.loadedElNum = 0;
this.loadedPercent = 0;
this.countEl = this.el.querySelector('.start-anim-01__count');
this.progressValEl = this.el.querySelector('.start-anim-01__progress-val');
}
/**
* 初期化
*/
init(): void {
if (!this.el) return;
this.fixWindow();
this.loadHandler();
}
/**
* ウインドウ固定
*/
fixWindow(): void {
const scrollBarWidth = window.innerWidth - document.body.clientWidth;
document.body.style.paddingRight = `${scrollBarWidth}px`;
document.documentElement.style.overflow = 'hidden';
}
/**
* ウインドウ固定を解除
*/
clearWindow(): void {
document.body.style.paddingRight = null;
document.documentElement.style.overflow = null;
}
/**
* 読み込み量の更新
*/
updateLoader(): void {
this.loadedElNum += 1;
// 画像・動画以外の読込を考慮し、90%までの進捗表示にする
const percent = Math.ceil(this.loadedElNum / this.totalElNum * 90);
this.countEl.textContent = percent.toString();
this.progressValEl.style.width = `${percent}%`;
// 読み込み完了後、ローダーを非表示にする
if (this.loadedElNum >= this.totalElNum) {
setTimeout(() => {
this.hideLoader();
}, 500);
}
}
/**
* 要素ロード時のイベント設定
*/
loadHandler(): void {
// 画像のロードイベント
[...this.imgEls].forEach(el => {
el.addEventListener('load', () => {
this.updateLoader();
});
});
// 動画のロードイベント
[...this.videoEls].forEach(el => {
el.addEventListener('loadeddata', () => {
this.updateLoader();
});
});
// ページロード完了時のイベント
window.onload = () => {
this.loadedElNum = this.totalElNum;
this.updateLoader();
};
}
/**
* ローダー非表示
*/
hideLoader(): void {
this.clearWindow();
gsap.to(this.el, {
duration: 1,
opacity: 0,
onComplete: () => {
// ローダー要素を削除
this.el.remove();
}
});
}
}