Scrollen | anchor | Position

KamiH

Grünschnabel
Hallo zusammen,

vorab: Ich kenne mich mit jvascript nicht aus!
Dennoch habe ich geschafft, ein script in meinTemplate (Joomla) einzubauen. Es funktioniert prima.
Nun möchte es minimal modifizieren, so dass beim scrollen nicht direkt auf "anchor" Stelle gescrollt wird, sondern 100px davor oder darüber.

Einen Versuch habe ich gestartet. Siehe Zeile 78
Leider geht es so nicht.

Und bei der Gelegenheit kann mir vielleicht jemand verraten, wo ich die Geschwindigkeit anpassen kann?

Welcher Experte hat einen Tipp für mich und Danke schon in vorraus!

Javascript:
/* Smooth scrolling
  Changes links that link to other parts of this page to scroll
  smoothly to those links rather than jump to them directly, which
  can be a little disorienting.
 
  sil, http://www.kryogenix.org/
 
  v1.0 2003-11-11
  v1.1 2005-06-16 wrap it up in an object
*/

var ss = {
  fixAllLinks: function() {
  // Get a list of all links in the page
  var allLinks = document.getElementsByTagName('a');
  // Walk through the list
  for (var i=0;i<allLinks.length;i++) {
  var lnk = allLinks[i];
  if ((lnk.href && lnk.href.indexOf('#') != -1) &&
  ( (lnk.pathname == location.pathname) ||
    ('/'+lnk.pathname == location.pathname) ) &&
  (lnk.search == location.search)) {
  // If the link is internal to the page (begins in #)
  // then attach the smoothScroll function as an onclick
  // event handler
  ss.addEvent(lnk,'click',ss.smoothScroll);
  }
  }
  },

  smoothScroll: function(e) {
  // This is an event handler; get the clicked on element,
  // in a cross-browser fashion
  if (window.event) {
  target = window.event.srcElement;
  } else if (e) {
  target = e.target;
  } else return;

  // Make sure that the target is an element, not a text node
  // within an element
  if (target.nodeName.toLowerCase() != 'a') {
  target = target.parentNode;
  }

  // Paranoia; check this is an A tag
  if (target.nodeName.toLowerCase() != 'a') return;

  // Find the <a name> tag corresponding to this href
  // First strip off the hash (first character)
  anchor = target.hash.substr(1);
  // Now loop all A tags until we find one with that name
  var allLinks = document.getElementsByTagName('a');
  var destinationLink = null;
  for (var i=0;i<allLinks.length;i++) {
  var lnk = allLinks[i];
  if (lnk.name && (lnk.name == anchor)) {
  destinationLink = lnk;
  break;
  }
  }
  if (!destinationLink) destinationLink = document.getElementById(anchor);

  // If we didn't find a destination, give up and let the browser do
  // its thing
  if (!destinationLink) return true;

  // Find the destination's position
  var destx = destinationLink.offsetLeft;
  var desty = destinationLink.offsetTop;
  var thisNode = destinationLink;
  while (thisNode.offsetParent &&
  (thisNode.offsetParent != document.body)) {
  thisNode = thisNode.offsetParent;
  destx += thisNode.offsetLeft;
  //hier ändere ich die top Position von anchor kami
  desty += thisNode.offsetTop - 90;
  }

  // Stop any current scrolling
  clearInterval(ss.INTERVAL);

  cypos = ss.getCurrentYPos();

  ss_stepsize = parseInt((desty-cypos)/ss.STEPS);
  ss.INTERVAL =
setInterval('ss.scrollWindow('+ss_stepsize+','+desty+',"'+anchor+'")',10);

  // And stop the actual click happening
  if (window.event) {
  window.event.cancelBubble = true;
  window.event.returnValue = false;
  }
  if (e && e.preventDefault && e.stopPropagation) {
  e.preventDefault();
  e.stopPropagation();
  }
  },

  scrollWindow: function(scramount,dest,anchor) {
  wascypos = ss.getCurrentYPos();
  isAbove = (wascypos < dest);
  window.scrollTo(0,wascypos + scramount);
  iscypos = ss.getCurrentYPos();
  isAboveNow = (iscypos < dest);
  if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
  // if we've just scrolled past the destination, or
  // we haven't moved from the last scroll (i.e., we're at the
  // bottom of the page) then scroll exactly to the link
  window.scrollTo(0,dest);
  // cancel the repeating timer
  clearInterval(ss.INTERVAL);
  // and jump to the link directly so the URL's right
  location.hash = anchor;
  }
  },

  getCurrentYPos: function() {
  if (document.body && document.body.scrollTop)
  return document.body.scrollTop;
  if (document.documentElement && document.documentElement.scrollTop)
  return document.documentElement.scrollTop;
  if (window.pageYOffset)
  return window.pageYOffset;
  return 0;
  },

  addEvent: function(elm, evType, fn, useCapture) {
  // addEvent and removeEvent
  // cross-browser event handling for IE5+,  NS6 and Mozilla
  // By Scott Andrew
  if (elm.addEventListener){
  elm.addEventListener(evType, fn, useCapture);
  return true;
  } else if (elm.attachEvent){
  var r = elm.attachEvent("on"+evType, fn);
  return r;
  } else {
  alert("Handler could not be removed");
  }
  }
}

ss.STEPS = 25;

ss.addEvent(window,"load",ss.fixAllLinks);
 
Zuletzt bearbeitet:
So funktioniert es:
Code:
                    while (thisNode.offsetParent && (thisNode.offsetParent != document.body)) {
                        thisNode = thisNode.offsetParent;
                        destx += thisNode.offsetLeft;
                        desty += thisNode.offsetTop;
                    }
                    desty -= 90;
Erklärung: In der Schleife wird jeweils das Eltern-Element ermittelt und die aktuelle Position (relativ zum Elternelement) aufaddiert. Liegt ein Anker direkt im Body, wird die Schleife gar nicht durchlaufen und deine Subtraktion ist nicht wirksam.

Und die Geschwindigkeit stellst Du hier ein:
Code:
ss.STEPS = 25;
Größerer Wert --> langsameres Scrollen.
 
Vielen Dank für Deine Erklärung!!!!
Mit der Position klappt nicht, wie Du geschrieben hast. Wurde es aber vielleicht mit einem anderen Script funktionieren?
Mit der Geschwindigkeit hat sofort funktioniert. Klasse!

Nur um zu verstehen, was ich eigentlich bewirken will – vielleicht kann es auch anderes gelöst werden.
Ich habe ein sticky navi, die eine Ebene höher über content liegt. Daher soll der smooth-script um die 90-100 px oder mit Prozentwerte manipoliert werden.
Hier ist die Seite.

Ich werde zunächst versuchen das screendesign anderes anzupassen, denn mit css kenne mich einwenig aus.
Wäre trotzdem sehr hilfreich zu erfahren, wie so etwas funktionieren könnte.
 
PS:
Nach dem extreme Werte eingegeben habe, habe gemerkt, dass die Animation bis zu Position "-100px" springt aber anschließend auf die ursprungliche Postion schnell zurückscrollt. Vielleicht muss dieser Wert zweimal eingetargen werden? Wurde es aber vielleicht mit einem anderen Script funktionieren?
 
Hm, ich hatte es mit einer Testseite getestet und damit hat es funktioniert:
Code:
<!DOCTYPE html>
<html>
<head>
</head>

<body>
<a href="#a2">Gehe zu Kontainer 2</a>
<div style="height: 1000px; border: 2px solid black">DIV 1</div>
<div id="a2" style="height: 1000px; border: 2px solid black">DIV 2</div>
<script>

/* Smooth scrolling
Changes links that link to other parts of this page to scroll
smoothly to those links rather than jump to them directly, which
can be a little disorienting.

sil, http://www.kryogenix.org/

v1.0 2003-11-11
v1.1 2005-06-16 wrap it up in an object
*/

var ss = {
fixAllLinks: function () {
// Get a list of all links in the page
var allLinks = document.getElementsByTagName('a');
// Walk through the list
for (var i = 0; i < allLinks.length; i++) {
var lnk = allLinks[i];
if ((lnk.href && lnk.href.indexOf('#') != -1) && ((lnk.pathname == location.pathname) || ('/' + lnk.pathname == location.pathname)) && (lnk.search == location.search)) {
// If the link is internal to the page (begins in #)
// then attach the smoothScroll function as an onclick
// event handler
ss.addEvent(lnk, 'click', ss.smoothScroll);
}
}
},
smoothScroll: function (e) {
// This is an event handler; get the clicked on element,
// in a cross-browser fashion
if (window.event) {
target = window.event.srcElement;
} else if (e) {
target = e.target;
} else return;
// Make sure that the target is an element, not a text node
// within an element
if (target.nodeName.toLowerCase() != 'a') {
target = target.parentNode;
}
// Paranoia; check this is an A tag
if (target.nodeName.toLowerCase() != 'a') return;
// Find the <a name> tag corresponding to this href
// First strip off the hash (first character)
anchor = target.hash.substr(1);
// Now loop all A tags until we find one with that name
var allLinks = document.getElementsByTagName('a');
var destinationLink = null;
for (var i = 0; i < allLinks.length; i++) {
var lnk = allLinks[i];
if (lnk.name && (lnk.name == anchor)) {
destinationLink = lnk;
break;
}
}
if (!destinationLink) destinationLink = document.getElementById(anchor);
// If we didn't find a destination, give up and let the browser do
// its thing
if (!destinationLink) return true;
// Find the destination's position
var destx = destinationLink.offsetLeft;
var desty = destinationLink.offsetTop;
var thisNode = destinationLink;
while (thisNode.offsetParent && (thisNode.offsetParent != document.body)) {
thisNode = thisNode.offsetParent;
destx += thisNode.offsetLeft;
//hier ändere ich die top Position von anchor kami
desty += thisNode.offsetTop;
}
desty -= 100;
// Stop any current scrolling
clearInterval(ss.INTERVAL);
cypos = ss.getCurrentYPos();
ss_stepsize = parseInt((desty - cypos) / ss.STEPS);
ss.INTERVAL = setInterval('ss.scrollWindow(' + ss_stepsize + ',' + desty + ',"' + anchor + '")', 10);
// And stop the actual click happening
if (window.event) {
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.preventDefault && e.stopPropagation) {
e.preventDefault();
e.stopPropagation();
}
},
scrollWindow: function (scramount, dest, anchor) {
wascypos = ss.getCurrentYPos();
isAbove = (wascypos < dest);
window.scrollTo(0, wascypos + scramount);
iscypos = ss.getCurrentYPos();
isAboveNow = (iscypos < dest);
if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
// if we've just scrolled past the destination, or
// we haven't moved from the last scroll (i.e., we're at the
// bottom of the page) then scroll exactly to the link
window.scrollTo(0, dest);
// cancel the repeating timer
clearInterval(ss.INTERVAL);
// and jump to the link directly so the URL's right
location.hash = anchor;
}
},
getCurrentYPos: function () {
if (document.body && document.body.scrollTop) return document.body.scrollTop;
if (document.documentElement && document.documentElement.scrollTop) return document.documentElement.scrollTop;
if (window.pageYOffset) return window.pageYOffset;
return 0;
},
addEvent: function (elm, evType, fn, useCapture) {
// addEvent and removeEvent
// cross-browser event handling for IE5+, NS6 and Mozilla
// By Scott Andrew
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
} else if (elm.attachEvent) {
var r = elm.attachEvent("on" + evType, fn);
return r;
} else {
alert("Handler could not be removed");
}
}
}
ss.STEPS = 500;
ss.addEvent(window, "load", ss.fixAllLinks);
</script>
</body>
</html>
Probiere ich es dagegen mit einem Fiddle, tritt der von dir beschriebene Fehler auf:
https://jsfiddle.net/Sempervivum/axfd0bhk/
Leider kann ich in dem Fiddle nicht debuggen.
 
PS: Glaube, ich konnte das Problem lösen. Der Übeltäter war das "location.hash = anchor;". So funktioniert es:
Code:
                scrollWindow: function (scramount, dest, anchor) {
                    wascypos = ss.getCurrentYPos();
                    isAbove = (wascypos < dest);
                    window.scrollTo(0, wascypos + scramount);
                    iscypos = ss.getCurrentYPos();
                    isAboveNow = (iscypos < dest);
                    if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
                        // if we've just scrolled past the destination, or
                        // we haven't moved from the last scroll (i.e., we're at the
                        // bottom of the page) then scroll exactly to the link
                        window.scrollTo(0, dest);
                        // cancel the repeating timer
                        clearInterval(ss.INTERVAL);
                        // and jump to the link directly so the URL's right
                        //location.hash = anchor;
                    }
                },
https://jsfiddle.net/Sempervivum/axfd0bhk/1/
 
Gut zu wissen!!!!! jsfiddle.net
Nachdem ich den Code von der Seite kopiert habe, und die Geschwindigkeit angepasst habe, läuft der Script hervorragend.
1000 Dank!
 
Zurück