삼각함수 - 이미지 슬라이드
by jinam yu
HTML
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/vue.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<div id="app">
<div class="viewport">
<ul class="slide">
<li
v-for="i in len"
:style="getPosition(i)"
:class="{
active: isActive(i),
}"
:data-id="i"
>
<button type="button">
<img :src="'https://placeimg.com/480/640/' + i" alt="" />
</button>
</li>
</ul>
<div class="control">
<button type="button" @click="prev">
<i class="fa-solid fa-chevron-left"></i>
</button>
<button type="button" @click="next">
<i class="fa-solid fa-chevron-right"></i>
</button>
</div>
</div>
</div>
SCSS
html,
body,
#app {
width: 100%;
height: 100%;
position: relative;
}
#app {
background-color: #363636;
}
.viewport {
width: 100%;
height: 100%;
position: relative;
overflow: hidden;
}
.slide {
position: absolute;
left: 0;
top: 0;
list-style: none;
padding: 0;
margin: 0;
width: 100%;
height: 100%;
transition: transform 0.75s cubic-bezier(0.165, 0.84, 0.44, 1);
li {
width: 24%;
font-size: 0;
left: 0;
top: 50%;
position: absolute;
will-change: left;
transition: left 0.2s ease-out;
transform: translate(-50%, -50%);
& > button {
width: 100%;
height: 100%;
position: relative;
padding-bottom: 130%;
background-color: #999;
border: 0;
border-radius: 8px;
overflow: hidden;
cursor: pointer;
box-shadow: 0 4px 16px 1px rgba(#000, 0.5);
transition: transform 0.5s cubic-bezier(0.165, 0.84, 0.44, 1);
img {
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 100%;
object-fit: cover;
}
&:hover {
transform: scale(1.15);
}
}
}
li.active {
button {
transform: scale(1.15);
}
}
}
.control {
position: absolute;
left: 50%;
bottom: 24px;
transform: translate(-50%, -50%);
button {
text-transform: uppercase;
line-height: 1;
border: 0;
background-color: transparent;
font-size: 22px;
font-weight: 700;
margin-left: 8px;
margin-right: 8px;
cursor: pointer;
color: white;
}
}
JavaScript
const cnt = 10;
const len = cnt * 2;
new Vue({
el:'#app',
data: {
len,
radius: 0,
rotate:0,
current:1,
},
methods: {
next() {
this.move(this.current + 1);
},
prev() {
this.move(this.current - 1);
},
move(i){
this.rotate = ((i - 1) / len) * 360;
this.current = i;
},
getStyles(){
const y = window.innerWidth - window.innerWidth / 4;
return { top: `${y}px`, transform: `rotate(${this.rotate}deg)` };
},
getPosition(i){
const index = i - 1;
const step = ((2 * Math.PI) / len) * (i - this.current);
const cos = Math.cos(step - Math.PI / 2) * this.radius;
const sin = Math.sin(step - Math.PI / 2) * this.radius;
const x = cos;
const y = sin;
return {
left: `calc( 50% + ${x}px)`,
zIndex: Math.floor(-y),
};
},
isActive(i){
let x = this.current % len;
if (x === 0) x = len;
if (x < 0) x = len + x;
return x === i;
},
resize() {
this.radius = window.innerWidth - window.innerWidth / 4;
},
},
mounted(){
window.addEventListener("resize", this.resize);
this.resize();
}
})