在滚动条上动态添加和删除 div?
Dynamically add and remove the div on scroll?
我尝试在像 Dojo 网格一样滚动时添加和删除 div 标签。我只想显示 7 div 个标签。
在容器内向左滚动时,当第一个 div 标签(在左侧)从网页中隐藏时,隐藏的 div 将从容器中移除并创建一个新标签附在右侧。
向右滚动时应应用相同的过程。
类似于this example。但是我不想滚动 <tr>
标签,而是想滚动 <div>
的标签。
这是我之前尝试过的:https://jsfiddle.net/9y2ptsbg/3/我该怎么做?如果有任何插件(比如 Dojo),它也会很有帮助。
尝试
$(function() {
// adjust `colors` length to multiples of 7
var colors = [
"rgba(143, 146, 199, 0.49)",
"rgba(199, 143, 186, 0.49)",
"rgba(149, 199, 143, 0.49)",
"rgba(229, 86, 61, 0.49)",
"rgba(212, 229, 61, 0.49)",
"rgba(206, 61, 229, 0.49)",
"rgba(229, 157, 61, 0.49)",
"rgba(61, 165, 229, 0.49)",
"rgba(61, 229, 133, 0.49)",
"rgba(229, 61, 61, 0.49)",
"rgba(116, 61, 229, 0.49",
"rgba(218, 229, 61, 0.49)",
"rgba(21, 43, 157, 0.49)",
"rgba(153, 157, 21, 0.49)",
"rgba(199, 143, 186, 0.49)",
"rgba(149, 199, 143, 0.49)",
"rgba(229, 86, 61, 0.49)",
"rgba(212, 229, 61, 0.49)",
"rgba(206, 61, 229, 0.49)",
"rgba(229, 157, 61, 0.49)",
"rgba(61, 165, 229, 0.49)",
"rgba(61, 229, 133, 0.49)",
"rgba(229, 61, 61, 0.49)",
"rgba(116, 61, 229, 0.49",
"rgba(218, 229, 61, 0.49)",
"rgba(21, 43, 157, 0.49)",
"rgba(153, 157, 21, 0.49)",
"rgba(199, 143, 186, 0.49)"
// "rgba(149, 199, 143, 0.49)"
];
var container = $("<div/>", {
"id":"container",
"title":"click to pause , resume `scroller`"
});
var n = 7;
var scrolled = false;
var elems = $.map(colors, function(color, i) {
return $("<div>", {
"class": "blocks-" + (i + 1),
"text": i + 1,
"css": {
"backgroundColor": color,
"left": (i * 25) + "%"
}
})[0].outerHTML
});
var scroller = function scroller(e) {
var xz = container.scrollLeft();
var wx = container.width() * .73;
var keys = $.map($("div:first, div:last", container), function(el) {
return Number(el.className.replace(/[^\d+]/g, ""));
});
var first = keys[0];
var last = keys[1];
var _scroller = function _scroller(elem, idx) {
if (idx === 1 && scrolled) {
scrolled = false;
elem.scroll()
return
};
elem
.stop(true, true)
.off("scroll")
.empty()
.append(
elems
.slice(idx ? (idx - 1) - n : last
, idx ? idx - 1 : last + n)
.map(function(el, i) {
return $(el).css("left", (i * 25) + "%")[0].outerHTML
}).join("")
)
.delay(250)
.animate({
scrollLeft: (idx ? "+=" : "-=") + elem.width() / 3
}, 1000, function() {
scrolled = true;
elem.on("scroll", scroller).scroll()
})
};
if (xz < n && first !== 1 ) {
_scroller(container, first)
};
if (xz > wx && last !== colors.length) {
_scroller(container);
};
};
$("body")
.append(
container.data("scroll", true).html(elems.slice(0, n))
.on("scroll", scroller)
);
container.on("click", function() {
if (container.data("scroll")) {
container.data("scroll", false).off("scroll")
} else {
container.data("scroll", true)
.on("scroll", scroller).scroll()
}
})
});
[class^=blocks] {
padding: 0px;
width: 25%;
position: absolute;
height: 150%;
text-align: center;
font-size: 100px;
}
#container {
width: 100%;
height: 250px;
position: relative;
overflow: auto;
margin-top: 50%;
background: #2a2a2a;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
是的,这是可能的。首先,你需要这样的结构:
<div class="scroll">
<div class="container">
<div class="element element-1">1</div>
<div class="element element-2">2</div>
<div class="element element-3">3</div>
<div class="element element-4">4</div>
<div class="element element-5">5</div>
<div class="element element-6">6</div>
</div>
</div>
.scroll
元素将成为您的滚动容器,它的宽度或高度都有限制(取决于您想要滚动的方式)并且有一个 overflow
.
另一方面,.container
占用尽可能高的宽度,因此对于 6 个元素,它将是 element width * 6
。
最后,因为您想创建一个 left/right 滚动动画,所以您可能想将 float: left
设置为所有 .element
个节点。
JavaScript 代码也不难。您想向 .scroll
元素添加一个 onScroll
事件处理程序,您可以这样做:
query(".scroll").on("scroll", function(evt) {
});
然后您想检测您是向左滚动还是向右滚动。您可以通过将滚动偏移量与之前的滚动偏移量进行比较来做到这一点,例如:
if (lastPos && lastPos - evt.target.scrollLeft > 0) {
// Scrolling to the left
} else if (lastPos && lastPos - evt.target.scrollLeft < 0) {
// Scrolling to the right
}
lastPos = evt.target.scrollLeft;
现在,在 if
中,您想遍历所有 .element
,检测是否在可见部分的左侧或右侧,以及它是否打开其中一侧,您将其移动到另一侧(取决于滚动方向)。
要检查元素是在 .scroll
的左侧还是右侧,我使用 Element.getBoundingClientRect()
:
var isLeftOfContainer = function(element) {
var bounds = element.getBoundingClientRect();
return (-bounds.left + element.parentNode.offsetLeft) >= bounds.width;
};
var isRightOfContainer = function(element) {
var bounds = element.getBoundingClientRect();
var box = element.parentNode.parentNode.getBoundingClientRect();
return bounds.left - element.parentNode.offsetLeft > box.width;
};
要将节点移动到另一侧,我使用 dojo/dom-construct::place()
。您可以添加 "first"
或 "last"
作为第三个参数,具体取决于您滚动的方向,例如:
domConstruct.place(elem, elem.parentNode, "first");
这会将元素 (elem
) 移动到父节点的第一个位置。这是我们向左滚动时想要做的事情。
要遍历所有元素,您可以使用 dojo/query
,例如:
query(".element").forEach(function(element) {
});
请记住,当您向左滚动时,您希望从最后一个元素到第一个元素遍历数组,这样如果同时隐藏了 2 个元素,则将第 6 个元素添加为添加第 5 个元素作为第一个元素之前的第一个元素。这确保您始终以正确的顺序添加元素。
最后你必须调整 .scroll
元素的滚动位置。如果将 DOM 节点移动到列表的另一侧,则会产生所有元素都将移动的副作用。如果您不向后移动滚动位置,这将导致 weird/buggy 行为。
您可以通过调整 .scroll
元素的 scrollLeft
属性来做到这一点。
一切结合起来你可以想出这样的东西:http://jsfiddle.net/c3u6bfmf/
也许这个 js fiddle 会有所帮助?
https://jsfiddle.net/9y2ptsbg/12/
var container = $("#container"),
info = $("#info");
var j = 0;
var colors = ['rgba(143, 146, 199, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)']
var ary = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36'],
cursor = 0,
attachDiv = function (_curr) {
container.empty();
var j = 0;
for (var i = _curr; i < _curr + 8; i++) {
container.append('<div class = "blocks blocks' + i + '" style="left:' + (j * 25) + '%; background:' + colors[i] + ';">' + ary[i] + '</div>');
j++;
}
};
var hasScrolled = false,
locked = false,
ticker = function () {
if (hasScrolled && !locked) {
locked = true;
var xz = container.scrollLeft(),
maxScrollLeft = container.get(0).scrollWidth - container.get(0).clientWidth,
middle = maxScrollLeft / 2;
if (xz == 0) {
cursor = Math.max(0, cursor - 4);
} else if (xz == maxScrollLeft) {
cursor = Math.min(cursor + 4, ary.length - 8)
}
attachDiv(cursor);
container.scrollLeft(middle);
info.text(cursor);
locked = false;
}
hasScrolled = false;
}
setInterval(ticker, 250);
container.on('scroll', function () {
hasScrolled = true;
});
attachDiv(0);
实际上,在您提供的示例中,您正在滚动 div
s。每个 div
包含一个 table,但这不是重点。
我会说你需要一个内容 div
,并根据当前滚动位置在 javascript 中播放它的边距。只要确保总宽度保持不变即可。
这将确保标准滚动条正确显示而不 "jump",同时内容可以调整到其位置。
顺便说一下,在您提供的示例中,他们使用了 3 个 div
和部分内容 - 只有显示中的 div
或 div
有内容,并且可能有部分内容(只有底部或顶部的一些内容,足以填满显示区域。
不管怎样,这里的关键是维护一个足够大的可滚动元素,让滚动条保持其大小和位置,或者使用完全写在javascript.
中的自定义滚动条
我尝试在像 Dojo 网格一样滚动时添加和删除 div 标签。我只想显示 7 div 个标签。
在容器内向左滚动时,当第一个 div 标签(在左侧)从网页中隐藏时,隐藏的 div 将从容器中移除并创建一个新标签附在右侧。
向右滚动时应应用相同的过程。
类似于this example。但是我不想滚动 <tr>
标签,而是想滚动 <div>
的标签。
这是我之前尝试过的:https://jsfiddle.net/9y2ptsbg/3/我该怎么做?如果有任何插件(比如 Dojo),它也会很有帮助。
尝试
$(function() {
// adjust `colors` length to multiples of 7
var colors = [
"rgba(143, 146, 199, 0.49)",
"rgba(199, 143, 186, 0.49)",
"rgba(149, 199, 143, 0.49)",
"rgba(229, 86, 61, 0.49)",
"rgba(212, 229, 61, 0.49)",
"rgba(206, 61, 229, 0.49)",
"rgba(229, 157, 61, 0.49)",
"rgba(61, 165, 229, 0.49)",
"rgba(61, 229, 133, 0.49)",
"rgba(229, 61, 61, 0.49)",
"rgba(116, 61, 229, 0.49",
"rgba(218, 229, 61, 0.49)",
"rgba(21, 43, 157, 0.49)",
"rgba(153, 157, 21, 0.49)",
"rgba(199, 143, 186, 0.49)",
"rgba(149, 199, 143, 0.49)",
"rgba(229, 86, 61, 0.49)",
"rgba(212, 229, 61, 0.49)",
"rgba(206, 61, 229, 0.49)",
"rgba(229, 157, 61, 0.49)",
"rgba(61, 165, 229, 0.49)",
"rgba(61, 229, 133, 0.49)",
"rgba(229, 61, 61, 0.49)",
"rgba(116, 61, 229, 0.49",
"rgba(218, 229, 61, 0.49)",
"rgba(21, 43, 157, 0.49)",
"rgba(153, 157, 21, 0.49)",
"rgba(199, 143, 186, 0.49)"
// "rgba(149, 199, 143, 0.49)"
];
var container = $("<div/>", {
"id":"container",
"title":"click to pause , resume `scroller`"
});
var n = 7;
var scrolled = false;
var elems = $.map(colors, function(color, i) {
return $("<div>", {
"class": "blocks-" + (i + 1),
"text": i + 1,
"css": {
"backgroundColor": color,
"left": (i * 25) + "%"
}
})[0].outerHTML
});
var scroller = function scroller(e) {
var xz = container.scrollLeft();
var wx = container.width() * .73;
var keys = $.map($("div:first, div:last", container), function(el) {
return Number(el.className.replace(/[^\d+]/g, ""));
});
var first = keys[0];
var last = keys[1];
var _scroller = function _scroller(elem, idx) {
if (idx === 1 && scrolled) {
scrolled = false;
elem.scroll()
return
};
elem
.stop(true, true)
.off("scroll")
.empty()
.append(
elems
.slice(idx ? (idx - 1) - n : last
, idx ? idx - 1 : last + n)
.map(function(el, i) {
return $(el).css("left", (i * 25) + "%")[0].outerHTML
}).join("")
)
.delay(250)
.animate({
scrollLeft: (idx ? "+=" : "-=") + elem.width() / 3
}, 1000, function() {
scrolled = true;
elem.on("scroll", scroller).scroll()
})
};
if (xz < n && first !== 1 ) {
_scroller(container, first)
};
if (xz > wx && last !== colors.length) {
_scroller(container);
};
};
$("body")
.append(
container.data("scroll", true).html(elems.slice(0, n))
.on("scroll", scroller)
);
container.on("click", function() {
if (container.data("scroll")) {
container.data("scroll", false).off("scroll")
} else {
container.data("scroll", true)
.on("scroll", scroller).scroll()
}
})
});
[class^=blocks] {
padding: 0px;
width: 25%;
position: absolute;
height: 150%;
text-align: center;
font-size: 100px;
}
#container {
width: 100%;
height: 250px;
position: relative;
overflow: auto;
margin-top: 50%;
background: #2a2a2a;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
是的,这是可能的。首先,你需要这样的结构:
<div class="scroll">
<div class="container">
<div class="element element-1">1</div>
<div class="element element-2">2</div>
<div class="element element-3">3</div>
<div class="element element-4">4</div>
<div class="element element-5">5</div>
<div class="element element-6">6</div>
</div>
</div>
.scroll
元素将成为您的滚动容器,它的宽度或高度都有限制(取决于您想要滚动的方式)并且有一个 overflow
.
另一方面,.container
占用尽可能高的宽度,因此对于 6 个元素,它将是 element width * 6
。
最后,因为您想创建一个 left/right 滚动动画,所以您可能想将 float: left
设置为所有 .element
个节点。
JavaScript 代码也不难。您想向 .scroll
元素添加一个 onScroll
事件处理程序,您可以这样做:
query(".scroll").on("scroll", function(evt) {
});
然后您想检测您是向左滚动还是向右滚动。您可以通过将滚动偏移量与之前的滚动偏移量进行比较来做到这一点,例如:
if (lastPos && lastPos - evt.target.scrollLeft > 0) {
// Scrolling to the left
} else if (lastPos && lastPos - evt.target.scrollLeft < 0) {
// Scrolling to the right
}
lastPos = evt.target.scrollLeft;
现在,在 if
中,您想遍历所有 .element
,检测是否在可见部分的左侧或右侧,以及它是否打开其中一侧,您将其移动到另一侧(取决于滚动方向)。
要检查元素是在 .scroll
的左侧还是右侧,我使用 Element.getBoundingClientRect()
:
var isLeftOfContainer = function(element) {
var bounds = element.getBoundingClientRect();
return (-bounds.left + element.parentNode.offsetLeft) >= bounds.width;
};
var isRightOfContainer = function(element) {
var bounds = element.getBoundingClientRect();
var box = element.parentNode.parentNode.getBoundingClientRect();
return bounds.left - element.parentNode.offsetLeft > box.width;
};
要将节点移动到另一侧,我使用 dojo/dom-construct::place()
。您可以添加 "first"
或 "last"
作为第三个参数,具体取决于您滚动的方向,例如:
domConstruct.place(elem, elem.parentNode, "first");
这会将元素 (elem
) 移动到父节点的第一个位置。这是我们向左滚动时想要做的事情。
要遍历所有元素,您可以使用 dojo/query
,例如:
query(".element").forEach(function(element) {
});
请记住,当您向左滚动时,您希望从最后一个元素到第一个元素遍历数组,这样如果同时隐藏了 2 个元素,则将第 6 个元素添加为添加第 5 个元素作为第一个元素之前的第一个元素。这确保您始终以正确的顺序添加元素。
最后你必须调整 .scroll
元素的滚动位置。如果将 DOM 节点移动到列表的另一侧,则会产生所有元素都将移动的副作用。如果您不向后移动滚动位置,这将导致 weird/buggy 行为。
您可以通过调整 .scroll
元素的 scrollLeft
属性来做到这一点。
一切结合起来你可以想出这样的东西:http://jsfiddle.net/c3u6bfmf/
也许这个 js fiddle 会有所帮助?
https://jsfiddle.net/9y2ptsbg/12/
var container = $("#container"),
info = $("#info");
var j = 0;
var colors = ['rgba(143, 146, 199, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)', 'rgba(229, 86, 61, 0.49)', 'rgba(212, 229, 61, 0.49)', 'rgba(206, 61, 229, 0.49)', 'rgba(229, 157, 61, 0.49)', 'rgba(61, 165, 229, 0.49)', 'rgba(61, 229, 133, 0.49)', 'rgba(229, 61, 61, 0.49)', 'rgba(116, 61, 229, 0.49', 'rgba(218, 229, 61, 0.49)', 'rgba(21, 43, 157, 0.49)', 'rgba(153, 157, 21, 0.49)', 'rgba(199, 143, 186, 0.49)', 'rgba(149, 199, 143, 0.49)']
var ary = ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28', '29', '30', '31', '32', '33', '34', '35', '36'],
cursor = 0,
attachDiv = function (_curr) {
container.empty();
var j = 0;
for (var i = _curr; i < _curr + 8; i++) {
container.append('<div class = "blocks blocks' + i + '" style="left:' + (j * 25) + '%; background:' + colors[i] + ';">' + ary[i] + '</div>');
j++;
}
};
var hasScrolled = false,
locked = false,
ticker = function () {
if (hasScrolled && !locked) {
locked = true;
var xz = container.scrollLeft(),
maxScrollLeft = container.get(0).scrollWidth - container.get(0).clientWidth,
middle = maxScrollLeft / 2;
if (xz == 0) {
cursor = Math.max(0, cursor - 4);
} else if (xz == maxScrollLeft) {
cursor = Math.min(cursor + 4, ary.length - 8)
}
attachDiv(cursor);
container.scrollLeft(middle);
info.text(cursor);
locked = false;
}
hasScrolled = false;
}
setInterval(ticker, 250);
container.on('scroll', function () {
hasScrolled = true;
});
attachDiv(0);
实际上,在您提供的示例中,您正在滚动 div
s。每个 div
包含一个 table,但这不是重点。
我会说你需要一个内容 div
,并根据当前滚动位置在 javascript 中播放它的边距。只要确保总宽度保持不变即可。
这将确保标准滚动条正确显示而不 "jump",同时内容可以调整到其位置。
顺便说一下,在您提供的示例中,他们使用了 3 个 div
和部分内容 - 只有显示中的 div
或 div
有内容,并且可能有部分内容(只有底部或顶部的一些内容,足以填满显示区域。
不管怎样,这里的关键是维护一个足够大的可滚动元素,让滚动条保持其大小和位置,或者使用完全写在javascript.
中的自定义滚动条