【问题标题】:Fullscreen, resizable canvas in Elm not visible on page loadElm 中的全屏、可调整大小的画布在页面加载时不可见
【发布时间】:2019-09-22 21:36:41
【问题描述】:

我正在使用 Elm 0.19 和 joakin/elm-canvas 包。

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

这是显示问题的有效 Ellie 代码/演示的链接:https://ellie-app.com/6JZDxnQWPLSa1 注意在按键事件触发更新之前屏幕是空白的,然后画布出现。

编辑:添加来自 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 ]
            ]
        ]

【问题讨论】:

  • 好点。我附上了我链接的 Ellie 演示中的代码。
  • 谢谢。不过有趣的问题。我看起来像 joakin/elm-canvas 中的错误。我建议将screen 设为Maybe,而不是最初使用任意值。这最初解决了这个问题,但是当你调整大小时它会再次清除屏幕。当屏幕调整大小时,它可能会强制重新渲染它,但这会增加一些混乱。我建议改为在 github repo 上打开一个问题。

标签: html5-canvas elm


【解决方案1】:

这里是一个工作示例:https://ellie-app.com/6KrhJjGLwc5a1。它有点闪烁,但画布会在调整大小时进行调整。 This post 帮我找到了这个解决方法。

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

【讨论】:

  • 绝对是解决这个问题的好方法。我已经在 GitHub 上提交了这个问题,因为正如 @glennsl 所说,这似乎是包的问题。
  • 对我来说,这更像是一个同步问题,而不是一个包问题。看,有一些延迟,框架显示得很好。有兴趣的可以在 GitHub 上here the link to the thread
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 2012-08-30
  • 1970-01-01
  • 2010-12-30
  • 1970-01-01
  • 2014-11-01
相关资源
最近更新 更多