Je fais défiler une div
et je veux avoir un lien quand je clique dessus, cela forcera cette div
à faire défiler pour voir un élément à l'intérieur .
document.getElementById(chr).scrollIntoView(true);
mais cela fait défiler toute la page tout en faisant défiler la div
elle-même . Comment résoudre ce problème?
Je veux le dire comme ça
MyContainerDiv.getElementById(chr).scrollIntoView(true);
Vous devez obtenir le décalage supérieur de l'élément que vous souhaitez faire défiler dans la vue, par rapport à son parent (le conteneur div scrolling):
var myElement = document.getElementById('element_within_div');
var topPos = myElement.offsetTop;
La variable topPos est maintenant définie sur la distance entre le haut du div à défilement et l'élément que vous souhaitez voir visible (en pixels).
Maintenant, nous disons à la div de faire défiler jusqu'à cette position en utilisant scrollTop
:
document.getElementById('scrolling_div').scrollTop = topPos;
Si vous utilisez le prototype de framework JS, vous feriez la même chose comme ceci:
var posArray = $('element_within_div').positionedOffset();
$('scrolling_div').scrollTop = posArray[1];
Encore une fois, cela fera défiler la div jusqu'à ce que l'élément que vous souhaitez voir se trouve tout en haut (ou, si ce n'est pas possible, faites défiler aussi bas que possible pour qu'il soit visible).
Vous devez trouver la position de l'élément dans la DIV que vous souhaitez faire défiler et définir la propriété scrollTop.
divElem.scrollTop = 0;
Mettre à jour:
Exemple de code pour monter ou descendre
function move_up() {
document.getElementById('divElem').scrollTop += 10;
}
function move_down() {
document.getElementById('divElem').scrollTop -= 10;
}
var box = document.querySelector('.box'),
targetElm = document.querySelector('.boxChild'); // <-- Scroll to here within ".box"
document.querySelector('button').addEventListener('click', function(){
scrollToElm( box, targetElm , 600 );
});
/////////////
function scrollToElm(container, Elm, duration){
var pos = getRelativePos(Elm);
scrollTo( container, pos.top , 2); // duration in seconds
}
function getRelativePos(Elm){
var pPos = Elm.parentNode.getBoundingClientRect(), // parent pos
cPos = Elm.getBoundingClientRect(), // target pos
pos = {};
pos.top = cPos.top - pPos.top + Elm.parentNode.scrollTop,
pos.right = cPos.right - pPos.right,
pos.bottom = cPos.bottom - pPos.bottom,
pos.left = cPos.left - pPos.left;
return pos;
}
function scrollTo(element, to, duration, onDone) {
var start = element.scrollTop,
change = to - start,
startTime = performance.now(),
val, now, elapsed, t;
function animateScroll(){
now = performance.now();
elapsed = (now - startTime)/1000;
t = (elapsed/duration);
element.scrollTop = start + change * easeInOutQuad(t);
if( t < 1 )
window.requestAnimationFrame(animateScroll);
else
onDone && onDone();
};
animateScroll();
}
function easeInOutQuad(t){ return t<.5 ? 2*t*t : -1+(4-2*t)*t };
.box{ width:80%; border:2px dashed; height:180px; overflow:auto; }
.boxChild{
margin:600px 0 300px;
width: 40px;
height:40px;
background:green;
}
<button>Scroll to element</button>
<div class='box'>
<div class='boxChild'></div>
</div>
Notez que le support du navigateur n'est pas génial pour celui-ci
var box = document.querySelector('.box'),
targetElm = document.querySelector('.boxChild');
document.querySelector('button').addEventListener('click', function(){
targetElm.scrollIntoView();
});
.box {
width: 80%;
border: 2px dashed;
height: 180px;
overflow: auto;
scroll-behavior: smooth; /* <-- for smooth scroll */
}
.boxChild {
margin: 600px 0 300px;
width: 40px;
height: 40px;
background: green;
}
<button>Scroll to element</button>
<div class='box'>
<div class='boxChild'></div>
</div>
.box {
width: 80%;
border: 2px dashed;
height: 180px;
overflow-y: scroll;
scroll-behavior: smooth; /* <--- */
}
#boxChild {
margin: 600px 0 300px;
width: 40px;
height: 40px;
background: green;
}
<a href='#boxChild'>Scroll to element</a>
<div class='box'>
<div id='boxChild'></div>
</div>
Le code devrait être:
var divElem = document.getElementById('scrolling_div');
var chElem = document.getElementById('element_within_div');
var topPos = divElem.offsetTop;
divElem.scrollTop = topPos - chElem.offsetTop;
Vous voulez faire défiler la différence entre la position supérieure de l'enfant et la position supérieure de div
Accédez aux éléments enfants à l'aide de:
var divElem = document.getElementById('scrolling_div');
var numChildren = divElem.childNodes.length;
etc....
Pour faire défiler un élément dans la vue d'un div, vous pouvez utiliser la fonction scrollIfNeeded
uniquement si nécessaire:
function scrollIfNeeded(element, container) {
if (element.offsetTop < container.scrollTop) {
container.scrollTop = element.offsetTop;
} else {
const offsetBottom = element.offsetTop + element.offsetHeight;
const scrollBottom = container.scrollTop + container.offsetHeight;
if (offsetBottom > scrollBottom) {
container.scrollTop = offsetBottom - container.offsetHeight;
}
}
}
document.getElementById('btn').addEventListener('click', ev => {
ev.preventDefault();
scrollIfNeeded(document.getElementById('goose'), document.getElementById('container'));
});
.scrollContainer {
overflow-y: auto;
max-height: 100px;
position: relative;
border: 1px solid red;
width: 120px;
}
body {
padding: 10px;
}
.box {
margin: 5px;
background-color: yellow;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
}
#goose {
background-color: Lime;
}
<div id="container" class="scrollContainer">
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div id="goose" class="box">goose</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
</div>
<button id="btn">scroll to goose</button>
Si vous utilisez jQuery, vous pouvez faire défiler une animation en utilisant les éléments suivants:
$(MyContainerDiv).animate({scrollTop: $(MyContainerDiv).scrollTop() + ($('element_within_div').offset().top - $(MyContainerDiv).offset().top)});
L'animation est facultative: vous pouvez également prendre la valeur scrollTop calculée ci-dessus et la placer directement dans la propriété scrollTop du conteneur.
Voici une solution JavaScript pur et simple qui fonctionne pour un nombre cible (valeur pour scrollTop
), un élément DOM cible ou certains cas spéciaux de chaîne:
/**
* target - target to scroll to (DOM element, scrollTop Number, 'top', or 'bottom'
* containerEl - DOM element for the container with scrollbars
*/
var scrollToTarget = function(target, containerEl) {
// Moved up here for readability:
var isElement = target && target.nodeType === 1,
isNumber = Object.prototype.toString.call(target) === '[object Number]';
if (isElement) {
containerEl.scrollTop = target.offsetTop;
} else if (isNumber) {
containerEl.scrollTop = target;
} else if (target === 'bottom') {
containerEl.scrollTop = containerEl.scrollHeight - containerEl.offsetHeight;
} else if (target === 'top') {
containerEl.scrollTop = 0;
}
};
Et voici quelques exemples d'utilisation:
// Scroll to the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget('top', scrollableDiv);
ou
// Scroll to 200px from the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget(200, scrollableDiv);
ou
// Scroll to targetElement
var scrollableDiv = document.getElementById('scrollable_div');
var targetElement= document.getElementById('target_element');
scrollToTarget(targetElement, scrollableDiv);
Il y a deux faits:
1) Le composant scrollIntoView n'est pas pris en charge par safari.
2) JS framework jQuery peut faire le travail comme ceci:
parent = 'some parent div has css position==="fixed"' || 'html, body';
$(parent).animate({scrollTop: $(child).offset().top}, duration)
Un autre exemple d'utilisation de jQuery et animate.
var container = $('#container');
var element = $('#element');
container.animate({
scrollTop: container.scrollTop = container.scrollTop() + element.offset().top - container.offset().top
}, {
duration: 1000,
specialEasing: {
width: 'linear',
height: 'easeOutBounce'
},
complete: function (e) {
console.log("animation completed");
}
});
C'est ce qui m'a finalement servi
/** Set parent scroll to show element
* @param element {object} The HTML object to show
* @param parent {object} The HTML object where the element is shown */
var scrollToView = function(element, parent) {
//Algorithm: Accumulate the height of the previous elements and add half the height of the parent
var offsetAccumulator = 0;
parent = $(parent);
parent.children().each(function() {
if(this == element) {
return false; //brake each loop
}
offsetAccumulator += $(this).innerHeight();
});
parent.scrollTop(offsetAccumulator - parent.innerHeight()/2);
}
le navigateur fait défiler automatiquement un élément qui fait l'objet du focus. Vous pouvez donc le faire également pour encapsuler l'élément dans lequel vous devez faire défiler l'élément <a>...</a>
, puis, lorsque vous avez besoin d'un défilement, il suffit de définir le focus sur cet élément a
Défilement animé par l'utilisateur
Voici un exemple de défilement par programme d'un <div>
horizontalement, sansJQuery. Pour faire défiler verticalement, vous devez remplacer les écritures JavaScript dans scrollLeft
par scrollTop
.
JSFiddle
https://jsfiddle.net/fNPvf/38536/
HTML
<!-- Left Button. -->
<div style="float:left;">
<!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
<input type="button" value="«" style="height: 100px;" onmousedown="scroll('scroller',3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
</div>
<!-- Contents to scroll. -->
<div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
<!-- <3 -->
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
</div>
<!-- Right Button. -->
<div style="float:left;">
<!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
<input type="button" value="»" style="height: 100px;" onmousedown="scroll('scroller',-3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
</div>
JavaScript
// Declare the Shared Timer.
var TIMER_SCROLL;
/**
Scroll function.
@param id Unique id of element to scroll.
@param d Amount of pixels to scroll per sleep.
@param del Size of the sleep (ms).*/
function scroll(id, d, del){
// Scroll the element.
document.getElementById(id).scrollLeft += d;
// Perform a delay before recursing this function again.
TIMER_SCROLL = setTimeout("scroll('"+id+"',"+d+", "+del+");", del);
}
Crédit à Dux .
Défilement Animé Auto
De plus, voici des fonctions permettant de faire défiler un <div>
complètement à gauche et à droite. La seule chose que nous changeons ici est que nous vérifions si l'extension complète du parchemin a été utilisée avant de faire un appel récursif pour faire défiler à nouveau.
JSFiddle
https://jsfiddle.net/0nLc2fhh/1/
HTML
<!-- Left Button. -->
<div style="float:left;">
<!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
<input type="button" value="«" style="height: 100px;" onclick="scrollFullyLeft('scroller',3, 10);"/>
</div>
<!-- Contents to scroll. -->
<div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
<!-- <3 -->
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
</div>
<!-- Right Button. -->
<div style="float:left;">
<!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
<input type="button" value="»" style="height: 100px;" onclick="scrollFullyRight('scroller',3, 10);"/>
</div>
JavaScript
// Declare the Shared Timer.
var TIMER_SCROLL;
/**
Scroll fully left function; completely scrolls a <div> to the left, as far as it will go.
@param id Unique id of element to scroll.
@param d Amount of pixels to scroll per sleep.
@param del Size of the sleep (ms).*/
function scrollFullyLeft(id, d, del){
// Fetch the element.
var el = document.getElementById(id);
// Scroll the element.
el.scrollLeft += d;
// Have we not finished scrolling yet?
if(el.scrollLeft < (el.scrollWidth - el.clientWidth)) {
TIMER_SCROLL = setTimeout("scrollFullyLeft('"+id+"',"+d+", "+del+");", del);
}
}
/**
Scroll fully right function; completely scrolls a <div> to the right, as far as it will go.
@param id Unique id of element to scroll.
@param d Amount of pixels to scroll per sleep.
@param del Size of the sleep (ms).*/
function scrollFullyRight(id, d, del){
// Fetch the element.
var el = document.getElementById(id);
// Scroll the element.
el.scrollLeft -= d;
// Have we not finished scrolling yet?
if(el.scrollLeft > 0) {
TIMER_SCROLL = setTimeout("scrollFullyRight('"+id+"',"+d+", "+del+");", del);
}
}