如何找出具有类似 类 划掉固定块(getBoundingClientRect)的块?
How to figure out what block with similar classes cross out fixed block (getBoundingClientRect)?
我有这个问题。我有 div 个不同颜色的方块轮播。让我们将它们命名为一、二和三。在它们之上有一个名为“INFO”的固定块。因此,它位于两个街区之间。如果块 ONE 在超过 80% 时跨越信息块,我想在控制台“1”中写入。我不知道如何找出 INFO 下的特定块。
P.S: 现在我在控制台写 'hello' 如果轮播的块跨越信息块,但我需要写轮播块的 ID。
HTML:
<body>
<div class="container">
<div class="carousel">
<!-- Carousel -->
<div class="carousel-content">
<div class="slide slide-1">
<div>1</div>
</div>
<div class="slide slide-2">
<div>2</div>
</div>
<div class="slide slide-3">
<div>3</div>
</div>
</div>
<!-- Fixed Block-->
<div class="infoblock">
<div>INFO</div>
</div>
<!-- Scroll Buttons -->
<div class="nav nav-left">
<div class="ion-chevron-left carousel-arrow-icon-left"></div>
</div>
<div class="nav nav-right">
<div class="ion-chevron-right carousel-arrow-icon-right"></div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
CSS:
*,
*:before,
*:after {
box-sizing: border-box;
}
.carousel {
position: relative;
width: 50%;
height: 50px;
margin: 0 auto;
}
.carousel-content {
position: relative;
overflow: hidden;
transition: width .4s;
height: 100%;
}
.slide {
height: 100%;
position: absolute;
z-index: 1;
transition: left .4s cubic-bezier(.47,.13,.15,.89);
}
.slide-1{
background-color:cyan;
}
.slide-2 {
background-color: green;
}
.slide-3 {
background-color: red;
}
.nav {
position: absolute;
top: 50%;
margin-top: -10px;
background-color: rgba(150,150,150,.3);
width: 20px;
height: 20px;
z-index: 2;
cursor: pointer;
border-radius: 50%;
border: none;
outline: none;
color: white;
}
.nav-left {
left: -25px;
}
.nav-right {
right: -25px;
}
.infoblock{
position: absolute;
background-color:darkorange;
z-index: 2;
margin-top: -5vh;
margin-left: 10vw;
height: 100%;
width: 20%;
opacity: 0.6;
text-align: center;
border: 1px solid black;
}
JavaScript:
var carousel = document.querySelector('.carousel');
var carouselContent = document.querySelector('.carousel-content');
var slides = document.querySelectorAll('.slide');
var arrayOfSlides = Array.prototype.slice.call(slides);
var carouselDisplaying;
var screenSize;
setScreenSize();
var lengthOfSlide;
function addClone() {
var lastSlide = carouselContent.lastElementChild.cloneNode(true);
lastSlide.style.left = (-lengthOfSlide) + "px";
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
}
function removeClone() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
}
function moveSlidesRight() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
var width = 0;
slidesArray.forEach(function (el, i) {
el.style.left = width + "px";
width += lengthOfSlide;
});
addClone();
}
moveSlidesRight();
function moveSlidesLeft() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray = slidesArray.reverse();
var maxWidth = (slidesArray.length - 1) * lengthOfSlide;
slidesArray.forEach(function (el, i) {
maxWidth -= lengthOfSlide;
el.style.left = maxWidth + "px";
});
}
window.addEventListener('resize', setScreenSize);
function setScreenSize() {
if (window.innerWidth >= 500) {
carouselDisplaying = 3;
} else if (window.innerWidth >= 300) {
carouselDisplaying = 2;
} else {
carouselDisplaying = 1;
}
getScreenSize();
}
function getScreenSize() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
lengthOfSlide = (carousel.offsetWidth / carouselDisplaying);
var initialWidth = -lengthOfSlide;
slidesArray.forEach(function (el) {
el.style.width = lengthOfSlide + "px";
el.style.left = initialWidth + "px";
initialWidth += lengthOfSlide;
});
}
var rightNav = document.querySelector('.nav-right');
rightNav.addEventListener('click', moveLeft);
var moving = true;
function moveRight() {
if (moving) {
moving = false;
var lastSlide = carouselContent.lastElementChild;
lastSlide.parentNode.removeChild(lastSlide);
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', activateAgain);
moveSlidesRight();
}
}
function activateAgain() {
var firstSlide = carouselContent.firstElementChild;
moving = true;
firstSlide.removeEventListener('transitionend', activateAgain);
}
var leftNav = document.querySelector('.nav-left');
leftNav.addEventListener('click', moveRight);
function moveLeft() {
if (moving) {
moving = false;
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', replaceToEnd);
moveSlidesLeft();
}
}
function replaceToEnd() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
carouselContent.appendChild(firstSlide);
firstSlide.style.left = ((arrayOfSlides.length - 1) * lengthOfSlide) + "px";
addClone();
moving = true;
firstSlide.removeEventListener('transitionend', replaceToEnd);
}
carouselContent.addEventListener('mousedown', seeMovement);
var initialX;
var initialPos;
function seeMovement(e) {
initialX = e.clientX;
getInitialPos();
carouselContent.addEventListener('mousemove', slightMove);
document.addEventListener('mouseup', moveBasedOnMouse);
}
function slightMove(e) {
if (moving) {
var movingX = e.clientX;
var difference = initialX - movingX;
if (Math.abs(difference) < (lengthOfSlide / 4)) {
slightMoveSlides(difference);
}
}
}
function getInitialPos() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
initialPos = [];
slidesArray.forEach(function (el) {
var left = Math.floor(parseInt(el.style.left.slice(0, -2)));
initialPos.push(left);
});
}
function slightMoveSlides(newX) {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray.forEach(function (el, i) {
var oldLeft = initialPos[i];
el.style.left = (oldLeft + newX) + "px";
});
}
function moveBasedOnMouse(e) {
var finalX = e.clientX;
if (initialX - finalX > 0) {
moveRight();
} else if (initialX - finalX < 0) {
moveLeft();
}
document.removeEventListener('mouseup', moveBasedOnMouse);
carouselContent.removeEventListener('mousemove', slightMove);
}
/* Blocks Overlapping*/
const boxes = document.querySelectorAll(".slide");
function checkOverlap(ele1, ele2) {
const boundings1 = ele1.getBoundingClientRect();
const boundings2 = ele2.getBoundingClientRect();
const top1 = parseInt(boundings1.top);
const height1 = parseInt(boundings1.height);
const top2 = parseInt(boundings2.top);
const overlap = 1 - (top2 - top1) / height1;
if (overlap >= 0.8) {
ele2.classList.add("overlap-80");
console.log('hello');
}
}
checkOverlap(boxes[0], boxes[1]);
checkOverlap(boxes[2], boxes[3]);
checkOverlap(boxes[4], boxes[5]);
如果 INFO
盒子总是比幻灯片小,你可以在四个角上使用 document.elementsFromPoint()
来获取这些点的幻灯片列表:
var carousel = document.querySelector('.carousel');
var carouselContent = document.querySelector('.carousel-content');
var slides = document.querySelectorAll('.slide');
var arrayOfSlides = Array.prototype.slice.call(slides);
var carouselDisplaying;
var screenSize;
setScreenSize();
var lengthOfSlide;
function addClone() {
var lastSlide = carouselContent.lastElementChild.cloneNode(true);
lastSlide.style.left = (-lengthOfSlide) + "px";
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
}
function removeClone() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
}
function moveSlidesRight() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
var width = 0;
slidesArray.forEach(function (el, i) {
el.style.left = width + "px";
width += lengthOfSlide;
});
addClone();
}
moveSlidesRight();
function moveSlidesLeft() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray = slidesArray.reverse();
var maxWidth = (slidesArray.length - 1) * lengthOfSlide;
slidesArray.forEach(function (el, i) {
maxWidth -= lengthOfSlide;
el.style.left = maxWidth + "px";
});
}
window.addEventListener('resize', setScreenSize);
function setScreenSize() {
if (window.innerWidth >= 500) {
carouselDisplaying = 3;
} else if (window.innerWidth >= 300) {
carouselDisplaying = 2;
} else {
carouselDisplaying = 1;
}
getScreenSize();
}
function getScreenSize() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
lengthOfSlide = (carousel.offsetWidth / carouselDisplaying);
var initialWidth = -lengthOfSlide;
slidesArray.forEach(function (el) {
el.style.width = lengthOfSlide + "px";
el.style.left = initialWidth + "px";
initialWidth += lengthOfSlide;
});
}
var rightNav = document.querySelector('.nav-right');
rightNav.addEventListener('click', moveLeft);
var moving = true;
function moveRight() {
if (moving) {
moving = false;
var lastSlide = carouselContent.lastElementChild;
lastSlide.parentNode.removeChild(lastSlide);
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', activateAgain);
moveSlidesRight();
}
}
function activateAgain() {
var firstSlide = carouselContent.firstElementChild.nextSibling; /*changed*/
moving = true;
firstSlide.removeEventListener('transitionend', activateAgain);
}
var leftNav = document.querySelector('.nav-left');
leftNav.addEventListener('click', moveRight);
function moveLeft() {
if (moving) {
moving = false;
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', replaceToEnd);
moveSlidesLeft();
}
}
function replaceToEnd() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
carouselContent.appendChild(firstSlide);
firstSlide.style.left = ((arrayOfSlides.length - 1) * lengthOfSlide) + "px";
addClone();
moving = true;
firstSlide.removeEventListener('transitionend', replaceToEnd);
}
carouselContent.addEventListener('mousedown', seeMovement);
var initialX;
var initialPos;
function seeMovement(e) {
initialX = e.clientX;
getInitialPos();
carouselContent.addEventListener('mousemove', slightMove);
document.addEventListener('mouseup', moveBasedOnMouse);
}
function slightMove(e) {
if (moving) {
var movingX = e.clientX;
var difference = initialX - movingX;
if (Math.abs(difference) < (lengthOfSlide / 4)) {
slightMoveSlides(difference);
}
}
}
function getInitialPos() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
initialPos = [];
slidesArray.forEach(function (el) {
var left = Math.floor(parseInt(el.style.left.slice(0, -2)));
initialPos.push(left);
});
}
function slightMoveSlides(newX) {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray.forEach(function (el, i) {
var oldLeft = initialPos[i];
el.style.left = (oldLeft + newX) + "px";
});
}
function moveBasedOnMouse(e) {
var finalX = e.clientX;
if (initialX - finalX > 0) {
moveRight();
} else if (initialX - finalX < 0) {
moveLeft();
}
document.removeEventListener('mouseup', moveBasedOnMouse);
carouselContent.removeEventListener('mousemove', slightMove);
}
/* Blocks Overlapping*/
/*changed*/
const infoBox = document.querySelector(".infoblock>div");
function checkOverlap() {
const info = infoBox.getBoundingClientRect();
let data = [],
slide = document.querySelector('.slide').getBoundingClientRect(),
list = [];
// check elements at each corner of info block and several points within
for(let x = 0, cache = {}; x < Math.round(info.width / (slide.width/3)); x++)
{
for(let y = 0; y < Math.round(info.height / (slide.height/3)); y++)
{
const X = Math.min(info.right-1, info.left + slide.width * x),
Y = Math.min(info.bottom-1, info.top + slide.height * y);
if (cache[X + "x" + Y])
continue;
list = list.concat(cache[X + "x" + Y] = document.elementsFromPoint(X, Y));
}
}
//leave only slides and remove any duplicates
list = list.filter((item, pos) => item.classList.contains("slide") && list.indexOf(item) === pos);
for(let i = 0; i < list.length; i++)
{
const slide = list[i];
const box = slide.getBoundingClientRect(),
width = Math.max(Math.min(box.right, info.right) - Math.max(box.left, info.left), 0),
height = Math.max(Math.min(box.bottom, info.bottom) - Math.max(box.top, info.top), 0),
overlapX = width / info.width,
overlapY = height / info.height,
overlapArea = (width * height) / (info.width * info.height);
data[data.length] = {slide: slide, area: overlapArea, x: overlapX, y: overlapY}
}
return data;
}
/* demo */
let infoRect = infoBox.getBoundingClientRect(),
theta = Math.random() * 10,
gamma = Math.random() * 1,
dragX = 0,
dragY = 0,
pause = true;
document.onmousedown = function(e)
{
if (e.target === infoBox.parentNode)
return infoBox.parentNode.classList.add("resize");
if (e.target != infoBox)
return;
dragX = e.x - infoBox.parentNode.offsetLeft;
dragY = e.y - infoBox.parentNode.offsetTop;
document.body.classList.add("drag");
}
document.onmouseup = function(e)
{
if (!document.body.classList.contains("drag") && !infoBox.parentNode.classList.contains("resize"))
return;
document.body.classList.remove("drag");
infoBox.parentNode.classList.remove("resize");
demoInfo(true);
}
document.onmousemove = function(e)
{
const isMove = document.body.classList.contains("drag");
if (!isMove && !infoBox.parentNode.classList.contains("resize"))
return;
if (isMove)
{
infoBox.parentNode.style.left = (e.x - dragX) + "px";
infoBox.parentNode.style.top = (e.y - dragY) + "px";
}
demoInfo();
}
//we can use parent container to listen for transition events
document.querySelector(".carousel-content").addEventListener("transitionend", demoInfo);
function isOverlapped(node, data)
{
for(let i = 0; i < data.length; i++)
{
if (data[i].slide === node)
return true;
}
return false;
}
function demoInfo(moved)
{
const r = infoBox.getBoundingClientRect();
document.documentElement.style.setProperty('--size', Math.min(r.height, Math.min(r.width, 100)) / 76 + 'em')
const data = checkOverlap();
data.sort((a,b) => b.area - a.area); //sorted by area
const slides = document.querySelectorAll(".slide");
for(let i = 0; i < slides.length; i++)
{
slides[i].classList.toggle("overlapMost", data.length && slides[i] === data[0].slide)
slides[i].classList.toggle("overlap", isOverlapped(slides[i], data))
}
if (data.length)
{
infoBox.textContent = "Slide " + data[0].slide.textContent.trim() + " overlap\nArea:" + Math.round(data[0].area * 100) + "%\nWidth:" + Math.round(data[0].x * 100) + "%\nHeight:" + Math.round(data[0].y * 100) + "%";
}
else
{
infoBox.textContent = "no overlap\n\ndrag me";
}
if (moved)
{
console.clear();
for(let i = 0; i < data.length; i++)
{
console.log("Slide " + data[i].slide.textContent.trim() + " ( " + Array.prototype.indexOf.call(data[i].slide.parentNode.children, data[i].slide) + " child) overlap area: " + Math.round(data[i].area * 100) + "%, X: " + Math.round(data[i].x *100) + "%, Y: " + Math.round(data[i].y *100) + "%");
}
}
}
demoInfo();
*,
*:before,
*:after {
box-sizing: border-box;
}
.carousel {
position: relative;
width: 50%;
height: 50px;
margin: 0 auto;
}
.carousel-content {
position: relative;
overflow: hidden;
transition: width .4s;
height: 100%;
}
.slide {
height: 100%;
position: absolute;
z-index: 1;
transition: left .4s cubic-bezier(.47,.13,.15,.89);
}
.slide > div
{
vertical-align: middle;
text-align: center;
}
.slide-1{
background-color:cyan;
}
.slide-2 {
background-color: green;
}
.slide-3 {
background-color: red;
}
.slide-4 {
background-color: lightblue;
}
.slide-5 {
background-color: lightpink;
}
.nav {
position: absolute;
top: 50%;
margin-top: -10px;
background-color: rgba(150,150,150,.3);
width: 20px;
height: 20px;
z-index: 2;
cursor: pointer;
border-radius: 50%;
border: none;
outline: none;
color: white;
}
.nav-left {
left: -25px;
}
.nav-right {
right: -25px;
}
.infoblock{
position: absolute;
background-color:darkorange;
z-index: 2;
/* margin-top: -5vh;
margin-left: 10vw;*/
height: 100%;
width: 25%;
opacity: 0.6;
text-align: center;
border: 1px solid black;
font-size: 0.7em;
font-size: var(--size);
white-space: pre;
min-width: 20%;
min-height: 80%;
cursor: move;
top: 5vh;
left: 10vw;
text-shadow: 0 0 1px gray;
resize: both;
overflow: hidden;
display: flex;
}
.infoblock > div
{
width: 100%;
height: 100%;
}
.overlap
{
box-shadow: 0 0 20px 0 black inset;
z-index: 2;
}
.overlapMost
{
box-shadow: 0 0 20px 10px blue inset;
z-index: 2;
}
body.drag
{
user-select: none;
}
<div class="container">
<div class="carousel">
<!-- Carousel -->
<div class="carousel-content">
<div class="slide slide-1">
<div>1</div>
</div>
<div class="slide slide-2">
<div>2</div>
</div>
<div class="slide slide-3">
<div>3</div>
</div>
<div class="slide slide-4">
<div>4</div>
</div>
<div class="slide slide-5">
<div>5</div>
</div>
</div>
<!-- Fixed Block-->
<div class="infoblock">
<div>Drag Me</div>
</div>
<!-- Scroll Buttons -->
<div class="nav nav-left">
<div class="ion-chevron-left carousel-arrow-icon-left"></div>
</div>
<div class="nav nav-right">
<div class="ion-chevron-right carousel-arrow-icon-right"></div>
</div>
</div>
</div>
P.S。
您的代码中存在一个错误,其中 transitionend
事件在向右移动时未被删除,因为它正在尝试将其从第一张幻灯片中删除,但当时带有事件侦听器的幻灯片已经移至第二个位置。
我有这个问题。我有 div 个不同颜色的方块轮播。让我们将它们命名为一、二和三。在它们之上有一个名为“INFO”的固定块。因此,它位于两个街区之间。如果块 ONE 在超过 80% 时跨越信息块,我想在控制台“1”中写入。我不知道如何找出 INFO 下的特定块。 P.S: 现在我在控制台写 'hello' 如果轮播的块跨越信息块,但我需要写轮播块的 ID。
HTML:
<body>
<div class="container">
<div class="carousel">
<!-- Carousel -->
<div class="carousel-content">
<div class="slide slide-1">
<div>1</div>
</div>
<div class="slide slide-2">
<div>2</div>
</div>
<div class="slide slide-3">
<div>3</div>
</div>
</div>
<!-- Fixed Block-->
<div class="infoblock">
<div>INFO</div>
</div>
<!-- Scroll Buttons -->
<div class="nav nav-left">
<div class="ion-chevron-left carousel-arrow-icon-left"></div>
</div>
<div class="nav nav-right">
<div class="ion-chevron-right carousel-arrow-icon-right"></div>
</div>
</div>
</div>
<script src="script.js"></script>
</body>
CSS:
*,
*:before,
*:after {
box-sizing: border-box;
}
.carousel {
position: relative;
width: 50%;
height: 50px;
margin: 0 auto;
}
.carousel-content {
position: relative;
overflow: hidden;
transition: width .4s;
height: 100%;
}
.slide {
height: 100%;
position: absolute;
z-index: 1;
transition: left .4s cubic-bezier(.47,.13,.15,.89);
}
.slide-1{
background-color:cyan;
}
.slide-2 {
background-color: green;
}
.slide-3 {
background-color: red;
}
.nav {
position: absolute;
top: 50%;
margin-top: -10px;
background-color: rgba(150,150,150,.3);
width: 20px;
height: 20px;
z-index: 2;
cursor: pointer;
border-radius: 50%;
border: none;
outline: none;
color: white;
}
.nav-left {
left: -25px;
}
.nav-right {
right: -25px;
}
.infoblock{
position: absolute;
background-color:darkorange;
z-index: 2;
margin-top: -5vh;
margin-left: 10vw;
height: 100%;
width: 20%;
opacity: 0.6;
text-align: center;
border: 1px solid black;
}
JavaScript:
var carousel = document.querySelector('.carousel');
var carouselContent = document.querySelector('.carousel-content');
var slides = document.querySelectorAll('.slide');
var arrayOfSlides = Array.prototype.slice.call(slides);
var carouselDisplaying;
var screenSize;
setScreenSize();
var lengthOfSlide;
function addClone() {
var lastSlide = carouselContent.lastElementChild.cloneNode(true);
lastSlide.style.left = (-lengthOfSlide) + "px";
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
}
function removeClone() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
}
function moveSlidesRight() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
var width = 0;
slidesArray.forEach(function (el, i) {
el.style.left = width + "px";
width += lengthOfSlide;
});
addClone();
}
moveSlidesRight();
function moveSlidesLeft() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray = slidesArray.reverse();
var maxWidth = (slidesArray.length - 1) * lengthOfSlide;
slidesArray.forEach(function (el, i) {
maxWidth -= lengthOfSlide;
el.style.left = maxWidth + "px";
});
}
window.addEventListener('resize', setScreenSize);
function setScreenSize() {
if (window.innerWidth >= 500) {
carouselDisplaying = 3;
} else if (window.innerWidth >= 300) {
carouselDisplaying = 2;
} else {
carouselDisplaying = 1;
}
getScreenSize();
}
function getScreenSize() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
lengthOfSlide = (carousel.offsetWidth / carouselDisplaying);
var initialWidth = -lengthOfSlide;
slidesArray.forEach(function (el) {
el.style.width = lengthOfSlide + "px";
el.style.left = initialWidth + "px";
initialWidth += lengthOfSlide;
});
}
var rightNav = document.querySelector('.nav-right');
rightNav.addEventListener('click', moveLeft);
var moving = true;
function moveRight() {
if (moving) {
moving = false;
var lastSlide = carouselContent.lastElementChild;
lastSlide.parentNode.removeChild(lastSlide);
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', activateAgain);
moveSlidesRight();
}
}
function activateAgain() {
var firstSlide = carouselContent.firstElementChild;
moving = true;
firstSlide.removeEventListener('transitionend', activateAgain);
}
var leftNav = document.querySelector('.nav-left');
leftNav.addEventListener('click', moveRight);
function moveLeft() {
if (moving) {
moving = false;
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', replaceToEnd);
moveSlidesLeft();
}
}
function replaceToEnd() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
carouselContent.appendChild(firstSlide);
firstSlide.style.left = ((arrayOfSlides.length - 1) * lengthOfSlide) + "px";
addClone();
moving = true;
firstSlide.removeEventListener('transitionend', replaceToEnd);
}
carouselContent.addEventListener('mousedown', seeMovement);
var initialX;
var initialPos;
function seeMovement(e) {
initialX = e.clientX;
getInitialPos();
carouselContent.addEventListener('mousemove', slightMove);
document.addEventListener('mouseup', moveBasedOnMouse);
}
function slightMove(e) {
if (moving) {
var movingX = e.clientX;
var difference = initialX - movingX;
if (Math.abs(difference) < (lengthOfSlide / 4)) {
slightMoveSlides(difference);
}
}
}
function getInitialPos() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
initialPos = [];
slidesArray.forEach(function (el) {
var left = Math.floor(parseInt(el.style.left.slice(0, -2)));
initialPos.push(left);
});
}
function slightMoveSlides(newX) {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray.forEach(function (el, i) {
var oldLeft = initialPos[i];
el.style.left = (oldLeft + newX) + "px";
});
}
function moveBasedOnMouse(e) {
var finalX = e.clientX;
if (initialX - finalX > 0) {
moveRight();
} else if (initialX - finalX < 0) {
moveLeft();
}
document.removeEventListener('mouseup', moveBasedOnMouse);
carouselContent.removeEventListener('mousemove', slightMove);
}
/* Blocks Overlapping*/
const boxes = document.querySelectorAll(".slide");
function checkOverlap(ele1, ele2) {
const boundings1 = ele1.getBoundingClientRect();
const boundings2 = ele2.getBoundingClientRect();
const top1 = parseInt(boundings1.top);
const height1 = parseInt(boundings1.height);
const top2 = parseInt(boundings2.top);
const overlap = 1 - (top2 - top1) / height1;
if (overlap >= 0.8) {
ele2.classList.add("overlap-80");
console.log('hello');
}
}
checkOverlap(boxes[0], boxes[1]);
checkOverlap(boxes[2], boxes[3]);
checkOverlap(boxes[4], boxes[5]);
如果 INFO
盒子总是比幻灯片小,你可以在四个角上使用 document.elementsFromPoint()
来获取这些点的幻灯片列表:
var carousel = document.querySelector('.carousel');
var carouselContent = document.querySelector('.carousel-content');
var slides = document.querySelectorAll('.slide');
var arrayOfSlides = Array.prototype.slice.call(slides);
var carouselDisplaying;
var screenSize;
setScreenSize();
var lengthOfSlide;
function addClone() {
var lastSlide = carouselContent.lastElementChild.cloneNode(true);
lastSlide.style.left = (-lengthOfSlide) + "px";
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
}
function removeClone() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
}
function moveSlidesRight() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
var width = 0;
slidesArray.forEach(function (el, i) {
el.style.left = width + "px";
width += lengthOfSlide;
});
addClone();
}
moveSlidesRight();
function moveSlidesLeft() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray = slidesArray.reverse();
var maxWidth = (slidesArray.length - 1) * lengthOfSlide;
slidesArray.forEach(function (el, i) {
maxWidth -= lengthOfSlide;
el.style.left = maxWidth + "px";
});
}
window.addEventListener('resize', setScreenSize);
function setScreenSize() {
if (window.innerWidth >= 500) {
carouselDisplaying = 3;
} else if (window.innerWidth >= 300) {
carouselDisplaying = 2;
} else {
carouselDisplaying = 1;
}
getScreenSize();
}
function getScreenSize() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
lengthOfSlide = (carousel.offsetWidth / carouselDisplaying);
var initialWidth = -lengthOfSlide;
slidesArray.forEach(function (el) {
el.style.width = lengthOfSlide + "px";
el.style.left = initialWidth + "px";
initialWidth += lengthOfSlide;
});
}
var rightNav = document.querySelector('.nav-right');
rightNav.addEventListener('click', moveLeft);
var moving = true;
function moveRight() {
if (moving) {
moving = false;
var lastSlide = carouselContent.lastElementChild;
lastSlide.parentNode.removeChild(lastSlide);
carouselContent.insertBefore(lastSlide, carouselContent.firstChild);
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', activateAgain);
moveSlidesRight();
}
}
function activateAgain() {
var firstSlide = carouselContent.firstElementChild.nextSibling; /*changed*/
moving = true;
firstSlide.removeEventListener('transitionend', activateAgain);
}
var leftNav = document.querySelector('.nav-left');
leftNav.addEventListener('click', moveRight);
function moveLeft() {
if (moving) {
moving = false;
removeClone();
var firstSlide = carouselContent.firstElementChild;
firstSlide.addEventListener('transitionend', replaceToEnd);
moveSlidesLeft();
}
}
function replaceToEnd() {
var firstSlide = carouselContent.firstElementChild;
firstSlide.parentNode.removeChild(firstSlide);
carouselContent.appendChild(firstSlide);
firstSlide.style.left = ((arrayOfSlides.length - 1) * lengthOfSlide) + "px";
addClone();
moving = true;
firstSlide.removeEventListener('transitionend', replaceToEnd);
}
carouselContent.addEventListener('mousedown', seeMovement);
var initialX;
var initialPos;
function seeMovement(e) {
initialX = e.clientX;
getInitialPos();
carouselContent.addEventListener('mousemove', slightMove);
document.addEventListener('mouseup', moveBasedOnMouse);
}
function slightMove(e) {
if (moving) {
var movingX = e.clientX;
var difference = initialX - movingX;
if (Math.abs(difference) < (lengthOfSlide / 4)) {
slightMoveSlides(difference);
}
}
}
function getInitialPos() {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
initialPos = [];
slidesArray.forEach(function (el) {
var left = Math.floor(parseInt(el.style.left.slice(0, -2)));
initialPos.push(left);
});
}
function slightMoveSlides(newX) {
var slides = document.querySelectorAll('.slide');
var slidesArray = Array.prototype.slice.call(slides);
slidesArray.forEach(function (el, i) {
var oldLeft = initialPos[i];
el.style.left = (oldLeft + newX) + "px";
});
}
function moveBasedOnMouse(e) {
var finalX = e.clientX;
if (initialX - finalX > 0) {
moveRight();
} else if (initialX - finalX < 0) {
moveLeft();
}
document.removeEventListener('mouseup', moveBasedOnMouse);
carouselContent.removeEventListener('mousemove', slightMove);
}
/* Blocks Overlapping*/
/*changed*/
const infoBox = document.querySelector(".infoblock>div");
function checkOverlap() {
const info = infoBox.getBoundingClientRect();
let data = [],
slide = document.querySelector('.slide').getBoundingClientRect(),
list = [];
// check elements at each corner of info block and several points within
for(let x = 0, cache = {}; x < Math.round(info.width / (slide.width/3)); x++)
{
for(let y = 0; y < Math.round(info.height / (slide.height/3)); y++)
{
const X = Math.min(info.right-1, info.left + slide.width * x),
Y = Math.min(info.bottom-1, info.top + slide.height * y);
if (cache[X + "x" + Y])
continue;
list = list.concat(cache[X + "x" + Y] = document.elementsFromPoint(X, Y));
}
}
//leave only slides and remove any duplicates
list = list.filter((item, pos) => item.classList.contains("slide") && list.indexOf(item) === pos);
for(let i = 0; i < list.length; i++)
{
const slide = list[i];
const box = slide.getBoundingClientRect(),
width = Math.max(Math.min(box.right, info.right) - Math.max(box.left, info.left), 0),
height = Math.max(Math.min(box.bottom, info.bottom) - Math.max(box.top, info.top), 0),
overlapX = width / info.width,
overlapY = height / info.height,
overlapArea = (width * height) / (info.width * info.height);
data[data.length] = {slide: slide, area: overlapArea, x: overlapX, y: overlapY}
}
return data;
}
/* demo */
let infoRect = infoBox.getBoundingClientRect(),
theta = Math.random() * 10,
gamma = Math.random() * 1,
dragX = 0,
dragY = 0,
pause = true;
document.onmousedown = function(e)
{
if (e.target === infoBox.parentNode)
return infoBox.parentNode.classList.add("resize");
if (e.target != infoBox)
return;
dragX = e.x - infoBox.parentNode.offsetLeft;
dragY = e.y - infoBox.parentNode.offsetTop;
document.body.classList.add("drag");
}
document.onmouseup = function(e)
{
if (!document.body.classList.contains("drag") && !infoBox.parentNode.classList.contains("resize"))
return;
document.body.classList.remove("drag");
infoBox.parentNode.classList.remove("resize");
demoInfo(true);
}
document.onmousemove = function(e)
{
const isMove = document.body.classList.contains("drag");
if (!isMove && !infoBox.parentNode.classList.contains("resize"))
return;
if (isMove)
{
infoBox.parentNode.style.left = (e.x - dragX) + "px";
infoBox.parentNode.style.top = (e.y - dragY) + "px";
}
demoInfo();
}
//we can use parent container to listen for transition events
document.querySelector(".carousel-content").addEventListener("transitionend", demoInfo);
function isOverlapped(node, data)
{
for(let i = 0; i < data.length; i++)
{
if (data[i].slide === node)
return true;
}
return false;
}
function demoInfo(moved)
{
const r = infoBox.getBoundingClientRect();
document.documentElement.style.setProperty('--size', Math.min(r.height, Math.min(r.width, 100)) / 76 + 'em')
const data = checkOverlap();
data.sort((a,b) => b.area - a.area); //sorted by area
const slides = document.querySelectorAll(".slide");
for(let i = 0; i < slides.length; i++)
{
slides[i].classList.toggle("overlapMost", data.length && slides[i] === data[0].slide)
slides[i].classList.toggle("overlap", isOverlapped(slides[i], data))
}
if (data.length)
{
infoBox.textContent = "Slide " + data[0].slide.textContent.trim() + " overlap\nArea:" + Math.round(data[0].area * 100) + "%\nWidth:" + Math.round(data[0].x * 100) + "%\nHeight:" + Math.round(data[0].y * 100) + "%";
}
else
{
infoBox.textContent = "no overlap\n\ndrag me";
}
if (moved)
{
console.clear();
for(let i = 0; i < data.length; i++)
{
console.log("Slide " + data[i].slide.textContent.trim() + " ( " + Array.prototype.indexOf.call(data[i].slide.parentNode.children, data[i].slide) + " child) overlap area: " + Math.round(data[i].area * 100) + "%, X: " + Math.round(data[i].x *100) + "%, Y: " + Math.round(data[i].y *100) + "%");
}
}
}
demoInfo();
*,
*:before,
*:after {
box-sizing: border-box;
}
.carousel {
position: relative;
width: 50%;
height: 50px;
margin: 0 auto;
}
.carousel-content {
position: relative;
overflow: hidden;
transition: width .4s;
height: 100%;
}
.slide {
height: 100%;
position: absolute;
z-index: 1;
transition: left .4s cubic-bezier(.47,.13,.15,.89);
}
.slide > div
{
vertical-align: middle;
text-align: center;
}
.slide-1{
background-color:cyan;
}
.slide-2 {
background-color: green;
}
.slide-3 {
background-color: red;
}
.slide-4 {
background-color: lightblue;
}
.slide-5 {
background-color: lightpink;
}
.nav {
position: absolute;
top: 50%;
margin-top: -10px;
background-color: rgba(150,150,150,.3);
width: 20px;
height: 20px;
z-index: 2;
cursor: pointer;
border-radius: 50%;
border: none;
outline: none;
color: white;
}
.nav-left {
left: -25px;
}
.nav-right {
right: -25px;
}
.infoblock{
position: absolute;
background-color:darkorange;
z-index: 2;
/* margin-top: -5vh;
margin-left: 10vw;*/
height: 100%;
width: 25%;
opacity: 0.6;
text-align: center;
border: 1px solid black;
font-size: 0.7em;
font-size: var(--size);
white-space: pre;
min-width: 20%;
min-height: 80%;
cursor: move;
top: 5vh;
left: 10vw;
text-shadow: 0 0 1px gray;
resize: both;
overflow: hidden;
display: flex;
}
.infoblock > div
{
width: 100%;
height: 100%;
}
.overlap
{
box-shadow: 0 0 20px 0 black inset;
z-index: 2;
}
.overlapMost
{
box-shadow: 0 0 20px 10px blue inset;
z-index: 2;
}
body.drag
{
user-select: none;
}
<div class="container">
<div class="carousel">
<!-- Carousel -->
<div class="carousel-content">
<div class="slide slide-1">
<div>1</div>
</div>
<div class="slide slide-2">
<div>2</div>
</div>
<div class="slide slide-3">
<div>3</div>
</div>
<div class="slide slide-4">
<div>4</div>
</div>
<div class="slide slide-5">
<div>5</div>
</div>
</div>
<!-- Fixed Block-->
<div class="infoblock">
<div>Drag Me</div>
</div>
<!-- Scroll Buttons -->
<div class="nav nav-left">
<div class="ion-chevron-left carousel-arrow-icon-left"></div>
</div>
<div class="nav nav-right">
<div class="ion-chevron-right carousel-arrow-icon-right"></div>
</div>
</div>
</div>
P.S。
您的代码中存在一个错误,其中 transitionend
事件在向右移动时未被删除,因为它正在尝试将其从第一张幻灯片中删除,但当时带有事件侦听器的幻灯片已经移至第二个位置。