2017-02-24 41 views
0

我正试图编写一个试剂组件,它对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)])) 

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

回答

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})) 
      })))