试剂画布组件

时间:2017-02-24 18:22:28

标签: canvas clojurescript reagent

我正在尝试编写一个试剂组件,它反映了HTML Canvas元素需要具有一些绝对像素大小的事实。我宁愿总是在最大分辨率上使用画布。

最后,我使用这样的组件:

[Canvas {:width "100%"
         :height "100%"
         :render (fn [ctx [w h]]
                    (.fillRect ctx 0 0 (/ w 2) (/ h 2)))}]

这是我的方法:

(defn Canvas [{:keys [width height render]}]
  (let [state (r/atom {:size nil})
        update-size (fn [el]
                      (when el 
                        (let [size (get-real-size el)
                              ctx (.getContext el "2d")]
                          (swap! state assoc :size size)
                          (render ctx size))))]
    (fn []
      (let [{:keys [size]} @state]
         [:canvas {:style {:width width :height height} 
                   :ref update-size
                   :width (nth size 0)
                   :height (nth size 1)}]))))

,而:

(defn get-real-size [el]
  (let [bb (.getBoundingClientRect el)]
    [(.-width bb) (.-height bb)]))

画布似乎使用相应的大小正确呈现。但渲染功能不会绘制任何东西。有人知道如何解决/处理这个问题吗?

1 个答案:

答案 0 :(得分:2)

您没有获得任何绘图的原因是您的组件在安装之前呈现。为了解决这个问题,你必须在安装后再次进行渲染。

以下是reagent manual explains this的方法。虽然它在窗口尺寸发生变化后提供了重绘问题的解决方案,但该解决方案也适用于您。

在您的情况下,您可以通过取消引用原子轻松触发重新渲染。

(defn Canvas [{:keys [width height render]}]
    (let [state (atom nil)]
        (reagent/create-class
            {:reagent-render      (fn []
                                      (let [update-size (fn [el]
                                                            (when el
                                                                (let [size (get-real-size el)
                                                                      ctx (.getContext el "2d")]
                                                                    (swap! state assoc :size size)
                                                                    (render ctx size))))]
                                          (fn [] (let [{:keys [size]} @state]
                                                     [:canvas {:style  {:width width :height height}
                                                               :ref    update-size
                                                               :width  (nth size 0)
                                                               :height (nth size 1)}]))))
             :component-did-mount (fn [] (reset! state {:size nil}))
             })))