スムーズスクロールが自由自在。アンカーリンクを使いこなす!scrollsmartly.jsが神がかってる。
スムーズスクロールはjavascriptとかjQueryを使うことが多いと思うのですが、他のjavaとの兼ね合いとか、なんかうまくいかない部分があったりしますよね。
そこで出会ったのが、scrollsmartly.js。
要望をすべて叶えてくれるスクロール
KAZUMiX氏が2008年に開発されたようで、今はもうリンク切れになっていたので・・・
私はDLしておりましたので、内容を見てみます。
// UTF-8 /** * scrollsmoothly.js * Copyright (c) 2008 KAZUMiX * http://d.hatena.ne.jp/KAZUMiX/20080418/scrollsmoothly * Licensed under the MIT License: * http://www.opensource.org/licenses/mit-license.php * * 更新履歴 * 2009/02/12 * スクロール先が画面左上にならない場合の挙動を修正 * 2008/04/18 * 公開 * */ (function(){ var easing = 0.25; var interval = 20; var d = document; var targetX = 0; var targetY = 0; var targetHash = ''; var scrolling = false; var splitHref = location.href.split('#'); var currentHref_WOHash = splitHref[0]; var incomingHash = splitHref[1]; var prevX = null; var prevY = null; // ドキュメント読み込み完了時にinit()を実行する addEvent(window, 'load', init); // ドキュメント読み込み完了時の処理 function init(){ // ページ内リンクにイベントを設定する setOnClickHandler(); // 外部からページ内リンク付きで呼び出された場合 if(incomingHash){ if(window.attachEvent && !window.opera){ // IEの場合はちょっと待ってからスクロール setTimeout(function(){scrollTo(0,0);setScroll('#'+incomingHash);},50); }else{ // IE以外はそのままGO scrollTo(0, 0); setScroll('#'+incomingHash); } } } // イベントを追加する関数 function addEvent(eventTarget, eventName, func){ if(eventTarget.addEventListener){ // モダンブラウザ eventTarget.addEventListener(eventName, func, false); }else if(window.attachEvent){ // IE eventTarget.attachEvent('on'+eventName, function(){func.apply(eventTarget);}); } } function setOnClickHandler(){ var links = d.links; for(var i=0; i<links.length; i++){ // ページ内リンクならスクロールさせる var link = links[i]; var splitLinkHref = link.href.split('#'); if(currentHref_WOHash == splitLinkHref[0] && d.getElementById(splitLinkHref[1])){ addEvent(link, 'click', startScroll); } } } function startScroll(event){ // リンクのデフォルト動作を殺す if(event){ // モダンブラウザ event.preventDefault(); //alert('modern'); }else if(window.event){ // IE window.event.returnValue = false; //alert('ie'); } // thisは呼び出し元になってる setScroll(this.hash); } function setScroll(hash){ // ハッシュからターゲット要素の座標をゲットする var targetEle = d.getElementById(hash.substr(1)); if(!targetEle)return; //alert(scrollSize.height); // スクロール先座標をセットする var ele = targetEle; var x = 0; var y = 0; while(ele){ x += ele.offsetLeft; y += ele.offsetTop; ele = ele.offsetParent; } var maxScroll = getScrollMaxXY(); targetX = Math.min(x, maxScroll.x); targetY = Math.min(y, maxScroll.y); targetHash = hash; // スクロール停止中ならスクロール開始 if(!scrolling){ scrolling = true; scroll(); } } function scroll(){ var currentX = d.documentElement.scrollLeft||d.body.scrollLeft; var currentY = d.documentElement.scrollTop||d.body.scrollTop; var vx = (targetX - currentX) * easing; var vy = (targetY - currentY) * easing; var nextX = currentX + vx; var nextY = currentY + vy; if((Math.abs(vx) < 1 && Math.abs(vy) < 1) || (prevX === currentX && prevY === currentY)){ // 目標座標付近に到達していたら終了 scrollTo(targetX, targetY); scrolling = false; location.hash = targetHash; prevX = prevY = null; return; }else{ // 繰り返し scrollTo(parseInt(nextX), parseInt(nextY)); prevX = currentX; prevY = currentY; setTimeout(function(){scroll()},interval); } } function getDocumentSize(){ return {width:Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), height:Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)}; } function getWindowSize(){ var result = {}; if(window.innerWidth){ var box = d.createElement('div'); with(box.style){ position = 'absolute'; top = '0px'; left = '0px'; width = '100%'; height = '100%'; margin = '0px'; padding = '0px'; border = 'none'; visibility = 'hidden'; } d.body.appendChild(box); var width = box.offsetWidth; var height = box.offsetHeight; d.body.removeChild(box); result = {width:width, height:height}; }else{ result = {width:d.documentElement.clientWidth || d.body.clientWidth, height:d.documentElement.clientHeight || d.body.clientHeight}; } return result; } function getScrollMaxXY() { if(window.scrollMaxX && window.scrollMaxY){ return {x:window.scrollMaxX, y:window.scrollMaxY}; } var documentSize = getDocumentSize(); var windowSize = getWindowSize(); return {x:documentSize.width - windowSize.width, y:documentSize.height - windowSize.height}; } }());
なにがすごいかというと。
縦横斜めどこへでもスクロールできるよ〜〜〜〜。
しゅごい;;;;
別ページからのリンクでも思い通りの場所に飛んでくれるよ〜〜〜〜。
私はこの機能がひたすらに欲しくて!!!!
探していたんです。
アンカーリンクって、どうしてもページ内リンクじゃないですか!
でもでも、例えば最近多くなってる、トップページが縦長デザインの場合。
ヘッダーメニューから、トップページ内アンカーリンクで飛ばしたい箇所があって、それが同一ページならまだしも。
別ページに飛んだ時にも同じヘッダーから、トップページのアンカーリンク箇所に飛ばす場合!
ぜんっぜんうまくいかなかった。
しかーし!!!!
この、scrollsmartly.jsなら、うまくいくんです!!!
アンカーリンクがスムーズになった。でも、ヘッダーが固定の場合の位置も一気に変えたい!
次の問題は、これです。
ヘッダーが固定の場合、アンカーリンクで飛ぶとヘッダーに隠れてしまいますよね。
marginとpaiddingを調整してcssだけでやる方法もありますが、アンカーリンクまみれのページだと、指定してられない。
だから、jQueryとかを使って一括指定するのですが、どうもうまくいかない。
そりゃあ同じような指示を2度してるからな・・・ってことは、このscrollsmartly.jsだけでリンク位置もどうにかなるんじゃないか!?
scrollsmartly.jsで停止位置をヘッダー分ずらす方法
ありました。
detail.chiebukuro.yahoo.co.jp
知恵袋様!!
ここの質問と回答をもとにやったらもう最高にできました!お二人が神様です。
// UTF-8 /** * scrollsmoothly.js * Copyright (c) 2008 KAZUMiX * http://d.hatena.ne.jp/KAZUMiX/20080418/scrollsmoothly * Licensed under the MIT License: * http://www.opensource.org/licenses/mit-license.php * * 更新履歴 * 2009/02/12 * スクロール先が画面左上にならない場合の挙動を修正 * 2008/04/18 * 公開 * */ (function(){ var easing = 0.25; var interval = 20; var d = document; var targetX = 0; var targetY = 0; var targetHash = ''; var scrolling = false; var splitHref = location.href.split('#'); var currentHref_WOHash = splitHref[0]; var incomingHash = splitHref[1]; var prevX = null; var prevY = null; var plusY = 110;//追加部分 // ドキュメント読み込み完了時にinit()を実行する addEvent(window, 'load', init); // ドキュメント読み込み完了時の処理 function init(){ // ページ内リンクにイベントを設定する setOnClickHandler(); // 外部からページ内リンク付きで呼び出された場合 if(incomingHash){ if(window.attachEvent && !window.opera){ // IEの場合はちょっと待ってからスクロール setTimeout(function(){scrollTo(0,0);setScroll('#'+incomingHash);},50); }else{ // IE以外はそのままGO scrollTo(0, 0); setScroll('#'+incomingHash); } } } // イベントを追加する関数 function addEvent(eventTarget, eventName, func){ if(eventTarget.addEventListener){ // モダンブラウザ eventTarget.addEventListener(eventName, func, false); }else if(window.attachEvent){ // IE eventTarget.attachEvent('on'+eventName, function(){func.apply(eventTarget);}); } } function setOnClickHandler(){ var links = d.links; for(var i=0; i<links.length; i++){ // ページ内リンクならスクロールさせる var link = links[i]; var splitLinkHref = link.href.split('#'); if(currentHref_WOHash == splitLinkHref[0] && d.getElementById(splitLinkHref[1])){ addEvent(link, 'click', startScroll); } } } function startScroll(event){ // リンクのデフォルト動作を殺す if(event){ // モダンブラウザ event.preventDefault(); //alert('modern'); }else if(window.event){ // IE window.event.returnValue = false; //alert('ie'); } // thisは呼び出し元になってる setScroll(this.hash); } function setScroll(hash){ // ハッシュからターゲット要素の座標をゲットする var targetEle = d.getElementById(hash.substr(1)); if(!targetEle)return; //alert(scrollSize.height); // スクロール先座標をセットする var ele = targetEle; var x = 0; var y = 0; while(ele){ x += ele.offsetLeft; y += ele.offsetTop; ele = ele.offsetParent; } var maxScroll = getScrollMaxXY(); targetX = Math.min(x, maxScroll.x); targetY = Math.min(y, maxScroll.y) - plusY;//追加部分 targetHash = hash; // スクロール停止中ならスクロール開始 if(!scrolling){ scrolling = true; scroll(); } } function scroll(){ var currentX = d.documentElement.scrollLeft||d.body.scrollLeft; var currentY = d.documentElement.scrollTop||d.body.scrollTop; var vx = (targetX - currentX) * easing; var vy = (targetY - currentY) * easing; var nextX = currentX + vx; var nextY = currentY + vy; if((Math.abs(vx) < 1 && Math.abs(vy) < 1) || (prevX === currentX && prevY === currentY)){ // 目標座標付近に到達していたら終了 scrollTo(targetX, targetY); scrolling = false; //location.hash = targetHash;//追加部分 prevX = prevY = null; return; }else{ // 繰り返し scrollTo(parseInt(nextX), parseInt(nextY)); prevX = currentX; prevY = currentY; setTimeout(function(){scroll()},interval); } } function getDocumentSize(){ return {width:Math.max(document.body.scrollWidth, document.documentElement.scrollWidth), height:Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)}; } function getWindowSize(){ var result = {}; if(window.innerWidth){ var box = d.createElement('div'); with(box.style){ position = 'absolute'; top = '0px'; left = '0px'; width = '100%'; height = '100%'; margin = '0px'; padding = '0px'; border = 'none'; visibility = 'hidden'; } d.body.appendChild(box); var width = box.offsetWidth; var height = box.offsetHeight; d.body.removeChild(box); result = {width:width, height:height}; }else{ result = {width:d.documentElement.clientWidth || d.body.clientWidth, height:d.documentElement.clientHeight || d.body.clientHeight}; } return result; } function getScrollMaxXY() { if(window.scrollMaxX && window.scrollMaxY){ return {x:window.scrollMaxX, y:window.scrollMaxY}; } var documentSize = getDocumentSize(); var windowSize = getWindowSize(); return {x:documentSize.width - windowSize.width, y:documentSize.height - windowSize.height}; } }());
「//追加部分」と書いていある三箇所を直すとできました!
最初の「 var plusY = 110;//追加部分 」の数字110は、固定したヘッダーの高さ「110px」を表します。
お好きに替えるだけでカスタマイズできますね。。。!!!
新しく改良されたscrollsmartly.jsが出てる!
元祖KAZUMiXさまのjsですが、リンク切れになっていました。。。。
けれど!
GitHubに追加改善をしてくれたjsが出ていました・・・!
なんかいろいろすごくなってるみたい・・・・・・・
今度はこれを使ってみよう^^