Home > Blockchain >  Canvas not rendering the image in Elm through a port to use a JavasScript image-filtering library (b
Canvas not rendering the image in Elm through a port to use a JavasScript image-filtering library (b

Time:11-28

** here is the view function:**

view : Model -> Html Msg
view model =
    div [ class "content" ]
        [ h1 [] [ text "Islamic art patterns" ]
        , button
            [ class "button"
            , onClick ClickedSurpriseMe
            ]
            [ text "SurpriseMe!" ]
        , div [ class "filters" ]
            [ viewFilter SlidHue "Hue" model.hue
            , viewFilter SlidRipple "Ripple" model.ripple
            , viewFilter SlidNoise "Noise" model.noise
            ]
        , h3 [] [ text "Thumbnail Size:" ]
        , div [ id "choose-size" ] <|
            List.map viewSizeChooser [ Small, Medium, Large ]
        , div [ id "thumbnails", class (sizeToString model.chosenSize) ] <|
            List.map (viewPhoto model.selectedUrl) model.photos
        , img
            [ id "main-canvas"
            , class "large"
            , src model.selectedUrl
            , onClick Tessellate
            , title "Click for Tessellate on/off!"
            ]
            []
        ]

**the port I am using: **

port setFilters : FilterOptions -> Cmd msg


type alias FilterOptions =
    { url : String
    , filters : List { name : String, amount : Int }
    }

the css code in index.html for the img and canvas, and the large class:

 img,canvas {border: 3px solid white; margin: 5px; } 
 .large {width:600px; float: right; cursor: pointer; }

and the JavaScript code in index.html:

<script>
    class RangeSlider extends HTMLElement {
        connectedCallback() {
            var input = document.createElement ("input");
             this.appendChild(input);

                var jsr = new JSR(input, {
                    max: this.max,
                    values: [this.val],
                    sliders: 1, 
                    grid: false
                });

                var rangeSliderNode = this;

                jsr.addEventListener("update", function(elem, value) {
                    var event = new CustomEvent("slide", {
                            detail: {userSlidTo: value}
                    });

                    rangeSliderNode.dispatchEvent(event);
                });
            }
        

    window.customElements.define("range-slider", RangeSlider);
</script>
</head>

<body>
    <div id="app"></div>

    <script src ="http://elm-in-action.com/pasta.js"></script>
    <script src="app.js"></script>
    <script>
         var app = Elm.MyPage.init({node: document.getElementById("app")});

         app.ports.setFilters.subscribe(function(options) {
            requestAnimationFrame(function() {
                Pasta.apply(document.getElementById("main-canvas"), options);
            });
         });
    </script>

The image filtering library requires using a canvas ("main-canvas"), but whenever I edit the img function to canvas in view, I get an empty rectangle, as seen in the following two pictures, before with img and after with canvas:

(https://i.stack.imgur.com/7bsok.png)

(https://i.stack.imgur.com/uEJsY.png)

I carefully examined what could go wrong with the rendering part of the canvas, couldn't manage to find a solution.

CodePudding user response:

I don't know what exactly the pasta function does. If it paints the given image (maybe also change the canvas size to match the image size) and applies a filter, then my comment won't help.

Setting the src attribute on a <canvas> element does unfortunately not paint the image to it.

I think you need to add another port to draw the image whenever one is selected using the Canvas APIs drawImage function. Then you can apply the filter on top of that.

Another quirk of the canvas element is, that its content will be cleared whenever its size is changed.
Maybe that also trips you up.

  • Related