(установлено! (.-onload image) (fn [])) не работает - PullRequest
0 голосов
/ 08 марта 2020

У меня есть следующий код, который принимает в качестве входных данных некоторые изображения, а затем сжимает их с помощью функции compress-omg, которая получает URL-адрес каждого изображения, введенного в последовательности, и сохраняет сжатые большие двоичные объекты в векторе БД: images

(defn image-selector []
  [:<>
   ;; appending image in this div
   [:div {:id "test-div"}]
   [:input {:type "file"
                     :multiple true
                     :id "input-image"
                     :on-change
                     (fn [e]
                         (let [files (array-seq (.. e -target -files))]
                           (doseq [file files]
                             ;; must create a new file-reader in each iteration
                             (let [file-reader (js/FileReader.)]
                               (set! (.-onload file-reader)
                                 (fn [e]
                                   (let [data-url (-> e .-target .-result)]
                                     (dispatch [:images (compress-img data-url)]))))
                               (.readAsDataURL file-reader file)))))}]])


(defn compress-img [data-url]
  "takes data-url. Compresses it and returns a blob."
  (let [image (js/Image.)
        canvas (js/document.createElement "canvas")
        ctx (.getContext canvas "2d")
        blob (js/Blob. [data-url])
        window-url (or (-> js/window .-URL) (-> js/window .-webkitURL ))
        blob-url (.createObjectURL window-url blob)
        ]
    (set! (.-onload image)
;; doesn't print 
          (fn [_]

            (prn "image height" (.-height image))
            (prn "image width " (.-width image))
            (set! (.-src image) blob-url)

            (.appendChild (js/document.getElementById "test-div") image)


            (.drawImage ctx image 0 0 (.-width image) (.-height image))
            ;; approximating sizes of compressed and uncompressed images
            (prn "size original (MB)" (* 0.75 0.000001 (.-length data-url)))
            (prn "size upload (MB)" (* 0.75 0.000001 (.-length (.toDataURL canvas "image/png" 0.1))))
            ;; compressing and returning the blob
            (js/Blob. [(.toDataURL canvas "image/png" 0.1)])
            )

          )
    (set! (.-onerror image)
;; doesn't print
          (fn [e]
            (prn "error is " e)
            (prn "error")))
   ))

Но события onload и onerror никогда не запускаются. Что я делаю не так?

Ответы [ 2 ]

0 голосов
/ 09 марта 2020

В вашем примере кода (set! (.-src image) blob-url) проскользнул в сам обработчик события onload.

Вы должны вызвать эту функцию вне этой функции, чтобы фактически начать загрузку изображения, чтобы оно могло должным образом вызвать onload.

Что-то вроде

(set! (.-src image) blob-url)
(set! (.-onload image)
  (fn [_]
    (prn "image height" (.-height image))
    (prn "image width " (.-width image))

    (.appendChild (js/document.getElementById "test-div") image)

    (.drawImage ctx image 0 0 (.-width image) (.-height image))
    ;; approximating sizes of compressed and uncompressed images
    (prn "size original (MB)" (* 0.75 0.000001 (.-length data-url)))
    (prn "size upload (MB)" (* 0.75 0.000001 (.-length (.toDataURL canvas "image/png" 0.1))))
    ;; compressing and returning the blob
    (js/Blob. [(.toDataURL canvas "image/png" 0.1)])
    ))
0 голосов
/ 08 марта 2020

Чтобы вызвать onload или onerror на Image, сначала необходимо (set! (.-src img) data-url).


Поскольку вы пытаетесь изменить размер URL-адреса данных, вот как мы делаем это в нашей кодовой базе:

(defn clamp [^js image width heigth]
  (let [img-width  (.-width image)
        img-height (.-height image)
        ratio      (/ img-width img-height)
        portrait?  (< img-width img-height)
        w          (if (< img-width width)
                     img-width
                     (if portrait?
                       width
                       (* width ratio)))
        h          (if (< img-height heigth)
                     img-height
                     (if portrait?
                       (/ heigth ratio)
                       heigth))]
    [w h]))

(defn resize! [image width height callback]
  (let [canvas (.createElement js/document "canvas")
        ctx    (.getContext canvas "2d")
        [w h]  (clamp image width height)]
    (set! (.-width canvas) w)
    (set! (.-height canvas) h)
    (.drawImage ctx image 0 0 w h)
    (callback (.toDataURL canvas))))

(defn resize-data-url! [uri width height callback]
  (let [img (.createElement js/document "img")]
    (set! (.-onload img) (fn [] (this-as image
                                  (resize! image width height callback))))
    (set! (.-src img) uri)
    nil))

(defn with-image-data
  "Asynchronously load an image `file` in a FileReader, then call the `callback`
  fn with the FileReader's result and a DOM Image intance. Usefull to get the
  image content as a DataUrl, image width and height. If the file is not an
  image, call `callback` with nil arguments."
  [file callback]
  (if-not (= (files/type file) :file.type/image)
    (callback nil nil)
    (let [reader (js/FileReader.)
          img    (js/Image.)]
      (set! (.-onload reader) #(set! (.-src img) (.-result reader)))
      (set! (.-onerror reader) #(taoensso.timbre/error %))
      (set! (.-onload img) (fn [_]
                             (resize-data-url! (.-result reader) 300 300
                                               (fn [url]
                                                 (callback url img)))))
      (.readAsDataURL reader file)
      nil)))
...