如何知道滚动条是否位于元素的底部

时间:2016-12-16 03:36:36

标签: elm onscroll

有没有办法知道滚动条是否位于Elm元素的底部?我在添加列表项时使用Dom.Scroll.toBottom滚动到列表的底部。单独离开时效果很好。但是如果你手动向上滚动一点,我不想再自动向下滚动到底部(直到你再次手动滚动到底部)。否则,您无法查看以前的列表项。

1 个答案:

答案 0 :(得分:1)

我可以使用以下代码获取clientHeightscrollHeightscrollTop属性。那些必须知道滚动是否在元素的底部。其余代码仅在滚动已经位于底部时才实现自动滚动的机制:

type alias Model =
    { messages : List Message
    , autoScrollMessages : Bool
    }

type Msg
    = NoOp (Result Dom.Error ())
    | ReceiveMessage ReceivedMessage
    | ScrolledMessages ScrollEvent

update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        NoOp res ->
            ( model, Cmd.none )
        ReceiveMessage message ->
            ( { model | messages = model.messages ++ [ message ] } , if model.autoScrollMessages then Task.attempt NoOp (Scroll.toBottom "messages") else Cmd.none )
        ScrolledMessages scrollEvent ->
            ( { model | autoScrollMessages = scrollEvent.scrollPos == scrollEvent.scrollHeight - scrollEvent.visibleHeight }, Cmd.none )

type alias ScrollEvent =
  { scrollHeight : Int
  , scrollPos : Int
  , visibleHeight : Int
  }

onScroll : (ScrollEvent -> msg) -> Html.Attribute msg
onScroll tagger =
  Html.Events.on "scroll" (Decode.map tagger onScrollJsonParser)

onScrollJsonParser : Decode.Decoder ScrollEvent
onScrollJsonParser =
  Decode.map3 ScrollEvent
      (Decode.at ["target", "scrollHeight"] Decode.int)
      (Decode.at ["target", "scrollTop"] Decode.int)
      (Decode.at ["target", "clientHeight"] Decode.int)

viewMessages : List Message -> Html Msg
viewMessages messages =
    ul
        [ id "messages"
        , onScroll ScrolledMessages
        ] <| List.map viewMessage messages