I wonder how to scale the current index from 1 to 0.8 when swiping to the next item. I've been building a carousel on how to make the centered item from 1 to 0.8 when the user swipes to the previous item or next item
When the user swipes into the next item the current item should slowly become from a 1 to 0.8 scaleY when it's not on the center
Only one item should have a 1 scaleY and centered item should scaleY from 1 to 0.8 every touchmove not only on touchend event
const MAIN_CONTAINER = document.querySelector('.main-container');
const CONTAINER_FLEX = document.getElementById('container-flex');
if (window.screen.width < 800) {
MAIN_CONTAINER.style.width = `${window.screen.width}px`;
}
// Get the position when clicking the element
let touchstartX = 0;
let touchstartY = 0;
// Get the position when moving the element
let touchMoveX = 0;
let touchMoveY = 0;
let previous_move = 0;
// Get the position when leaving the element
let touchendX = 0;
let touchendY = 0;
// Swipe Detection
// Default is 1
let speed_of_swipe = 0.5;
let previous_translate_item = -305;
let current_translate = -305;
let current_index = 1;
CONTAINER_FLEX.style.transform = `translate3d(-305px, 0, 0)`;
CONTAINER_FLEX.addEventListener('touchstart', (event) => {
touchstartX = event.touches[0].pageX;
touchstartY = event.touches[0].pageY;
previous_move = touchstartX;
});
CONTAINER_FLEX.addEventListener('touchmove', (event) => {
touchMoveX = event.touches[0].pageX;
touchMoveY = event.touches[0].pageY;
current_translate =
previous_translate_item (touchMoveX - touchstartX) * speed_of_swipe;
// if (current_index === 0 && current_translate > 20) current_translate = 20;
// if (current_index === 2 && current_translate < -620) current_translate = -620;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
});
CONTAINER_FLEX.addEventListener('touchend', (event) => {
touchendX = event.changedTouches[0].pageX;
touchendY = event.changedTouches[0].pageY;
let val_converter = (val) =>
-Math.sign(val) * Math.floor((Math.abs(val) - 40) / 300 1);
let move = current_translate - previous_translate_item;
current_index = val_converter(move);
// if (move < -345) current_index = 1;
// if (move < -40) current_index = 1;
// if (move > 40) current_index -= 1;
// if (move > 345) current_index -= 1;
// including the margin
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
if (current_index > 3) {
CONTAINER_FLEX.style.pointerEvents = 'none';
current_index = 1;
setTimeout(() => {
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.pointerEvents = 'auto';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
}, 400);
}
if (current_index <= 0) {
CONTAINER_FLEX.style.pointerEvents = 'none';
current_index = 3;
setTimeout(() => {
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.pointerEvents = 'auto';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
}, 400);
}
console.log(current_index);
});
//
window.addEventListener('resize', (event) => {
if (window.screen.width < 800) {
MAIN_CONTAINER.style.width = `${window.screen.width}px`;
}
});
*,
::before,
::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.5;
background-color: #131b24;
}
.main-container {
padding: 30px 0;
height: 300px;
width: 910px;
border-top: 1px solid #444;
border-bottom: 1px solid #444;
overflow: hidden;
background-color: white;
}
.container-flex {
height: 100%;
display: flex;
column-gap: 5px;
transition: transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1);
}
.item {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-width: 300px;
transform: scaleY(0.8);
}
.item h1 {
font-size: 40px;
color: white;
}
/* ITEMS */
.item-1 {
background-color: #2c3e50;
}
.item-2 {
background-color: #3498db;
}
.item-3 {
background-color: #1abc9c;
}
<div >
<div id="container-flex">
<div >
<h1>2</h1>
</div>
<div >
<h1>3</h1>
</div>
<div >
<h1>1</h1>
</div>
<div >
<h1>2</h1>
</div>
<div >
<h1>3</h1>
</div>
<div >
<h1>1</h1>
</div>
<div >
<h1>2</h1>
</div>
</div>
</div>
CodePudding user response:
i add a scaleUp
function to your js that called on CIRCLE_ITEMS.onclick
and CONTAINER_FLEX.ontouchend
. and by calling it , a scale-up
class is added to the items.
function scaleUp (current_index){
document.querySelectorAll('.item').forEach(item => {
item.classList.remove('scale-up')
})
document.querySelectorAll(`.item-${current_index}`).forEach(item => {
item.classList.add('scale-up')
})
}
.scale-up{
transform: scale(1)
}
and you can improve the code ... :)
const MAIN_CONTAINER = document.querySelector('.main-container');
const CONTAINER_FLEX = document.getElementById('container-flex');
const CIRCLE_ITEMS = document.querySelectorAll('.circle-holder span');
if (window.screen.width < 800) {
MAIN_CONTAINER.style.width = `${window.screen.width}px`;
}
// Get the position when clicking the element
let touchstartX = 0;
let touchstartY = 0;
// Get the position when moving the element
let touchMoveX = 0;
let touchMoveY = 0;
let previous_move = 0;
// Get the position when leaving the element
let touchendX = 0;
let touchendY = 0;
// Swipe Detection
// Default is 1
let speed_of_swipe = 0.5;
let previous_translate_item = -305;
let current_translate = -305;
let current_index = 1;
CONTAINER_FLEX.style.transform = `translate3d(-305px, 0, 0)`;
CONTAINER_FLEX.addEventListener('touchstart', (event) => {
touchstartX = event.touches[0].pageX;
touchstartY = event.touches[0].pageY;
previous_move = touchstartX;
});
CONTAINER_FLEX.addEventListener('touchmove', (event) => {
touchMoveX = event.touches[0].pageX;
touchMoveY = event.touches[0].pageY;
current_translate =
previous_translate_item (touchMoveX - touchstartX) * speed_of_swipe;
// if (current_index === 0 && current_translate > 20) current_translate = 20;
// if (current_index === 2 && current_translate < -620) current_translate = -620;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
});
CONTAINER_FLEX.addEventListener('touchend', (event) => {
touchendX = event.changedTouches[0].pageX;
touchendY = event.changedTouches[0].pageY;
let val_converter = (val) =>
-Math.sign(val) * Math.floor((Math.abs(val) - 40) / 300 1);
let move = current_translate - previous_translate_item;
current_index = val_converter(move);
// if (move < -345) current_index = 1;
// if (move < -40) current_index = 1;
// if (move > 40) current_index -= 1;
// if (move > 345) current_index -= 1;
// including the margin
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
if (current_index > CIRCLE_ITEMS.length) {
CONTAINER_FLEX.style.pointerEvents = 'none';
current_index = 1;
setTimeout(() => {
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.pointerEvents = 'auto';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
}, 400);
}
if (current_index <= 0) {
CONTAINER_FLEX.style.pointerEvents = 'none';
current_index = CIRCLE_ITEMS.length;
setTimeout(() => {
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.pointerEvents = 'auto';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
}, 400);
}
//console.log(current_index);
onRemoveCarouselActiveItem();
CIRCLE_ITEMS[current_index - 1].classList.add('active');
scaleUp (current_index)
});
//
CIRCLE_ITEMS.forEach((item) => {
item.addEventListener('click', (e) => {
let data_item = e.target.dataset.carouselCount * 1;
current_index = data_item;
current_translate = current_index * -305;
previous_translate_item = current_translate;
onRemoveCarouselActiveItem();
e.target.classList.add('active');
scaleUp (current_index)
CONTAINER_FLEX.style.transition =
'transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
});
});
function onRemoveCarouselActiveItem() {
let active_item = document.querySelector('.circle-holder .active');
if (active_item)active_item.classList.remove('active')
}
window.addEventListener('resize', (event) => {
if (window.screen.width < 800) {
MAIN_CONTAINER.style.width = `${window.screen.width}px`;
}
});
function scaleUp (current_index){
document.querySelectorAll('.item').forEach(item => {
item.classList.remove('scale-up')
})
document.querySelectorAll(`.item-${current_index}`).forEach(item => {
item.classList.add('scale-up')
})
}
*,
::before,
::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
body {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.5;
background-color: #131b24;
}
.main-container {
padding: 30px 0;
height: 300px;
width: 910px;
border-top: 1px solid #444;
border-bottom: 1px solid #444;
overflow: hidden;
background-color: white;
}
.container-flex {
height: 100%;
display: flex;
column-gap: 5px;
transition: transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1);
}
.item {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-width: 300px;
transform: scaleY(0.8);
transition: ease .3s transform;
}
.item h1 {
font-size: 40px;
color: white;
}
/* ITEMS */
.item-1 {
background-color: #2c3e50;
}
.item-2 {
background-color: #3498db;
}
.item-3 {
background-color: #1abc9c;
}
/* ============================================================== */
.circle-holder {
display: flex;
align-items: center;
margin-top: 30px;
}
.circle-holder span {
height: 30px;
width: 30px;
border: 1px solid #444;
border-radius: 100%;
margin: 0 20px;
}
.circle-holder span.active {
background-color: #2c3e50;
}
.scale-up{
transform: scale(1)
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div >
<div id="container-flex">
<div >
<h1>2</h1>
</div>
<div >
<h1>3</h1>
</div>
<div >
<h1>1</h1>
</div>
<div >
<h1>2</h1>
</div>
<div >
<h1>3</h1>
</div>
<div >
<h1>1</h1>
</div>
<div >
<h1>2</h1>
</div>
</div>
</div>
<div >
<span data-carousel-count="1"></span>
<span data-carousel-count="2"></span>
<span data-carousel-count="3"></span>
</div>
<script src="index.js"></script>
</body>
</html>
CodePudding user response:
Is that what you need ? Test it on screen because of px calculations, SO snippet is not behave correct.
const MAIN_CONTAINER = document.querySelector('.main-container');
const CONTAINER_FLEX = document.getElementById('container-flex');
const CIRCLE_ITEMS = document.querySelectorAll('.circle-holder span');
if (window.screen.width < 800) {
MAIN_CONTAINER.style.width = `${window.screen.width}px`;
}
// Get the position when clicking the element
let touchstartX = 0;
let touchstartY = 0;
// Get the position when moving the element
let touchMoveX = 0;
let touchMoveY = 0;
let previous_move = 0;
// Get the position when leaving the element
let touchendX = 0;
let touchendY = 0;
// Swipe Detection
// Default is 1
let speed_of_swipe = 0.5;
let previous_translate_item = -305;
let current_translate = -305;
let current_index = 1;
let old_index = 1;
CONTAINER_FLEX.style.transform = `translate3d(-305px, 0, 0)`;
CONTAINER_FLEX.addEventListener('transitionstart', () =>{
FindAndChangeMiddleItem(1,2);
},{once: true})
CONTAINER_FLEX.addEventListener('touchstart', (event) => {
touchstartX = event.touches[0].pageX;
touchstartY = event.touches[0].pageY;
previous_move = touchstartX;
});
CONTAINER_FLEX.addEventListener('touchmove', (event) => {
touchMoveX = event.touches[0].pageX;
touchMoveY = event.touches[0].pageY;
current_translate =
previous_translate_item (touchMoveX - touchstartX) * speed_of_swipe;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
});
CONTAINER_FLEX.addEventListener('touchend', (event) => {
touchendX = event.changedTouches[0].pageX;
touchendY = event.changedTouches[0].pageY;
let val_converter = (val) =>
-Math.sign(val) * Math.floor((Math.abs(val) - 40) / 300 1);
let move = current_translate - previous_translate_item;
current_index = val_converter(move);
// if (move < -345) current_index = 1;
// if (move < -40) current_index = 1;
// if (move > 40) current_index -= 1;
// if (move > 345) current_index -= 1;
// including the margin
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
if (current_index > CIRCLE_ITEMS.length) {
CONTAINER_FLEX.style.pointerEvents = 'none';
current_index = 1;
setTimeout(() => {
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.pointerEvents = 'auto';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
}, 400);
}
if (current_index <= 0) {
CONTAINER_FLEX.style.pointerEvents = 'none';
current_index = CIRCLE_ITEMS.length;
setTimeout(() => {
current_translate = current_index * -305;
previous_translate_item = current_translate;
CONTAINER_FLEX.style.transition =
'transform 0ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.pointerEvents = 'auto';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
}, 400);
}
onRemoveCarouselActiveItem();
CIRCLE_ITEMS[current_index - 1].classList.add('active');
});
CIRCLE_ITEMS.forEach((item) => {
item.addEventListener('click', (e) => {
let data_item = e.target.dataset.carouselCount * 1;
current_index = data_item;
current_translate = current_index * -305;
previous_translate_item = current_translate;
onRemoveCarouselActiveItem();
e.target.classList.add('active');
CONTAINER_FLEX.style.transition =
'transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1)';
CONTAINER_FLEX.style.transform = `translate3d(${current_translate}px, 0, 0)`;
FindAndChangeMiddleItem(old_index, current_index);
old_index = current_index;
});
});
const items = document.querySelectorAll('.item');
let middleItemBeforeChange;
let middleItemAfterChange;
let change_index;
function FindAndChangeMiddleItem(old_index, current_index){
let itemArray = document.elementsFromPoint(window.innerWidth / 2, window.innerHeight / 2);
change_index = current_index - old_index;
for (let i = 0; i < itemArray.length; i ){
if (itemArray[i].classList.contains('item')){
middleItemBeforeChange = itemArray[i];
}
}
for (let i = 0; i < items.length; i ){
if (items[i] === middleItemBeforeChange){
if (change_index < 0 && i change_index < 0){
return;
}
else if (change_index > 0 && i change_index > items.length){
return;
}
else{
middleItemAfterChange = items[i change_index];
}
}
}
items.forEach((item) => {
if (item != middleItemAfterChange){
if(item.classList.contains('item-big')){
item.classList.remove('item-big');
}
item.classList.add('item-small');
}
else{
if(item.classList.contains('item-small')){
item.classList.remove('item-small');
}
item.classList.add('item-big');
}
})
}
function onRemoveCarouselActiveItem() {
let active_item = document.querySelector('.circle-holder .active');
if (active_item) active_item.classList.remove('active');
}
window.addEventListener('resize', (event) => {
if (window.screen.width < 800) {
MAIN_CONTAINER.style.width = `${window.screen.width}px`;
}
});
/* Remove default margin */
body,
h1,
h2,
h3,
h4,
p,
figure,
blockquote,
dl,
dd {
margin: 0;
}
input,
button,
textarea,
select {
font: inherit;
}
*,
*::before,
*::after {
box-sizing: border-box;
}
/* body {
min-height: 100vh;
margin: 0;
background-color: bisque;
display: grid;
place-content: center;
} */
body {
overflow: hidden;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
font-family: Arial, Helvetica, sans-serif;
line-height: 1.5;
background-color: #131b24;
}
.main-container {
padding: 30px 0;
height: 300px;
width: 910px;
border-top: 1px solid #444;
border-bottom: 1px solid #444;
overflow: hidden;
background-color: white;
}
.container-flex {
height: 100%;
display: flex;
column-gap: 5px;
transition: transform 400ms cubic-bezier(0.165, 0.84, 0.44, 1);
}
.item {
height: 100%;
display: flex;
justify-content: center;
align-items: center;
min-width: 300px;
max-width: 300px;
transition: 400ms all ease;
}
.item h1 {
font-size: 40px;
color: white;
}
/* ITEMS */
.item-1 {
background-color: #2c3e50;
}
.item-2 {
background-color: #3498db;
}
.item-3 {
background-color: #1abc9c;
}
.circle-holder {
display: flex;
align-items: center;
margin-top: 30px;
}
.circle-holder span {
height: 30px;
width: 30px;
border: 1px solid #444;
border-radius: 100%;
margin: 0 20px;
}
.circle-holder span.active {
background-color: #2c3e50;
}
.item-small{
transform: scaleY(0.8);
}
.item-big{
transform: scaleY(1);
}
<div >
<div id="container-flex">
<div >
<h1>2</h1>
</div>
<div >
<h1>3</h1>
</div>
<div >
<h1>1</h1>
</div>
<div >
<h1>2</h1>
</div>
<div >
<h1>3</h1>
</div>
<div >
<h1>1</h1>
</div>
<div >
<h1>2</h1>
</div>
</div>
</div>
<div >
<span data-carousel-count="1"></span>
<span data-carousel-count="2"></span>
<span data-carousel-count="3"></span>
</div>