Слайдер изображений с разделителем диагональных линий

Я создал контейнер-слайдер из 5 изображений, в котором просматривается каждое следующее и предыдущее изображения. Единственная проблема, с которой я столкнулся, заключается в том, что мне нужно сделать так, чтобы изображения разделялись диагональными линиями, а не горизонтальными.

Это мой код:

const images = document.querySelectorAll(".slider-img")

function clearActiveImage() {
  images.forEach(function(image) {
    image.classList.remove("active-slider");
  });
}

images.forEach(function(image, index) {
  image.onclick = function() {
    event.stopPropagation()
    if (images[index].classList.contains("active-slider")) {
      images[index].classList.remove("active-slider")
    } else {
      clearActiveImage(index)
      images[index].classList.add("active-slider")
    }
  }
})

window.addEventListener("click", () => {
  clearActiveImage()
})
.slider-container {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 150px;
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slider-main {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  aspect-ratio: 1.5 / 1;
  display: flex;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

.slider-main:has(.img.active) .img:not(.active) {
  filter: grayscale(100%)
}

.slider-img {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 100%;
  width: calc(100% / 5);
  object-fit: cover;
  overflow: hidden;
  border: none;
  transition: all 0.4s cubic-bezier(0.32, 0, 0.67, 0);
  cursor: pointer;
}

.active-slider {
  width: 200%;
}
<div class = "slider-container">
  <div class = "slider-main">
    <img class = "slider-img active-slider" src = "https://image.shutterstock.com/image-photo/mountains-fog-beautiful-night-autumn-260nw-1233564241.jpg" alt = "">
    <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/sunset-ruby-beach-260nw-35902396.jpg" alt = "">
    <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/streelights-uttakleiv-village-shine-below-260nw-2333054447.jpg" alt = "">
    <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/twilight-light-over-isolated-sandwood-260nw-2333055437.jpg" alt = "">
    <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/silhouette-young-traveler-watched-star-260nw-1730791102.jpg" alt = "">
  </div>
</div>

Я уже пробовал использовать «transform: skewX(-20deg)», но тогда все мои изображения искажаются. Прикрепляю изображение того, как это должно выглядеть.

🤔 А знаете ли вы, что...
JavaScript активно развивается, и новые версии языка регулярно включают новые функции и улучшения.


3
119
3

Ответы:

Редактировать:

Я нашел лучшее решение, используя пути обрезки.

Вы можете определить многоугольник clip-path после упаковки каждого изображения в контейнер. Функция polygon устанавливает вершины многоугольника, позволяя вам настроить форму, которая по сути «вырезана» из элемента div.

const images = document.querySelectorAll(".slider-img")

function clearActiveImage() {
  images.forEach(function(image) {
    image.classList.remove("active-slider");
  });
}

images.forEach(function(image, index) {
  image.onclick = function() {
    event.stopPropagation()
    if (images[index].classList.contains("active-slider")) {
      images[index].classList.remove("active-slider")
    } else {
      clearActiveImage(index)
      images[index].classList.add("active-slider")
    }
  }
})

window.addEventListener("click", () => {
  clearActiveImage()
})
    .slider-container {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 150px;
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slider-main {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  aspect-ratio: 1.5 / 1;
  display: flex;
  overflow: hidden;
  width: 120%;
  height: 100%;
}

.slider-main:has(.img.active) .img:not(.active) {
  filter: grayscale(100%)
}

.slider-img-container {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 100%;
  width: calc(100% / 5);
  object-fit: cover;
  border: none;
  transition: all 0.4s cubic-bezier(0.32, 0, 0.67, 0);
  cursor: pointer;
  clip-path: polygon(100% 0%, 0% 100%, 200% 100%, 200% 0%);
}

.slider-img-container:first-child {
  clip-path: polygon(0% 0%, 0% 100%, 200% 100%, 200% 0%);
}

.active-slider {
  width: 200%;
}

.slider-img {
  transform: translateX(-50%);
  
}
   

 <div class = "slider-container">
     <div class = "slider-main">
         <div class = "slider-img-container">
            <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/mountains-fog-beautiful-night-autumn-260nw-1233564241.jpg" alt = "">
         </div>
        <div class = "slider-img-container">
          <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/sunset-ruby-beach-260nw-35902396.jpg" alt = "">
        </div>
        <div class = "slider-img-container">
          <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/streelights-uttakleiv-village-shine-below-260nw-2333054447.jpg" alt = "">
        </div>  
        <div class = "slider-img-container">
           <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/twilight-light-over-isolated-sandwood-260nw-2333055437.jpg" alt = "">       
        </div>
        <div class = "slider-img-container">
          <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/silhouette-young-traveler-watched-star-260nw-1730791102.jpg" alt = "">
         </div>
      </div>
    </div>
    

Оригинальный ответ:

Вы можете попробовать что-то в этом роде: обернуть каждое изображение элементом div, повернуть контейнер и повернуть изображение в противоположном направлении. Мой пример не идеален, но вы можете поиграть с ним, чтобы получить желаемый эффект.

const images = document.querySelectorAll(".slider-img")

function clearActiveImage() {
  images.forEach(function(image) {
    image.classList.remove("active-slider");
  });
}

images.forEach(function(image, index) {
  image.onclick = function() {
    event.stopPropagation()
    if (images[index].classList.contains("active-slider")) {
      images[index].classList.remove("active-slider")
    } else {
      clearActiveImage(index)
      images[index].classList.add("active-slider")
    }
  }
})

window.addEventListener("click", () => {
  clearActiveImage()
})
    .slider-container {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 150px;
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slider-main {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  aspect-ratio: 1.5 / 1;
  display: flex;
  overflow: hidden;
  width: 120%;
  height: 100%;
}

.slider-main:has(.img.active) .img:not(.active) {
  filter: grayscale(100%)
}

.slider-img-container {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 120%;
  width: calc(150% / 5);
  object-fit: cover;
  overflow: hidden;
  border: none;
  transition: all 0.4s cubic-bezier(0.32, 0, 0.67, 0);
  cursor: pointer;
  transform: rotate(12deg) translateY(-10%);
}

.active-slider {
  width: 200%;
}

.slider-img {
  transform: rotate(-12deg) translate(-50%, -10%);
  transform-origin: top left;
  
}
   

 <div class = "slider-container">
     <div class = "slider-main">
         <div class = "slider-img-container">
            <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/mountains-fog-beautiful-night-autumn-260nw-1233564241.jpg" alt = "">
         </div>
        <div class = "slider-img-container">
          <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/sunset-ruby-beach-260nw-35902396.jpg" alt = "">
        </div>
        <div class = "slider-img-container">
          <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/streelights-uttakleiv-village-shine-below-260nw-2333054447.jpg" alt = "">
        </div>  
        <div class = "slider-img-container">
           <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/twilight-light-over-isolated-sandwood-260nw-2333055437.jpg" alt = "">       
        </div>
        <div class = "slider-img-container">
          <img class = "slider-img" src = "https://image.shutterstock.com/image-photo/silhouette-young-traveler-watched-star-260nw-1730791102.jpg" alt = "">
         </div>
      </div>
    </div>
    

Я надеюсь, что это хорошо соответствует вашим требованиям, но здесь у меня возникла проблема, например внешнее пространство.

.slider-img:not(.active-slider) {
    transform: skew(-14deg);
}

Решено

Это вариант использования clip-path.

Но для этого может потребоваться использовать медиа-запрос, чтобы установить для переменной css --ms в .slider-img другое значение, соответствующее разным размерам экрана.

const images = document.querySelectorAll(".slider-img");
const clearActiveImage = ({ target }) => images.forEach((image) => image !== target && image.classList.remove("active-slider"));
images.forEach((image) => image.addEventListener("click", ({ currentTarget }) => currentTarget.classList.toggle("active-slider")));
window.addEventListener("click", clearActiveImage);
.slider-container {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 150px;
  width: 50%;
  display: flex;
  justify-content: center;
  align-items: center;
}

.slider-main {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  aspect-ratio: 1.5 / 1;
  display: flex;
  overflow: hidden;
  width: 100%;
  height: 100%;
}

.slider-main:has(.img.active) .img:not(.active) {
  filter: grayscale(100%);
}

.slider-main:has(.active-slider) .slider-img {
  width: calc(100% / 5);
}

.slider-img {
  --ms: 40px;
  position: relative;
  z-index: var(--i);
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  height: 100%;
  width: calc(100% / 5 + var(--ms));
  flex-shrink: 0;
  object-fit: cover;
  overflow: hidden;
  border: none;
  transition: all 0.4s cubic-bezier(0.32, 0, 0.67, 0);
  cursor: pointer;
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--ms)) 100%, 0 100%);
}

.slider-img:not(:first-child) {
  margin-left: calc(var(--ms) * -1);
}

.slider-img:last-child {
  clip-path: polygon(0 0, 100% 0, 100% 100%, 0 100%);
}

.slider-img.active-slider {
  width: calc(100% / 5 + var(--ms) * 4) !important;
}
<div class = "slider-container">
  <div class = "slider-main">
    <img style = "--i: 4" class = "slider-img active-slider" src = "https://image.shutterstock.com/image-photo/mountains-fog-beautiful-night-autumn-260nw-1233564241.jpg" alt = "">
    <img style = "--i: 3" class = "slider-img" src = "https://image.shutterstock.com/image-photo/sunset-ruby-beach-260nw-35902396.jpg" alt = "">
    <img style = "--i: 2" class = "slider-img" src = "https://image.shutterstock.com/image-photo/streelights-uttakleiv-village-shine-below-260nw-2333054447.jpg" alt = "">
    <img style = "--i: 1" class = "slider-img" src = "https://image.shutterstock.com/image-photo/twilight-light-over-isolated-sandwood-260nw-2333055437.jpg" alt = "">
    <img style = "--i: 0" class = "slider-img" src = "https://image.shutterstock.com/image-photo/silhouette-young-traveler-watched-star-260nw-1730791102.jpg" alt = "">
  </div>
</div>