iT邦幫忙

1

各位前輩好

我上次才問過https://ithelp.ithome.com.tw/questions/10195025

感謝大大的解釋後我有再研究

但研究到一半

主管後來說不要使用套件....

然後我努力嘗試自行寫滾動事件

一開始找到判別往上往下的方式

var lastscrollTop = 0;

 $(".container1").scroll(function () {
     var currentScrollPosition = $(this).scrollTop();//滾動的高度
     if (currentScrollPosition > lastscrollTop) {
         console.log("往下");
     } else {
         console.log("往上");
     }
     lastscrollTop = currentScrollPosition;

     if(lastscrollTop === 0){
         console.log("到頂了");
     }
     if (lastscrollTop === max_num_li * 700) {
         console.log("到底了");
     }
});

這樣的判斷是可以的
但就在我想要加入滾動效果時

var lastscrollTop = 0;

$(".container1").scroll(function () {
    var currentScrollPosition = $(this).scrollTop();//滾動的高度
    if (currentScrollPosition > lastscrollTop) {
       console.log("往下");
       $(".container1").animate({scrollTop:($(".container1").scrollTop() + 700)},500);
    } else {
        console.log("往上");
        //$(".container1").animate({scrollTop:($(".container1").scrollTop() - 700)},500);
    }
    lastscrollTop = currentScrollPosition;
    if(lastscrollTop === 0){
        console.log("到頂了");
    }
    if (lastscrollTop === max_num_li * 700) {
        console.log("到底了");
    }
});

這樣的情形就變成的確第一次滾動會往下700
然後他就失控的不停緩慢往下
往上還不能使用呢/images/emoticon/emoticon10.gif

後來跟主管求救討教後,他給我這段

var lastscrollTop = 0;
$(".container1").scroll(function () {
    var currentScrollPosition = $(this).scrollTop();//滾動的高度
    if (currentScrollPosition > lastscrollTop) {
        console.log("往下");
        lastscrollTop = currentScrollPosition+700;
        $(".container1").animate({scrollTop:lastscrollTop},500);
    } else {
        console.log("往上");
    }
        //lastscrollTop = currentScrollPosition;
    if(lastscrollTop === 0){
        console.log("到頂了");
    };
    if (lastscrollTop === max_num_li * 700) {
        console.log("到底了");
    };
});

就瀟灑離去~~~

結果發現還是失敗的!!!!/images/emoticon/emoticon04.gif

其實開始滑動時都正常

但當我打開console.log看時
發現他一次往下後跳超多往上
https://ithelp.ithome.com.tw/upload/images/20190904/20113556cjanPJOG1O.jpg

然後上面的選單是跳錨點
切換錨點後
有時候會出現自動往下一頁的情形(下圖中按P6時跳到最後一張大圖區)
有時候則是往下滑動一頁的效果失敗(變成正常滑鼠滾動)
實測如下
https://imgur.com/2xvg7Bd

最終主管的方式也是錯誤的/images/emoticon/emoticon16.gif

請問各位大大該怎麼做呢?

codepen

再拜託各位大大賜教拯救了

謝謝各位

0
firecold
iT邦新手 4 級 ‧ 2019-09-04 15:26:47

雖然說多學沒有壞處
codepen不能用

看了範例影片後
你要不要考慮用html錨點阿?

okaybeok iT邦新手 5 級 ‧ 2019-09-04 15:37:37 檢舉

firecold大您好

codepen我自己測點擊連結
是可以的唷
附上連結
https://codepen.io/Okaybeok/pen/pozWLXv

html錨點我是下在上面選單列
點擊就會跳區域
(XXX表示沒有下的,用不到)

主要是要滑鼠滾動時動作
所以不太明白您說考慮用html錨點是什麼意思呢?
再麻煩賜教~

謝謝你

firecold iT邦新手 4 級 ‧ 2019-09-04 16:40:54 檢舉

我看到 你有寫使用了錨點了
只是要加上動畫
抱歉一開始沒看到

okaybeok iT邦新手 5 級 ‧ 2019-09-05 15:10:42 檢舉

沒關係的!
謝謝你的回覆唷

3
浩瀚星空
iT邦大師 1 級 ‧ 2019-09-04 16:10:53

給你一個思考的點。

$(".container1").animate({scrollTop:lastscrollTop},500);

這一段運行時,會不會去跑scroll事件呢??
其實答案是肯定的。

所以,做法其實很單純。不要讓它去觸發scroll事件就好了。
不過說是這樣說,但要解決是要思考很多東西的。

我個人的解法是不利用scroll來觸動動作,而是啟動動作。
而是將scroll來記錄對應值及啟動對應。
並且會給與一個動作開關。

當效果還沒完成之前,任何一個scroll動作都不會再去觸發效果動作。
除非效果已經完成了。

大約是上面給你參考。
附註一提,其實animate動作是可以偵測是否已經完成了。去找找看吧。

你的問題其實就是很單純的重覆觸發動作。

2
dragonH
iT邦大師 4 級 ‧ 2019-09-04 21:24:05

codepen

主要的邏輯就是

把 container1 的 scroll 停用

全部交給 js 控制

其實上次應該就要這樣做了

然後 menu 那邊

添加 click listener

根據點擊的項目

更改 n 值

這樣也就不會亂跳了

應該是沒啥問題

有問題就...

再說吧/images/emoticon/emoticon11.gif

okaybeok iT邦新手 5 級 ‧ 2019-09-05 15:10:17 檢舉

dragonH大大
真的十分感謝你的協助
感覺該請你喝杯咖啡或餐點
/images/emoticon/emoticon02.gif

經過您的解釋和上方浩瀚星空大的
覺得這次比較好懂呢

小妹在此想請教大大,也確認我是不是理解正確
錯誤的話再麻煩大大指教

 var moving = false;

這個是上方浩瀚星空大所指的開關嗎?

    $(".container1").on('mousewheel DOMMouseScroll', function (e) {
    if (moving) {
        return;
    }
    moving = true;
    console.log(moving);
    setTimeout(function () {
        var down = e.originalEvent.deltaY > 0;
         if (down && n === num_li) {
             moving = false;
             return;
         }
         if (!down && n === 1) {
             moving = false;
             return;
         }
         n += down ? 1 : -1;
         console.log(n);
    $(".container1").animate({ scrollTop: $(".container1").scrollTop() + $(".p0" + n).position().top }, 500, function () {
        moving = false;
        console.log(moving);
        });
    }, 0);
});

請問這邊使用setTimeout是否就是在阻止他重複觸發?
然後下方內容是根據事件的deltaY是正還負判斷他是往下還是往上;
下面兩個if判斷是判斷是否到頂或到底然後停止滾動事件
下方就是滾動到定點

$('.menu_li').click(function(e) {
      const targets = ['#first_video', '#popular_video', '#about_program', '#host_s', '', '', '#staff_team'];
      const to = $(this).children('a').attr('href');
      const position = targets.indexOf(to)
      if (position) {
        n = position + 1;
      }
    });

這段是在選單下click事件
targets是我頁面上有的id
請問這個id順序會有影響嗎?

to是點到那個li下的a連結目標

const position = targets.indexOf(to)
      if (position) {
        n = position + 1;
      }

但這段就有點...不確定是什麼了
在targets陣列中尋找第一個被找到之a連結目標

下面的if代表什麼呢?
也請問這個n為什麼要+1呢?

此外,
我有注意到若是點選到其他頁面(那個XXX的連結若是其他頁面,非此頁面)再跳回來,點到頁面後滾動,就會亂跳了
(codepen好像無法展示)

請問是什麼原因呢?
有辦法解決嗎?/images/emoticon/emoticon06.gif

抱歉我的問題比較多,/images/emoticon/emoticon20.gif

謝謝您總撥空幫忙解決問題!!/images/emoticon/emoticon02.gif

dragonH iT邦大師 4 級 ‧ 2019-09-05 15:25:43 檢舉

okaybeok

var moving = false;
這個是上方浩瀚星空大所指的開關嗎?

而且如果你回去看你之前參考的那個

會發現他早就存在你的 code

請問這邊使用setTimeout是否就是在阻止他重複觸發?

原本我是想用 setTimeout 來達到 delay 的效果

不過後來看起來是不需要

可以直接拿掉

然後下方內容是根據事件的deltaY是正還負判斷他是往下還是往上;
下面兩個if判斷是判斷是否到頂或到底然後停止滾動事件
下方就是滾動到定點

這段是在選單下click事件
targets是我頁面上有的id
請問這個id順序會有影響嗎?

我 codepen 那部分只是示範而已

因為你好像沒有menu沒有全部的錨點

主要的邏輯就是

當你點上方 menu 到 p03

就把 n 設成 3

const position = targets.indexOf(to)
if (position) {
n = position + 1;
}

indexof 的功能在於 取得元素(to) 在陣列(targets) 的位置

不在陣列中

會回傳 -1

if (position) 的目的是在於確保他在陣列中

+1 的目的是因為他回傳的是在陣列中的位置

也就是從 0 開始

所以需要 +1

我有注意到若是點選到其他頁面(那個XXX的連結若是其他頁面,非此頁面)再跳回來,點到頁面後滾動,就會亂跳了

亂跳的原因是因為

你重新進到這個頁面

n 會被初始化成 1

但你目前的位置不一定在 p01

所以就會亂跳

三個解法

1 .

當 user 到你這個網頁

直接把他 scroll 到最上方

2 .

網頁會紀錄你的位置

主要是因為 web 的 history api

所以你可以試試照著他的做看有沒用

if ('scrollRestoration' in history) {
  // Back off, browser, I got this...
  history.scrollRestoration = 'manual';
}

3 .

在一進到這頁面時

檢查 url 後面是否帶著 #XXXXXXX

再根據這個

重新設定 n 的值

方法很多

我要發表回答

立即登入回答