2017-02-24 61 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})) 
      })))