Dynamic labels for value and limits

This commit is contained in:
simon 2017-07-02 23:03:25 +01:00
parent 0afe3c5d2b
commit a782e17f7c
3 changed files with 104 additions and 46 deletions

View file

@ -23,6 +23,11 @@
fill: #444444; fill: #444444;
} }
.snm-limit {
text-align: center;
font-size: 66%;
}
.snm-meter { .snm-meter {
height: 50%; height: 50%;
width: auto; width: auto;
@ -44,3 +49,14 @@
stroke: green; stroke: green;
stroke-width: 15; stroke-width: 15;
} }
.snm-value {
text-align: center;
}
.snm-warning {
fill: none;
stroke-width: 10;
stroke-linejoin: round;
stroke: red;
}

View file

@ -49,7 +49,9 @@
{:name :max-value :required false :type "double" :default 100 {:name :max-value :required false :type "double" :default 100
:validate-fn number? :description "the maximum value model can take"} :validate-fn number? :description "the maximum value model can take"}
{:name :class :required false :type "string" {:name :class :required false :type "string"
:validate-fn string? :description "CSS class names, space separated"} :validate-fn string? :description "CSS class names, space separated, for the top-level SVG element"}
{:name :alarm-class :required false :type "string"
:validate-fn string? :description "CSS class names, space separated, for the cursor"}
{:name :cursor-class :required false :type "string" :default "snm-cursor" {:name :cursor-class :required false :type "string" :default "snm-cursor"
:validate-fn string? :description "CSS class names, space separated, for the cursor"} :validate-fn string? :description "CSS class names, space separated, for the cursor"}
{:name :frame-class :required false :type "string" :default "snm-frame" {:name :frame-class :required false :type "string" :default "snm-frame"
@ -62,6 +64,10 @@
:validate-fn string? :description "CSS class names, space separated, for the scale"} :validate-fn string? :description "CSS class names, space separated, for the scale"}
{:name :redzone-class :required false :type "string" :default "snm-redzone" {:name :redzone-class :required false :type "string" :default "snm-redzone"
:validate-fn string? :description "CSS class names, space separated, for the redzone"} :validate-fn string? :description "CSS class names, space separated, for the redzone"}
{:name :unit :required false :type "string"
:validate-fn string? :description "Unit to show after the value"}
{:name :id :required false :type "string" :default "meter"
:validate-fn string? :description "Element id for this instance of the meter"}
{:name :style :required false :type "CSS style map" {:name :style :required false :type "CSS style map"
:validate-fn css-style? :description "CSS styles to add or override"} :validate-fn css-style? :description "CSS styles to add or override"}
{:name :attr :required false :type "HTML attr map" {:name :attr :required false :type "HTML attr map"
@ -88,56 +94,88 @@
(defn swinging-needle-meter (defn swinging-needle-meter
"Render an SVG swinging needle meter" "Render an SVG swinging needle meter"
[& {:keys [model setpoint width height min-value max-value class cursor-class frame-class hub-class needle-class scale-class redzone-class style attr] [& {:keys [model setpoint width height min-value max-value class alarm-class cursor-class frame-class hub-class needle-class scale-class redzone-class unit id style attr]
:or {width "100%" :or {width "100%"
height "100%" height "100%"
min-value 0 min-value 0
max-value 100 max-value 100
cursor-class "snm-cursor" cursor-class "snm-cursor"
frame-class "snm-frame" frame-class "snm-frame"
hub-class "snm-hub" hub-class "snm-hub"
needle-class "snm-needle" needle-class "snm-needle"
scale-class "snm-scale" scale-class "snm-scale"
redzone-class "snm-redzone"} redzone-class "snm-redzone"
id "meter"}
:as args}] :as args}]
{:pre [(validate-args-macro swinging-needle-args-desc args "swinging-needle")]} {:pre [(validate-args-macro swinging-needle-args-desc args "swinging-needle")]}
(let [model (deref-or-value model) (let [model (deref-or-value model)
setpoint (deref-or-value setpoint)] setpoint (deref-or-value setpoint)
current-value (str model (if unit " ") unit)]
[box [box
:align :start :align :start
:child [:div :child [:div
(merge (merge
{:class (str "rc-swinging-needle " class) {:class (str "swinging-needle " class)
:style (merge (flex-child-style "none") :style (merge (flex-child-style "none")
{:width width :height height} {:width width :height height}
style)} style)}
attr) attr)
[:div [:svg {:xmlns:svg "http://www.w3.org/2000/svg"
{:class (str "swinging-needle ") :xmlns "http://www.w3.org/2000/svg"
:role "swinging-needle"} :xml:space "preserve"
[:svg {:xmlns:svg "http://www.w3.org/2000/svg" :overflow "visible"
:xmlns "http://www.w3.org/2000/svg" :viewBox "0 0 180 120"
:xml:space "preserve" :y "0px"
:overflow "visible" :x "0px"
:viewBox "0 0 180 120" :version "1.1"
:y "0px" :id id
:x "0px" :class (str "snm-meter " class)}
:version "1.1" [:text
:class (str "snm-meter " class)} {:xml:space "preserve"
[:path {:class scale-class :x "-75.5"
:d "m 11.85914,76.864488 c 0,0 14.34545,-53.795412 68.140856,-53.795412 53.795424,0 68.140864,53.795412 68.140864,53.795412"}] :y "50"
[:path {:class redzone-class :d "m 137.74738,54.878869 c 0,0 3.02675,3.620416 6.3911,11.14347 3.36435,7.523055 4.20612,11.198095 4.20612,11.198095"}] :id (str id "-min-value")
[:rect {:class frame-class :x "5" :y "5" :height "100" :width "150"}] :class "snm-limit"
[:path {:class cursor-class :transform "matrix(0.2398013,-0.97082199,0.97082199,0.2398013,0,0)"}[:tspan min-value]]
:d "M 80,20 80,100" [:text
:visibility (if (and (number? setpoint) (> setpoint min-value)) "visible" "hidden") {:xml:space "preserve"
:transform (str "rotate( " (deflection setpoint min-value max-value) ", 80, 100)")}] :x "102"
[:path {:class needle-class :y "-102"
:d "M 80,20 80,100" :id (str id "-max-value")
:transform (str "rotate( " (deflection model min-value max-value) ", 80, 100)") }] :class "snm-limit"
[:circle {:class hub-class :r "10" :cx "80" :cy "100"}]] :transform "matrix(0.26614433,0.96393319,-0.96393319,0.26614433,0,0)"}[:tspan max-value]]
;;; Useful for debugging: [:text
;; (str "value: " model "; min: " min-value {:xml:space "preserve"
;; "; max: " max-value ;; 4.5 here is a real fudge. It's roughly half the width in SVG units of a single character;
;; "; deflection: " (int (deflection model min-value max-value))) ;; it's intended to keep the visible text roughly in the middle of the meter.
]]])) :x (str (- 80 (* (count current-value) 4.5)))
:y "60"
:width "100"
:id (str id "-current-value")
:class "snm-value"}[:tspan current-value]]
[:path {:class scale-class
:id (str id "-scale")
:d "m 11.85914,76.864488 c 0,0 14.34545,-53.795412 68.140856,-53.795412 53.795424,0 68.140864,53.795412 68.140864,53.795412"}]
[:path {:class redzone-class
:id (str id "-redzone")
:d "m 137.74738,54.878869 c 0,0 3.02675,3.620416 6.3911,11.14347 3.36435,7.523055 4.20612,11.198095 4.20612,11.198095"}]
[:rect {:class (str frame-class (if (< min-value model max-value) "" (str " " alarm-class)))
:id (str id "-frame")
:x "5" :y "5" :height "100" :width "150"}]
[:path {:class cursor-class
:id (str id "-cursor")
:d "M 80,20 80,100"
:visibility (if (and (number? setpoint) (> setpoint min-value)) "visible" "hidden")
:transform (str "rotate( " (deflection setpoint min-value max-value) ", 80, 100)")}]
[:path {:class needle-class
:id (str id "-needle")
:d "M 80,20 80,100"
:transform (str "rotate( " (deflection model min-value max-value) ", 80, 100)") }]
[:circle {:class hub-class
:id (str id "-hub")
:r "10" :cx "80" :cy "100"}]]
;;; Useful for debugging:
(str "value: " model "; min: " min-value
"; max: " max-value
"; deflection: " (int (deflection model min-value max-value)))
]]))

View file

@ -41,9 +41,13 @@
[v-box [v-box
:gap "20px" :gap "20px"
:children [[swinging-needle-meter :children [[swinging-needle-meter
:model value :model value
:setpoint setpoint :setpoint setpoint
:width "350px"] ;; :unit "Mw"
;; :min-value 20
;; :max-value 40
;; :alarm-class "snm-warning"
:width "350px"]
[title :level :level3 :label "Parameters"] [title :level :level3 :label "Parameters"]
[h-box [h-box
:gap "10px" :gap "10px"