diff options
Diffstat (limited to 'docs/prototypes/gallery-widget.el')
| -rw-r--r-- | docs/prototypes/gallery-widget.el | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/docs/prototypes/gallery-widget.el b/docs/prototypes/gallery-widget.el index 5a80e59..543affe 100644 --- a/docs/prototypes/gallery-widget.el +++ b/docs/prototypes/gallery-widget.el @@ -49,6 +49,12 @@ a typo'd token must fail loudly, not render black." "Needle angle at value 0, degrees from vertical (negative = left).") (defconst gallery-widget--gauge-max-deg 60.0 "Needle angle at value 100.") +(defconst gallery-widget--gauge-cx 48 + "Horizontal center of the needle gauge.") +(defconst gallery-widget--gauge-cy 48 + "Vertical center and baseline of the needle gauge.") +(defconst gallery-widget--gauge-radius 47 + "Outer radius of the needle gauge.") (defun gallery-widget--clamp-value (value) "Validate VALUE is a number and clamp it to the gauge's 0-100 range. @@ -76,27 +82,36 @@ Positive angles swing right, matching the gauge's needle travel." "Format coordinate N with two decimals for stable, readable SVG output." (format "%.2f" n)) +(defun gallery-widget--semicircle-path (cx cy radius &optional close) + "Return an upper semicircle path centered at (CX, CY) with RADIUS. +Append a closing segment when CLOSE is non-nil." + (format "M %g %g A %g %g 0 0 1 %g %g%s" + (- cx radius) cy radius radius (+ cx radius) cy + (if close " Z" ""))) + (defun gallery-widget--node (svg tag &rest attrs) "Append a TAG element with ATTRS plist to SVG and return it." (let ((node (dom-node tag (cl-loop for (k v) on attrs by #'cddr collect (cons (intern (substring (symbol-name k) 1)) v))))) - (svg--append svg node) + (dom-append-child svg node) node)) (defun gallery-widget-needle-gauge (value) "Render the gallery's needle gauge at VALUE (0-100) as an svg.el object. Geometry mirrors the web card: 96px-wide semicircular dial, pivot at its bottom center, 40px needle sweeping -60..+60 degrees, readout below." - (let* ((w 96) (h 64) (cx 48.0) (cy 48.0) + (let* ((w 96) (h 64) + (cx gallery-widget--gauge-cx) + (cy gallery-widget--gauge-cy) ;; clamp once; the angle and the readout render the same value (value (gallery-widget--clamp-value value)) (angle (gallery-widget--needle-angle value)) (tip (gallery-widget--polar cx cy 40.0 angle)) (svg (svg-create w h :viewBox (format "0 0 %d %d" w h)))) ;; glow filter: the SVG equivalent of the web card's box-shadow bloom - (svg--append + (dom-append-child svg (dom-node 'defs nil (dom-node 'filter @@ -107,13 +122,15 @@ bottom center, 40px needle sweeping -60..+60 degrees, readout below." (stdDeviation . "2")))))) ;; arc: 2px wash stroke, centerline radius 47 (96px circle, 2px border) (gallery-widget--node svg 'path - :d "M 1 48 A 47 47 0 0 1 95 48" + :d (gallery-widget--semicircle-path + cx cy gallery-widget--gauge-radius) :fill "none" :stroke (gallery-widget-token 'wash) :stroke-width "2") ;; ticks: 8px steel radials at -60 / 0 / +60 (dolist (deg '(-60.0 0.0 60.0)) - (let ((outer (gallery-widget--polar cx cy 47.0 deg)) + (let ((outer (gallery-widget--polar + cx cy gallery-widget--gauge-radius deg)) (inner (gallery-widget--polar cx cy 39.0 deg))) (gallery-widget--node svg 'line :class "tick" @@ -148,7 +165,7 @@ bottom center, 40px needle sweeping -60..+60 degrees, readout below." ;; lower half of its 8px circle; here the dome is drawn directly) (gallery-widget--node svg 'path :class "hub" - :d "M 44 48 A 4 4 0 0 1 52 48 Z" + :d (gallery-widget--semicircle-path cx cy 4 t) :fill (gallery-widget-token 'gold)) ;; value readout, matching the web card's cream bold figure (svg-text svg (format "%d%%" (round value)) |
