官术网_书友最值得收藏!

The concept of time in RxJS

Now that we have a working environment, we can progress with our animation. It is probably a good idea to specify how often we would like to have a new animation frame.

This effectively means adding the concept of time to our application. You're free to play with different values, but let's start with a new frame every 10 milliseconds:

(def rx-interval js/rxjs.interval)
(def rx-take js/rxjs.operators.take)
(def rx-map js/rxjs.operators.map)
(def app-time (rx-interval 10))

As RxJS is a JavaScript library, we need to use ClojureScript's interoperability to call its functions. For convenience, we will bind the interval function of RxJS to a local var. We will use this approach throughout this book when appropriate.

Next, we will create an infinite stream of numbersstarting at 0, that will have a new element every 10 milliseconds. Let's make sure this is working as expected:

(-> app-time
(.pipe (rx-take 5)) (.subscribe (fn [n] (.log js/console n)))) ;; 0 ;; 1 ;; 2 ;; 3 ;; 4
I use the term stream very loosely here. It will be defined more precisely later in the book.

Remember that time is infinite, so we will use the take Rx operator in order to avoid indefinitely printing out numbers to the console.

Our next step is to calculate the 2D coordinate representing a segment of the sine wave we can draw. This will be given by the following functions:

(defn deg-to-rad [n] 
  (* (/ Math/PI 180) n)) 
 
(defn sine-coord [x] 
  (let [sin (Math/sin (deg-to-rad x)) 
        y   (- 100 (* sin 90))] 
    {:x   x 
     :y   y 
     :sin sin}))

(def sine-wave
(.pipe app-time (rx-map sine-coord)))

The sine-coord function takes an x point of our 2D canvas and calculates the y point based on the sine of x. The constants 100 and 90 simply control how tall and sharp the slope should be. As an example, try calculating the sine coordinate when x is 50:

(.log js/console (str (sine-coord 50))) 
;;{:x 50, :y 31.05600011929198, :sin 0.766044443118978} 

We will be using app-time as the source for the values of x. Creating the sine wave is now only a matter of combining both app-time and sine-coord:

(-> app-time 
    (.pipe (rx-take 5) )
    (.subscribe (fn [num] 
                  (.log js/console (sine-coord num))))) 
 
 ;; {:x 0, :y 100, :sin 0}  
 ;; {:x 1, :y 98.42928342064448, :sin 0.01745240643728351}  
 ;; {:x 2, :y 96.85904529677491, :sin 0.03489949670250097}  
 ;; {:x 3, :y 95.28976393813505, :sin 0.052335956242943835}  
 ;; {:x 4, :y 93.72191736302872, :sin 0.0697564737441253}  

This brings us to the original code snippet that piqued our interest, alongside a function to perform the actual drawing:

(defn fill-rect [x y colour]
(set! (.-fillStyle (ctx)) colour)
(.fillRect (ctx) x y 2 2)) (-> app-time (.pipe (rx-take 700)) (.subscribe (fn [num] (fill-rect x y "orange"))))

As this point, we can save the file again and watch as the sine wave we have just created gracefully appears on the screen.

主站蜘蛛池模板: 宁乡县| 教育| 平南县| 郁南县| 新野县| 晋城| 三亚市| 凤阳县| 安徽省| 庄浪县| 大兴区| 南川市| 南汇区| 洮南市| 界首市| 漳平市| 喀什市| 黔江区| 宣武区| 宣城市| 普兰店市| 上饶市| 祥云县| 鞍山市| 广饶县| 延寿县| 开鲁县| 白玉县| 河津市| 佛冈县| 庆云县| 商洛市| 宁国市| 定襄县| 丹东市| 西吉县| 垦利县| 四川省| 榆社县| 苍南县| 临沭县|