20.30日30日目:ブラウザの幅と高さを得る


これは私の20日目です
今日、私は何か視覚的なことをしたかったですが、私はSVGは利用可能なスペースを埋めるためにしたかった.
代わりに、ブラウザの幅と高さについての情報を得ることを学ぶ日になりました.
JavaScriptでは、私はinnerWidth and innerHeight . elmでは、それはより難しいです.
このポストには混乱と眠れない眠りが書かれている.
コードデモhttps://ellie-app.com/bZDy65SqXXFa1

目次
  • 1. Getting the browser's width and height
  • 2. Responding to window resize events

  • 3. The code
  • 3.1. Model and Msg
  • 3.2. Main and subscription
  • 3.3. Update
  • 3.4. View
  • 4. Conclusion

  • ブラウザの幅と高さを取得する
    ELM文書の経験は少しイライラしました.説明はしばしば良いです、そして、タイプ注釈は助けます、しかし、ちょうど1か2つのコード例が多くを助けたいくつかの場面がありました.
    例えば、Browser.Dom.getViewport 良い音が、どのように私はそれを使用しますか?そのタイプ注釈は言うTask x Viewport . 見たTask 前述のViewport よく説明されていますが、地球上ではどうですかx ?
    もちろん、私はもっと徹底的にドキュメンテーションを読むべきでした、しかし、ちょうど実用的な例を持っていることはどんなレベルの開発者のためにでもよかったでしょう.
    type aliasは分かりやすいです.
    type alias Viewport =
        { scene :
              { width : Float
              , height : Float
              }
        , viewport :
              { x : Float
              , y : Float
              , width : Float
              , height : Float
              }
        }
    
    しかし、戻そうとするときBrowser.Dom.getViewport.scene 関数で、このエラーを取得します.

    This is not a record, so it has no fields to access!
    23| Browser.Dom.getViewport.scene
    ^^^^^^^^^^^^^^^^^^^^^^^
    This getViewport value is a:
    Task.Task x Browser.Dom.Viewport
    But I need a record with a scene field!


    タイプエイリアスを読んでくれたことをよくお詫びします.
    だから私は読んでTask documentation , そして、時間の例を再訪してくださいTask.perform GetBrowserDimensions Browser.Dom.getViewport , 次のコードを使用します.
    type Msg
        = GetBrowserDimensions
    
    
    dimensions =
        Task.perform GetBrowserDimensions Browser.Dom.getViewport
    
    これは私が以前見た一種のエラーメッセージをもたらしました、しかし、私はまだ少し苦労します.Msg and msg - 良い選択肢はありません.

    28| Task.perform GetBrowserDimensions Browser.Dom.getViewport
    ^^^^^^^^^^^^^^^^^^^^
    This GetBrowserDimensions value is a:
    Msg
    But perform needs the 1st argument to be:
    a -> msg


    私はエルムスラックチャンネルで尋ねました.

    Samuel Kacer 28 minutes ago
    The first argument to Task.perform needs to be a function that will take the result from the Task and wrap it in some kind of message. so for the case of getViewPort, the argument needs to be of type Viewport -> Msg.
    the first argument you are providing, GetBrowserDimensions, is of type Msg, so I assume it doesn't contain anything and has a definition something like this:
    type Msg =
    ...
    | GetBrowserDimensions
    but instead needs to be something like
    | GetBrowserDimensions Viewport
    that way the constructor for that message variant will have a type of Viewport -> Msg, which would fit for the Task you are wanting to perform

    arkham 27 minutes ago
    you can check out this ellie https://ellie-app.com/bZvHnKqpPrCa1


    また、私は窓のリサイズイベントに反応するためにそれを必要としましたonResize documentation 用途Cmd Msg そのタイプとして、私は明らかに私はSub Msg 私の場合は

    Kristian Pedersen 2 hours ago



    ウィンドウリサイズイベントに対する応答

    Actually, I realized I wanted it to update on window resize. Again, I think I’m almost there, but it’s telling me I need a sub msg, not a cmd msg:
    https://ellie-app.com/bZBqjmgPS9pa1
    What also confuses me is that going by the documentation, the subscriptions function returns a cmd msg, but in my example, it need to be a sub msg: https://package.elm-lang.org/packages/elm/browser/latest/Browser-Events#onResize

    arkham 1 hour ago
    hey Pedersen, it’s just the type of the subscription is a Sub Msg instead of a Cmd Msg , so your subscriptions function should be a Sub Msg, here’s a working ellie https://ellie-app.com/bZC6k6dv9wna1

    arkham 1 hour ago
    I also converted the Ints to Floats to get the type checker to be happy

    arkham 1 hour ago
    and here’s a very simple example of a subscription: https://guide.elm-lang.org/effects/time.html

    arkham 1 hour ago
    oh, and to be clear: the documentation is saying that onResize returns a Sub msg https://package.elm-lang.org/packages/elm/browser/latest/Browser-Events#onResize


    助けと忍耐のおかげで、アーカム!あなたは伝説です.

    3 .コード
    すべての混乱と前後に行くと、私の結果コードは、ほとんどかなり正直に見えるように見える.

    3.1 .モデルとMSG
    type alias Model =
        { width : Float, height : Float }
    
    
    initialModel : Model
    initialModel =
        { width = 0, height = 0 }
    
    
    type Msg
        = NoOp
        | GotInitialViewport Viewport
        | Resize ( Float, Float )
    
    モデルはまっすぐ進む.Although GotInitialViewport and Resize 別の、彼らは両方Float s.
    私は、これがどのように見えるか本当に好きでありません.多分それはちょうどそれを介して行うにはクリーナーされているだろうか?

    3.2 .メインとサブスクリプション
    main : Program () Model Msg
    main =
        let
            handleResult v =
                case v of
                    Err err ->
                        NoOp
    
                    Ok vp ->
                        GotInitialViewport vp
        in
        Browser.element
            { init = \_ -> ( initialModel, Task.attempt handleResult Browser.Dom.getViewport )
            , view = view
            , update = update
            , subscriptions = subscriptions
            }
    
    
    subscriptions : model -> Sub Msg
    subscriptions _ =
        E.onResize (\w h -> Resize ( toFloat w, toFloat h ))
    
    それは私が前に見たことと比較してかなりちゃんとした主な機能です.
    タスクhandleResult されて、それはそれらの2つの1つを返しますCmd Msg 年代のslet 文.

    3.3 .更新
    setCurrentDimensions model ( w, h ) =
        { model | width = w, height = h }
    
    
    update : Msg -> Model -> ( Model, Cmd Msg )
    update msg model =
        case msg of
            GotInitialViewport vp ->
                ( setCurrentDimensions model ( vp.scene.width, vp.scene.height ), Cmd.none )
    
            Resize ( w, h ) ->
                ( setCurrentDimensions model ( w, h ), Cmd.none )
    
            NoOp ->
                ( model, Cmd.none )
    
    Cmd.none しかし、私はエルムが私が慣れているより多くの説明を好むことを推測するけれども、それは代わりに暗黙的でありえました.
    それは初心者として私に少し余分なオーバーヘッドを加えます、しかし、私はそれが見ることができると思いますCmd.none 一目で.
    再び、私は私のダブルアプローチが好きではありません、そこで、私は幅と高さ2つの異なる方法を得ますvp 変数、および( w, h ) タプル.それはちょうど間違って感じている.

    3.4 .ビュー
    いくつかのデータを表示するだけです.混乱した日への良い結末
    view : Model -> Html Msg
    view model =
        div []
            [ text
                ("The width is "
                    ++ (model.width |> String.fromFloat)
                    ++ "px, and the height is "
                    ++ (model.height |> String.fromFloat)
                    ++ "px"
                )
            ]
    

    結論
    これは、JavaScript相互運用を通して行うよりも、elmのやり方ですぐに利点を見ることができない場合ですwindow.eventListener .
    私は間違いなく再読み込みする必要がありますBrowser.Dom and Task ドキュメント.
    私も必要なのは良い夜の睡眠です.(お勧めいたします"Why We Sleep" by Matthew Walker )
    私はあまりにも早く目を覚まし、シエスタを持っていなかったと私は私の思考と気分に負の影響に気づいている.私は前に学習フラストレーションを介してされているので、同様にこの1つを取得します.
    あまりにも良い夜の睡眠を取得し、明日参照してください!