/**
 * 本模块负责添加分段进度条
 */ /**
 * 本模块负责添加分段进度条
 */ ( function ( ) { class SegProgress { static cssInited = false ; constructor ( resp ) { if ( ! resp . data . view_points || resp . data . view_points . length == 0 ) return ; this . init ( resp . data . view_points ) ; } async init ( view_points ) { if ( ! SegProgress . cssInited ) { SegProgress . cssInited = true ; API . addCss ( `
                            .bilibili-progress-segmentation-logo{display:inline-block;position:absolute;top:-12px;height:30px;width:1px}
                            .bilibili-progress-segmentation-logo>img{position: absolute;top:-14px;transform:translate(-50%,-50%) scale(0.7);left:50%;transition:top 0.1s}
                            .bilibili-player.mode-widescreen .bilibili-progress-segmentation-logo>img,
                            .bilibili-player.mode-webfullscreen .bilibili-progress-segmentation-logo>img,
                            .bilibili-player.mode-fullscreen .bilibili-progress-segmentation-logo>img{top:-18px;left:50%;transform:translate(-50%,-50%) scale(1)}
                            .bilibili-progress-segmentation-logo.active>img#segmentation-logo{top:-110px}
                            .bilibili-progress-segmentation{height:29px;position:absolute;top:-12px}
                            .bilibili-progress-segmentation:hover > div > div{border-color:#fb7299;border-style:solid;border-width:0 2px;width:100%;height:3px;top:6px;left:-2px;position:relative;background:#fb7299}
                            .bilibili-progress-segmentation > div{box-sizing:border-box;border-style:solid;border-color:#fb7299;border-left-width:2px;position:absolute;width:100%;height:6px;top:12px}
                            .bilibili-progress-detail-chapter{top:-96px;position:absolute;width:100%;font-size:17px;font-weight:bold;color:#fff;text-shadow:0 0 5px #000}
                            .bilibili-progress-segmentation:last-child > div{border-right-width:2px}
                            .bilibili-player-filter-chapter:hover{color:#00a1d6}
                            .bilibili-player-chapterList{position:relative;height:100%;width:100%;overflow:auto}
                            .bilibili-player-chapterList::-webkit-scrollbar{width:6px}
                            .bilibili-player-chapterList::-webkit-scrollbar-track{border-radius:4px;background-color:#fff}
                            .bilibili-player-chapterList::-webkit-scrollbar-thumb{border-radius:4px;background-color:#fff}
                            .bilibili-player-chapterList:hover::-webkit-scrollbar-track{background-color:#edf2f9}
                            .bilibili-player-chapterList:hover::-webkit-scrollbar-thumb{background-color:#a2a2a2}
                            .bilibili-player-chapter-info{width:100%;height:72px;margin-top:5px;white-space:normal;font-size:14px;position:relative;cursor:pointer}
                            .bilibili-player-chapter-info > img{position:absolute;left:15px;top:4px;border-radius:2px}
                            .bilibili-player-chapter-info > p{padding-top:5px;margin:0 5px 5px 138px;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:3;height:43px}
                            .bilibili-player-chapter-info:hover > p{color:#00a1d6}
                            .bilibili-player-chapter-info > span{color:#99a2aa}
                            .bilibili-player-chapter-info.active{background-color:#f3f3f3}` ) ; } let sliderTracker = < HTMLDivElement > document . querySelector ( ".bilibili-player-video-progress .bpui-slider-tracker" ) ; let sliderBar = < HTMLElement > document . getElementsByClassName ( "bilibili-player-video-progress-bar" ) [ 0 ] ; let handleWidth = document . getElementsByClassName ( "bpui-slider-handle" ) [ 0 ] . clientWidth ; let trackerWrp = < HTMLElement > document . getElementsByClassName ( "bpui-slider-tracker-wrp" ) [ 0 ] ; let videoDuration = ( < any > window ) . player . getDuration ( ) ; let chptName = document . createElement ( "div" ) ; chptName . className = "bilibili-progress-detail-chapter" ; ( < HTMLDivElement > document . querySelector ( ".bilibili-player-video-progress-detail" ) ) . appendChild ( chptName ) ; let type = view_points [ 0 ] . type ; let segDivs = [ ] ; for ( let v of view_points ) { let seg = document . createElement ( "div" ) ; if ( type == "1" ) { seg . className = "bilibili-progress-segmentation-logo" ; let title = document . createElement ( "div" ) ; title . innerHTML = "-> " + v . content ; title . className = "bilibili-progress-detail-chapter" ; title . style . cssText = "width: auto; transform: translateX(-50%); display: none" ; let img = < HTMLImageElement > document . createElement ( "img" ) ; img . id = "segmentation-logo" ; img . width = 32 ; img . height = 36 ; img . src = v . logoUrl ; img . addEventListener ( "mousemove" , e => e . stopPropagation ( ) ) ; img . addEventListener ( "mouseenter" , ( ) => { title . style . display = "" ; img . style . zIndex = "1000" ; } ) ; img . addEventListener ( "mouseleave" , ( ) => { title . style . display = "none" ; img . style . zIndex = "" ; } ) ; img . addEventListener ( "click" , ( ) => ( < any > window . player ) . seek ( v . from ) ) ; seg . appendChild ( title ) ; seg . appendChild ( img ) ; } else if ( type == "2" ) { seg . className = "bilibili-progress-segmentation" ; let duration = view_points [ view_points . length - 1 ] . to ; let ratio = videoDuration / duration / duration ; seg . style . width = ( v . to - v . from ) * ratio * 100 + "%" ; seg . style . left = v . from * ratio * 100 + "%" ; seg . innerHTML = "<div><div></div></div>" ; seg . onmouseenter = ( ) => chptName . innerHTML = v . content ; } segDivs . push ( seg ) ; sliderTracker . appendChild ( seg ) ; } if ( type == "1" ) { function update ( ) { for ( let i = 0 ; i < segDivs . length ; i ++ ) { segDivs [ i ] . style . left = view_points [ i ] . to / videoDuration * ( trackerWrp . clientWidth - handleWidth ) + handleWidth / 2 + "px" ; } } setTimeout ( ( ) => update ( ) , 500 ) ; chptName . style . top = "-140px" ; trackerWrp . addEventListener ( "mousemove" , e => { let closestPoint = 1e6 ; let box = sliderBar . getBoundingClientRect ( ) ; let pos = ( e . pageX - ( box . left + window . scrollX - document . body . clientLeft ) - handleWidth / 2 ) / ( trackerWrp . clientWidth - handleWidth ) * videoDuration ; 0 > pos && ( pos = 0 ) ; pos > videoDuration && ( pos = videoDuration ) ; let thumbnailArea = 80 / ( trackerWrp . clientWidth - handleWidth ) * videoDuration ; let hitArea = trackerWrp . clientWidth > 400 ? thumbnailArea / 10 : thumbnailArea / 20 ; for ( let i = 0 ; i < view_points . length ; i ++ ) { segDivs [ i ] . style . zIndex = "" ; if ( view_points [ i ] . to >= pos - thumbnailArea && view_points [ i ] . to <= pos + thumbnailArea ) { segDivs [ i ] . className = "bilibili-progress-segmentation-logo active" ; if ( view_points [ i ] . to >= pos - hitArea && view_points [ i ] . to <= pos + hitArea && Math . abs ( view_points [ i ] . to - pos ) < closestPoint ) { chptName . innerHTML = view_points [ i ] . content ; closestPoint = Math . abs ( view_points [ i ] . to - pos ) ; segDivs [ i ] . style . zIndex = "1000" ; } } else { segDivs [ i ] . className = "bilibili-progress-segmentation-logo" ; } } if ( closestPoint == 1e6 ) chptName . innerHTML = "" ; } ) ; ( < any > window ) . player . addEventListener ( "video_player_resize" , ( ) => update ( ) ) ; trackerWrp . addEventListener ( "mouseleave" , ( ) => { for ( let i = 0 ; i < view_points . length ; i ++ ) { segDivs [ i ] . className = "bilibili-progress-segmentation-logo" ; } } ) ; } let wrapList = < HTMLDivElement > document . querySelector ( "div.bilibili-player-wraplist" ) ; let panels = wrapList . children ; let chptInfo = null ; let chptPanel = document . createElement ( "div" ) ; chptPanel . style . display = "none" ; chptPanel . className = "bilibili-player-filter-wrap bilibili-player-chapterList" ; wrapList . appendChild ( chptPanel ) ; let chptBtn = document . createElement ( "div" ) ; chptBtn . className = "bilibili-player-filter-btn bilibili-player-filter-chapter bpui-component bpui-button bpui-button-type-small button" ; chptBtn . innerHTML = '<span class="bpui-button-text"><span>视频看点</span></span>' ; ( < any > document . querySelector ( "div.bilibili-player-filter" ) ) . appendChild ( chptBtn ) ; function refreshState ( ) { if ( ! chptInfo ) return ; let progress = ( < any > window ) . player . getCurrentTime ( ) ; for ( let i = 0 , v ; i < view_points . length ; i ++ ) { v = view_points [ i ] ; if ( progress < v . to ) { let active = document . querySelector ( ".bilibili-player-chapter-info.active" ) ; active && active . classList . remove ( "active" ) ; chptInfo [ i ] . classList . add ( "active" ) ; break ; } } } let timeFormat = ( t ) => t < 10 ? "0" + t : t ; chptBtn . onclick = ( ) => { let activePanel = < HTMLDivElement > document . querySelector ( "div.bilibili-player-filter-btn.active" ) ; if ( activePanel == chptBtn ) return ; activePanel . classList . remove ( "active" ) ; chptBtn . classList . add ( "active" ) ; for ( let i = 0 ; i < panels . length ; i ++ ) { const element = < HTMLDivElement > panels [ i ] ; if ( element . style . display == "block" ) { element . style . display = "none" ; break ; } } if ( ! chptInfo ) { chptInfo = [ ] ; for ( let i = 0 , v ; i < view_points . length ; i ++ ) { v = view_points [ i ] ; let dura = v . to - v . from ; let div = document . createElement ( "div" ) ; div . className = "bilibili-player-chapter-info" ; div . innerHTML = `<img width="112" height="63" src="${ v . imgUrl }"/>
                                        <p class="chapter-name">${ v . content }</p>
                                        <span style="margin-left: 138px">${ timeFormat ( Math . floor ( v . from / 60 ) ) }:${ timeFormat ( v . from % 60 ) }</span>
                                        <span style="margin-right: 5px; float: right;">${ dura >= 60 ? `${ Math . floor ( dura / 60 ) }分` : "" }${ dura > 0 ? `${ dura % 60 }秒` : "" }</span>` ; div . onclick = ( jumpto => ( ) => { ( < any > window ) . player . seek ( jumpto ) ; let active = document . querySelector ( ".bilibili-player-chapter-info.active" ) ; active && active . classList . remove ( "active" ) ; div . classList . add ( "active" ) ; } ) ( v . from ) ; chptInfo [ i ] = div ; chptPanel . appendChild ( div ) ; } } ; chptPanel . style . display = "block" ; refreshState ( ) ; } ; ( < any > window ) . player . addEventListener ( "video_media_seeked" , refreshState ) ; chptPanel . onmouseenter = refreshState ; class timer { static handle : any ; static start ( ) { if ( ! timer . handle ) timer . handle = setInterval ( refreshState , 3000 ) ; } static stop ( ) { if ( timer . handle ) { clearInterval ( timer . handle ) ; timer . handle = null ; } } } ( < any > window ) . player . addEventListener ( "video_media_playing" , timer . start ) ; ( < any > window ) . player . addEventListener ( "video_media_pause" , timer . stop ) ; if ( ( < any > window ) . player . getState ( ) == "PLAYING" ) timer . start ( ) ; } } API . segProgress = ( data ) => { try { new SegProgress ( data ) ; } catch ( e ) { toast . error ( "segProgress.js" , e ) ; } } ; } ) ( ) ; declare namespace API { param data function segProgress ( data ) ; }