<div class="other-27" id="js-other-27">
<div class="other-27__main">
<div class="other-27__spacer"></div>
<div class="other-27__inner">
<div class="other-27__text"><span>TEXT</span></div>
<div class="other-27__img"><img src="https://picsum.photos/id/238/450/800" /></div>
<div class="other-27__text --front"><span>TEXT</span></div>
</div>
<div class="other-27__spacer"></div>
</div>
<div class="other-27__bg"></div>
</div>
.other-27#js-other-27
.other-27__main
.other-27__spacer
.other-27__inner
.other-27__text
span TEXT
.other-27__img
img(src=img)
.other-27__text.--front
span TEXT
.other-27__spacer
.other-27__bg
{
"img": "https://picsum.photos/id/238/450/800"
}
$BLOCK_NAME: '.other-27';
// 変数
$offset_bg: -20px;
#{ $BLOCK_NAME } {
position: relative;
padding: 32px;
overflow: hidden;
background: rgb(75, 34, 19);
&__main {
position: relative;
z-index: 1;
min-height: 200vh;
background: #fff;
padding: 32px;
clip-path: polygon(
100% 100%,
74% 100%,
0 100%,
0% 97%,
0% 88%,
1% 81%,
0% 77%,
2% 68%,
1% 58%,
1% 51%,
2% 42%,
1% 37%,
1% 30%,
2% 23%,
1% 14%,
0% 7%,
0% 2%,
0% 0%,
100% 0%,
100% 4%,
99% 9%,
98% 17%,
98% 27%,
100% 32%,
99% 40%,
100% 50%,
98% 63%,
99% 72%,
100% 79%,
99% 92%
);
}
&__spacer {
height: 100vh;
}
&__inner {
position: relative;
}
// TODO: 参考にしたサイトのCSSの付け方のほうがレスポンシブ対応にいい?transform 3d上手く使えないので一旦このまま
&__img {
position: relative;
z-index: 2;
aspect-ratio: 9 / 16;
height: 400px;
margin: 0 auto;
transform-origin: 0 -1200px;
// transform: rotate(-20deg);
clip-path: polygon(
0% 98%,
3% 100%,
12% 100%,
16% 99%,
22% 99%,
29% 100%,
37% 98%,
48% 98%,
56% 100%,
69% 98%,
75% 100%,
84% 99%,
92% 99%,
98% 99%,
100% 94%,
100% 88%,
99% 85%,
100% 78%,
99% 73%,
100% 67%,
98% 61%,
99% 54%,
98% 46%,
99% 37%,
97% 29%,
100% 18%,
99% 5%,
95% 0%,
86% 1%,
79% 0%,
68% 0%,
64% 4%,
58% 0%,
51% 1%,
46% 3%,
37% 1%,
29% 0%,
17% 1%,
13% 0%,
6% 0%,
1% 0%,
0% 4%,
0% 13%,
1% 20%,
1% 27%,
0% 33%,
0% 44%,
1% 53%,
0% 63%,
1% 69%,
0% 79%,
2% 83%,
0% 90%
);
}
&__text {
pointer-events: none;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
margin: auto;
text-align: center;
display: flex;
align-items: center;
justify-content: center;
> span {
font-size: 200px;
line-height: 1;
font-weight: bold;
}
&.--front {
z-index: 2;
-webkit-text-stroke-color: #000;
-webkit-text-stroke-width: 2px;
-webkit-text-fill-color: transparent;
}
}
&__bg {
position: absolute;
top: $offset_bg;
left: $offset_bg;
right: $offset_bg;
bottom: $offset_bg;
background: url(/parts/img/components/others/other27/noise.jpg);
mix-blend-mode: screen;
background-size: 100px 100px;
opacity: 0.7;
animation: other27Noise 0.5s steps(2) infinite;
}
}
@keyframes other27Noise {
0% {
transform: translate(0, 0);
}
33.333% {
transform: translate(20px, 20px);
}
66.666% {
transform: translate(-20px, -20px);
}
100% {
transform: translate(0, 0);
}
}
'use strict';
import { gsap } from 'gsap';
import { ScrollTrigger } from 'gsap/ScrollTrigger';
gsap.registerPlugin(ScrollTrigger);
export const other27 = () => {
const other = new Other27('js-other-27');
other.init();
};
class Other27 {
el: HTMLElement;
imgEl: HTMLElement;
constructor(id: string) {
this.el = document.getElementById(id);
if (!this.el) return;
this.imgEl = this.el.querySelector('.other-27__img');
}
/**
* 初期化
*/
init(): void {
if (!this.el) return;
this.scrollHandler();
}
/**
* スクロール連動のイベント設定
*/
scrollHandler(): void {
gsap.fromTo(
this.imgEl,
{
rotation: -20,
},
{
rotation: 20,
scrollTrigger: {
trigger: this.imgEl,
start: 'top 70%',
end: 'bottom top',
scrub: 0.3,
},
}
);
}
}