Html5 canvas Elm中的全屏、可调整大小的画布在页面加载时不可见

Html5 canvas Elm中的全屏、可调整大小的画布在页面加载时不可见,html5-canvas,elm,Html5 Canvas,Elm,我使用的是Elm 0.19和包 我所要做的就是画一幅画布,它横跨整个屏幕的宽度和高度,并随着窗口大小的变化而动态调整大小。我花了几个小时调试和研究,但我只是卡住了。我已经尝试了多种实现,我可以让它工作,但不是在初始页面加载时。相反,它仅在调用update函数后呈现。我觉得我错过了一些明显的东西,因为我对Elm还是很陌生 以下是显示问题的Ellie代码/演示的链接: 注意屏幕是如何空白的,直到一个按键事件触发更新,然后画布出现 编辑:添加来自Ellie演示的代码 module Main expos

我使用的是Elm 0.19和包

我所要做的就是画一幅画布,它横跨整个屏幕的宽度和高度,并随着窗口大小的变化而动态调整大小。我花了几个小时调试和研究,但我只是卡住了。我已经尝试了多种实现,我可以让它工作,但不是在初始页面加载时。相反,它仅在调用update函数后呈现。我觉得我错过了一些明显的东西,因为我对Elm还是很陌生

以下是显示问题的Ellie代码/演示的链接: 注意屏幕是如何空白的,直到一个按键事件触发更新,然后画布出现

编辑:添加来自Ellie演示的代码

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 ]
            ]
        ]

这里有一个工作示例:。它有点闪烁,但画布在调整大小时进行了调整。帮助我找到了很多解决方法

我在模型中添加了一个
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
    )

说得好。我已经附上了我链接的Ellie演示的代码。谢谢。不过这是个有趣的问题。我看起来像若金/榆树画布上的一只虫子。我建议将
screen
a
设置为可能的
,而不是最初使用任意值。这解决了最初的问题,但它会清除屏幕上再次调整大小。当屏幕调整大小时,完全强制重新播放可能会奏效,但这会增加一点混乱。我建议改为在github回购协议上发行一个问题。这绝对是解决这个问题的好办法。我已经在GitHub上提交了这个问题,因为正如@glennsl所说的,这似乎是软件包的问题。对我来说,这更像是一个同步问题,而不是软件包问题。看,经过一些延迟,画面显示得很好。对于感兴趣的人,请访问GitHub。