resources/public | ||
src | ||
.gitignore | ||
index.html | ||
LICENSE | ||
project.clj | ||
README.md |
swinging-needle-meter
A re-frame application designed to display an example swinging needle meter, as an experiment in animating SVG from re-frame. Draws heavily on re-com.
Works well in Chrome and Firefox; not tested in Internet Exploder.
Demo site
There's a demo site here.
Intended uses
This is a component for a console, typically one controlling a technical or scientific instrument. It is by design flexible and configurable. Minimum value, maximum value, warning value and number of gradations shown are all configurable, as are (obviously) styles.
A cursor will be shown if the value of setpoint is between min-value and max-value; setpoint is a dynamic value which is watched during the run. While the model value is within +- tolerance of the setpoint value, a class target-class is set on the meter indicating an on-target status (by default the frame goes green).
A red-zone may be shown if a warn-value is set which is between min-value and max-value. If such a warn-value is set, then if the current value (model) exceeds warn-value, a class warning-class is set on the meter indicating a warning status (by default the frame goes maroon).
Usage
In your cljs file, require the following:
(:require [re-frame.core :as rf]
[re-com.core :refer [h-box v-box box label title slider p single-dropdown]]
[swinging-needle-meter.swinging-needle-meter :refer [swinging-needle-meter swinging-needle-args-desc]]
[swinging-needle-meter.utils :refer [panel-title title2 args-table status-text]])
within a re-com component,
[swinging-needle-meter
:model @(rf/subscribe [:old-value])
:setpoint @(rf/subscribe [:setpoint]) ;; optional
:unit @(rf/subscribe [:unit]) ;; optional
:min-value @(rf/subscribe [:min-val]) ;; optional; default 0
:warn-value @(rf/subscribe [:warn-val]) ;; optional; default 80
:max-value @(rf/subscribe [:max-val]) ;; optional; default 100
:tolerance 2 ;; optional; default 3
:alarm-class "snm-warning" ;; optional; default "snm-warning"
:gradations @(rf/subscribe [:gradations]) ;; optional; default 5
:height (int (* @(rf/subscribe [:size]) 6)) ;; optional; default 200 (pixels)
:width (int (* @(rf/subscribe [:size]) 10))];; optional; default 300 (pixels)
or, minimally, just
[swinging-needle-meter
:model @(rf/subscribe [:old-value])]
There are further arguments which may be set which are documented here.
Obviously, all the subscriptions above must be registered with re-frame/reg-sub
.
The value subscribed to as the value to :model
is expected to be a floating point number between that of :min-value
and :max-value
.
Simulation of a mechanical meter needle with inertia and damping
You don't need animated movement, you can simply jerk the needle to its new position; animation appeals to users who are used to mechanical meters and is easy on the eye, but obviously it means the needle lags a little behind changes in the underlying state.
If you want animation, this is how it works.
The event registered to be driven by :timer
in swinging-needle-meter/events.cljs
drives the animation of the movement of the needle. The value of :timer
is initialised in the state to (js/Date.)
in swinging-needle-meter/state.js
. Thus, it's a clock that ticks.
The actual value in the state which is tracked by the meter is the value of, in the example, :target
. The :timer
event moves :old-value
progressively towards :target
until they coincide. So in a real deployment you'd poll the actual real world value that you were tracking using a repeated asynchronous JSON request, and, on a response to such a request, you would update the value of :target
in the state.
Obviously, if you want to put multiple meters onto one page tracking different real world variables, you would minimally have to have a separate key in the state for
- The
target
of each meter; - the
old-value
of each meter (if animation is desired);
You might also want a separate key for the warn-value
of each meter, and possibly also the set-point
. Values of other parameters may be subscribed to from values in the state but it will probably be more convenient to hard-wire them or allow them to default.
Development Mode
Run application:
lein clean
lein figwheel dev
Figwheel will automatically push cljs changes to the browser.
Wait a bit, then browse to http://localhost:3449.
Production Build
To compile clojurescript to javascript:
lein clean
lein cljsbuild once min
License
Copyright © 2017 Simon Brooke. Licensed under the GNU General Public License, version 2.0 or (at your option) any later version. If you wish to incorporate parts of this into another open source project which uses a less restrictive license, please contact me; I'm open to dual licensing it.