Полноэкранный, изменяемый размер холста в Elm не виден при загрузке страницы - PullRequest
1 голос
/ 23 сентября 2019

Я использую Elm 0.19 и пакет joakin / elm-canvas .

Все, что я пытаюсь сделать, это нарисовать холст, который охватывает всю ширину и высотуэкран и динамически изменяет размеры при изменении размера окна.Я потратил несколько часов на отладку и исследование, но я просто застрял.Я пробовал несколько реализаций, и я могу заставить его работать, но не при начальной загрузке страницы.Вместо этого он рендерится только после вызова функции update.Я чувствую, что упускаю что-то очевидное, поскольку я все еще очень плохо знаком с Elm.

Вот ссылка на рабочий код / ​​демонстрацию Элли, показывающая проблему: https://ellie -app.com/ 6JZDxnQWPLSa1 Обратите внимание на то, что экран пуст, пока после нажатия клавиши не произойдет обновление, а затем не появится холст.

Редактировать: добавление кода из демонстрации Элли.

module Main exposing (..)

import Browser
import Browser.Dom exposing (Viewport, getViewport)
import Browser.Events exposing (onKeyDown, onResize)
import Canvas exposing (..)
import Canvas.Settings exposing (..)
import Canvas.Settings.Advanced exposing (..)
import Color
import Html exposing (Html, div)
import Html.Attributes exposing (style)
import Json.Decode as Decode
import Task


main : Program () Model Msg
main =
    Browser.element
        { init = init
        , view = view
        , subscriptions = subscriptions
        , update = update
        }


-- MODEL


type alias Model =
    { screen : { width : Int, height : Int }
    }


init : () -> ( Model, Cmd Msg )
init _ =
    ( { screen = { width = 800, height = 600 }
      }
    , Task.perform (\{ viewport } -> ScreenSize (round viewport.width) (round viewport.height)) getViewport
    )


-- UPDATE


type Msg
    = TurnLeft
    | TurnRight
    | MoveForward
    | Other
    | ScreenSize Int Int


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        TurnLeft ->
            ( model, Cmd.none )

        TurnRight ->
            ( model, Cmd.none )

        MoveForward ->
            ( model, Cmd.none )

        ScreenSize w h ->
            ( { model | screen = { width = w, height = h } }
            , Cmd.none
            )

        Other ->
            ( model, Cmd.none )


-- SUBSCRIPTIONS


subscriptions : Model -> Sub Msg
subscriptions model =
    Sub.batch
        [ onKeyDown keyDecoder
        , onResize ScreenSize
        ]


keyDecoder : Decode.Decoder Msg
keyDecoder =
    Decode.map toDirection (Decode.field "key" Decode.string)


toDirection : String -> Msg
toDirection string =
    case string of
        "ArrowLeft" ->
            TurnLeft

        "ArrowRight" ->
            TurnRight

        "ArrowUp" ->
            MoveForward

        _ ->
            Other


-- VIEW


clearScreen : Float -> Float -> Renderable
clearScreen width height =
    shapes [ fill Color.black ] [ rect ( 0, 0 ) width height ]


view : Model -> Html Msg
view { screen } =
    div
        [ style "display" "flex"
        , style "justify-content" "center"
        , style "align-items" "center"
        ]
        [ Canvas.toHtml
            ( screen.width, screen.height )
            []
            [ clearScreen (toFloat screen.width) (toFloat screen.height)
              , shapes [ fill Color.red ] [ rect ( 30, 30 ) 200 200 ]
            ]
        ]

1 Ответ

1 голос
/ 23 сентября 2019

Вот рабочий пример: https://ellie -app.com / 6KrhJjGLwc5a1 .Он немного мигает, но холст настроен на изменение размера. Этот пост очень помог мне найти этот обходной путь.

Я добавил busy реквизит для модели:

type alias Model =
    { screen : { width : Int, height : Int }
    , busy : Bool
    }

и добавил PostScreenSizeпринудительно перезагрузить представление после выполнения ScreenSize:

ScreenSize w h ->
    ( { model | screen = { width = w, height = h }, busy = True }
    , delay PostScreenSize
    )

PostScreenSize ->
    ( { model | busy = False }
    , Cmd.none
    )
...