▲TOPへ戻る

【javascript】スクロールとともに、どの段落を表示しているか、目次に反映させる方法

スクロールした時に、どの段落を表示させているか、目次に反映させるjavascriptを書いてみました。

  • 第1段落
  • 第2段落
  • 第3段落
  • 第4段落
  • 第5段落
  • 親譲おやゆずりの無鉄砲むてっぽうで小供の時から損ばかりしている。小学校に居る時分学校の二階から飛び降りて一週間ほど腰こしを抜ぬかした事がある。なぜそんな無闇むやみをしたと聞く人があるかも知れぬ。別段深い理由でもない。新築の二階から首を出していたら、同級生の一人が冗談じょうだんに、いくら威張いばっても、そこから飛び降りる事は出来まい。弱虫やーい。と囃はやしたからである。小使こづかいに負ぶさって帰って来た時、おやじが大きな眼めをして二階ぐらいから飛び降りて腰を抜かす奴やつがあるかと云いったから、この次は抜かさずに飛んで見せますと答えた。

    親類のものから西洋製のナイフを貰もらって奇麗きれいな刃はを日に翳かざして、友達ともだちに見せていたら、一人が光る事は光るが切れそうもないと云った。切れぬ事があるか、何でも切ってみせると受け合った。そんなら君の指を切ってみろと注文したから、何だ指ぐらいこの通りだと右の手の親指の甲こうをはすに切り込こんだ。幸さいわいナイフが小さいのと、親指の骨が堅かたかったので、今だに親指は手に付いている。しかし創痕きずあとは死ぬまで消えぬ。

    庭を東へ二十歩に行き尽つくすと、南上がりにいささかばかりの菜園があって、真中まんなかに栗くりの木が一本立っている。これは命より大事な栗だ。実の熟する時分は起き抜けに背戸せどを出て落ちた奴を拾ってきて、学校で食う。菜園の西側が山城屋やましろやという質屋の庭続きで、この質屋に勘太郎かんたろうという十三四の倅せがれが居た。勘太郎は無論弱虫である。弱虫の癖くせに四つ目垣を乗りこえて、栗を盗ぬすみにくる。ある日の夕方折戸おりどの蔭かげに隠かくれて、とうとう勘太郎を捕つらまえてやった。その時勘太郎は逃にげ路みちを失って、一生懸命いっしょうけんめいに飛びかかってきた。向むこうは二つばかり年上である。弱虫だが力は強い。鉢はちの開いた頭を、こっちの胸へ宛あててぐいぐい押おした拍子ひょうしに、勘太郎の頭がすべって、おれの袷あわせの袖そでの中にはいった。邪魔じゃまになって手が使えぬから、無暗に手を振ふったら、袖の中にある勘太郎の頭が、右左へぐらぐら靡なびいた。しまいに苦しがって袖の中から、おれの二の腕うでへ食い付いた。痛かったから勘太郎を垣根へ押しつけておいて、足搦あしがらをかけて向うへ倒たおしてやった。山城屋の地面は菜園より六尺がた低い。勘太郎は四つ目垣を半分崩くずして、自分の領分へ真逆様まっさかさまに落ちて、ぐうと云った。勘太郎が落ちるときに、おれの袷の片袖がもげて、急に手が自由になった。その晩母が山城屋に詫わびに行ったついでに袷の片袖も取り返して来た。

    この外いたずらは大分やった。大工の兼公かねこうと肴屋さかなやの角かくをつれて、茂作もさくの人参畠にんじんばたけをあらした事がある。人参の芽が出揃でそろわぬ処ところへ藁わらが一面に敷しいてあったから、その上で三人が半日相撲すもうをとりつづけに取ったら、人参がみんな踏ふみつぶされてしまった。古川ふるかわの持っている田圃たんぼの井戸いどを埋うめて尻しりを持ち込まれた事もある。太い孟宗もうそうの節を抜いて、深く埋めた中から水が湧わき出て、そこいらの稲いねにみずがかかる仕掛しかけであった。その時分はどんな仕掛か知らぬから、石や棒ぼうちぎれをぎゅうぎゅう井戸の中へ挿さし込んで、水が出なくなったのを見届けて、うちへ帰って飯を食っていたら、古川が真赤まっかになって怒鳴どなり込んで来た。たしか罰金ばっきんを出して済んだようである。

    おやじはちっともおれを可愛かわいがってくれなかった。母は兄ばかり贔屓ひいきにしていた。この兄はやに色が白くって、芝居しばいの真似まねをして女形おんながたになるのが好きだった。おれを見る度にこいつはどうせ碌ろくなものにはならないと、おやじが云った。乱暴で乱暴で行く先が案じられると母が云った。なるほど碌なものにはならない。ご覧の通りの始末である。行く先が案じられたのも無理はない。ただ懲役ちょうえきに行かないで生きているばかりである。

    HTML
     <div class="content">
        <div class="index">
            <li class="para">第1段落</li>
            <li class="para">第2段落</li>
            <li class="para">第3段落</li>
            <li class="para">第4段落</li>
            <li class="para">第5段落</li>
        </div>
        <div class="novel">
            <p>文章省略</p>
            <p>文章省略</p>
            <p>文章省略</p>
            <p>文章省略</p>
            <p>文章省略</p>
        </div>
    </div>
    CSS
        .content{
            display: flex;
            position: relative;
            background: rgb(243, 243, 243);
            padding: 10px;
        }
        .index{
            position: absolute;
            top: 10px;
            width: 120px;
            height: 200px;
            border: 1px solid ;
            padding: 20px;
            text-align: center;
        }
        .index.fixed{        /* クラスのfixedがついた時 */
            position: fixed;
            top: 100px;
        }
        .index li{
            font-size: 1.2em;
        }
        .para.active{       /* 目次にクラスactiveがついた時 */
            color: #fff;
            background: red;
            border-radius: 5px;
        }
        .novel{
            width: 70%;
            margin-left: 150px;
        }
        .novel p{
            text-indent: 1em;
        }
        .novel p.active{    /* 段落にクラスactiveがついた時 */
            font-weight: bold;
        }
    javascript
        const para = document.querySelectorAll(".para");
        const novelP = document.querySelectorAll(".novel p");
        
        window.addEventListener("scroll", function(){
            //目次のあるボックスを指定の位置でクラスを追加する
            const indexDistance = document.querySelector(".content").getBoundingClientRect().top;
            const indexDistanceB = document.querySelector(".content").getBoundingClientRect().bottom;
            if(indexDistance < 100){
                document.querySelector(".index").classList.add("fixed");
            }else if(indexDistance > 200){
                document.querySelector(".index").classList.remove("fixed");
            }
            if(indexDistanceB<350){
                document.querySelector(".index").classList.remove("fixed");
            }
            
            //段落が現れたら、要素にクラスactiveを追加、消えたら削除
            for (let i = 0; i < novelP.length; i++) {
                const novelPDistance = novelP[i].getBoundingClientRect().top;
                if(novelPDistance < 400){
                    novelP[i].classList.add("active");
                    para[i].classList.add("active");
                    if(novelP[i-1]!=null){      //novelP[i-1]が存在したらの場合
                        novelP[i-1].classList.remove("active")
                        para[i-1].classList.remove("active")
                    }
                }else {
                    novelP[i].classList.remove("active");
                    para[i].classList.remove("active");
                }           
            }     
        })

    profile

    パソコン好きなガオ

    コロナ禍によるステイホームを機にプログラミングを学ぶ。パソコンに関してはプロではないが、ちょっと詳しい程度。<