Elm:获取图像大小

7

我想获取一张图片的宽度和高度,给定一个URL,请问这张图片的宽度和高度是多少?


1
怎么尝试?您能否在问题中添加 [mcve]? - Robert Longson
我不太确定该如何开始,我想也许我的问题更多的是如何在 Elm 中获取图像的大小。在 JavaScript 中,我可以创建一个 Image() 元素并设置其 URL,然后在 onload 事件中读取其宽度和高度。在 Elm 中,我该如何做类似的事情而不需要导出到 JavaScript? - Anis Jonischkeit
你是在使用 Elm 来定位浏览器吗?如果是这样,或许可以以某种方式使用/适应这项技术(我是一个 Elm 新手):https://dev59.com/bHRB5IYBdhLWcg3wcm2d - Eljay
2个回答

8
我不认为在 Elm 中有一种方法可以做到这一点。端口是其中一种解决方案。你可以在这里了解它们。我已经编写了一个小例子,可以在ellie上运行。在这个例子中,我使用了你在评论中提供的 JS 示例,但还有其他可能的解决方案,比如事件监听器或查询 DOM。
port module Main exposing (main)

import Html exposing (..)
import Html.Attributes exposing (..)


main : Program Never Model Msg
main =
    Html.program
        { init = init
        , update = update
        , view = view
        , subscriptions = subscriptions
        }


type alias Model =
    { imageUrl : String
    , dim : Maybe ( Int, Int )
    }


testImg : String
testImg =
    "https://images-na.ssl-images-amazon.com/images/I/71TcaVWvBsL._SY355_.jpg"


init : ( Model, Cmd msg )
init =
    Model testImg Nothing
        ! [ getDim testImg ]


type Msg
    = UpdateDim ( Int, Int )


update : Msg -> Model -> ( Model, Cmd msg )
update msg model =
    case msg of
        UpdateDim xy ->
            { model | dim = Just xy } ! []


view : Model -> Html msg
view model =
    case model.dim of
        Nothing ->
            div [] []

        Just dims ->
            div []
                [ img [ src model.imageUrl ] []
                , text <|
                    "size: "
                        ++ toString dims
                ]


subscriptions : Model -> Sub Msg
subscriptions model =
    newDim UpdateDim

-- this port handles our incomming height and width
-- and passes it to a Msg constructor
port newDim : (( Int, Int ) -> msg) -> Sub msg

-- this port passes our string out of Elm and into
-- js land
port getDim : String -> Cmd msg

index.html

<html>
<head>
  <style>
    /* you can style your program here */
  </style>
</head>
<body>
  <script>
    var app = Elm.Main.fullscreen()
    // you can use ports and stuff here
    app.ports.getDim.subscribe(function(url){
      // recieve the url for the image through
      // the `getDim` port in Main.elm
      let img = new Image()
      img.src = url
      img.onload = function() {
        // send the height and width back to elm through
        // the `newDim` port in Main.elm
        app.ports.newDim.send([img.height, img.width])
      }
    })
  </script>
</body>
</html>

2
正如 Slack 中的某位用户指出的那样,如果您打算在 DOM 中显示图像,则可以在 Elm 中附加一个 onload 处理程序,并从中获取大小,因此您不需要使用端口。但是,如果您不想在 DOM 中显示图像,那么您提供的答案是迄今为止我找到的最佳答案。 - Anis Jonischkeit
@AnisJonischkeit 如果提供一些有关那种方法的详细信息,或者至少提供一些指向Slack线程存档的链接,那将非常有帮助作为另一个答案。 - CoderDennis
@CoderDennis,我已经发布了另一个带有此解决方案的答案。 - Anis Jonischkeit

6

我在评论中提到,如果您显示图像,则可以在不使用端口的情况下执行此操作。这就是我所说的解决方案:

module Main exposing (main)

import Browser
import Debug exposing (toString)
import Html exposing (Html, div, img, text)
import Html.Attributes exposing (src)
import Html.Events exposing (on)
import Json.Decode as Decode


type alias Model =
    { imageDimensions : Maybe ImgDimensions }


initialModel : Model
initialModel =
    { imageDimensions = Nothing }


type Msg
    = ImgLoaded ImgDimensions


update : Msg -> Model -> Model
update msg model =
    case msg of
        ImgLoaded dimensions ->
            { model | imageDimensions = Just dimensions }


type alias ImgDimensions =
    { width : Int
    , height : Int
    }


decodeImgLoad msg =
    Decode.map msg <|
        Decode.field "target" <|
            Decode.map2 ImgDimensions
                (Decode.field "width" Decode.int)
                (Decode.field "height" Decode.int)


view : Model -> Html Msg
view model =
    div []
        [ text <| "Image Loaded = " ++ toString model.imageDimensions
        , img
            [ on "load" (decodeImgLoad ImgLoaded)
            , src "https://cloud.netlifyusercontent.com/assets/344dbf88-fdf9-42bb-adb4-46f01eedd629/bd07f82e-a30d-4e93-a2cf-0c16ea2b7f40/08-owl-opt.jpg"
            ]
            []
        ]


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

https://ellie-app.com/3FCdcDqy4gqa1


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接