🎉 Improve zoom actions for huge shapes

This commit is contained in:
Alejandro Alonso 2026-01-27 08:13:15 +01:00
parent 7d3ac38749
commit b40ccaf030
3 changed files with 48 additions and 30 deletions

View File

@ -124,33 +124,51 @@
(defn adjust-to-viewport (defn adjust-to-viewport
([viewport srect] (adjust-to-viewport viewport srect nil)) ([viewport srect] (adjust-to-viewport viewport srect nil))
([viewport srect {:keys [padding] :or {padding 0}}] ([viewport srect {:keys [padding min-zoom] :or {padding 0 min-zoom nil}}]
(let [gprop (/ (:width viewport) (let [gprop (/ (:width viewport)
(:height viewport)) (:height viewport))
srect (-> srect srect-padded (-> srect
(update :x #(- % padding)) (update :x #(- % padding))
(update :y #(- % padding)) (update :y #(- % padding))
(update :width #(+ % padding padding)) (update :width #(+ % padding padding))
(update :height #(+ % padding padding))) (update :height #(+ % padding padding)))
width (:width srect) width (:width srect-padded)
height (:height srect) height (:height srect-padded)
lprop (/ width height)] lprop (/ width height)
(cond adjusted-rect
(> gprop lprop) (cond
(let [width' (* (/ width lprop) gprop) (> gprop lprop)
padding (/ (- width' width) 2)] (let [width' (* (/ width lprop) gprop)
(-> srect padding (/ (- width' width) 2)]
(update :x #(- % padding)) (-> srect-padded
(assoc :width width') (update :x #(- % padding))
(grc/update-rect :position))) (assoc :width width')
(grc/update-rect :position)))
(< gprop lprop) (< gprop lprop)
(let [height' (/ (* height lprop) gprop) (let [height' (/ (* height lprop) gprop)
padding (/ (- height' height) 2)] padding (/ (- height' height) 2)]
(-> srect (-> srect-padded
(update :y #(- % padding)) (update :y #(- % padding))
(assoc :height height') (assoc :height height')
(grc/update-rect :position))) (grc/update-rect :position)))
:else :else
(grc/update-rect srect :position))))) (grc/update-rect srect-padded :position))]
;; If min-zoom is specified and the resulting zoom would be below it,
;; return a rect with the original top-left corner centered in the viewport
;; instead of using the aspect-ratio-adjusted rect (which can push coords
;; extremely far with extreme aspect ratios).
(if (and (some? min-zoom)
(< (/ (:width viewport) (:width adjusted-rect)) min-zoom))
(let [anchor-x (:x srect)
anchor-y (:y srect)
vbox-width (/ (:width viewport) min-zoom)
vbox-height (/ (:height viewport) min-zoom)]
(-> adjusted-rect
(assoc :x (- anchor-x (/ vbox-width 2))
:y (- anchor-y (/ vbox-height 2))
:width vbox-width
:height vbox-height)
(grc/update-rect :position)))
adjusted-rect))))

View File

@ -51,7 +51,7 @@
(or (> (:width srect) width) (or (> (:width srect) width)
(> (:height srect) height)) (> (:height srect) height))
(let [srect (gal/adjust-to-viewport size srect {:padding 40}) (let [srect (gal/adjust-to-viewport size srect {:padding 40 :min-zoom 0.01})
zoom (/ (:width size) (:width srect))] zoom (/ (:width size) (:width srect))]
(-> local (-> local

View File

@ -97,7 +97,7 @@
state state
(update state :workspace-local (update state :workspace-local
(fn [{:keys [vport] :as local}] (fn [{:keys [vport] :as local}]
(let [srect (gal/adjust-to-viewport vport srect {:padding 160}) (let [srect (gal/adjust-to-viewport vport srect {:padding 160 :min-zoom 0.01})
zoom (/ (:width vport) (:width srect))] zoom (/ (:width vport) (:width srect))]
(-> local (-> local
(assoc :zoom zoom) (assoc :zoom zoom)
@ -118,7 +118,7 @@
(gsh/shapes->rect))] (gsh/shapes->rect))]
(update state :workspace-local (update state :workspace-local
(fn [{:keys [vport] :as local}] (fn [{:keys [vport] :as local}]
(let [srect (gal/adjust-to-viewport vport srect {:padding 40}) (let [srect (gal/adjust-to-viewport vport srect {:padding 40 :min-zoom 0.01})
zoom (/ (:width vport) (:width srect))] zoom (/ (:width vport) (:width srect))]
(-> local (-> local
(assoc :zoom zoom) (assoc :zoom zoom)
@ -142,7 +142,7 @@
(fn [{:keys [vport] :as local}] (fn [{:keys [vport] :as local}]
(let [srect (gal/adjust-to-viewport (let [srect (gal/adjust-to-viewport
vport srect vport srect
{:padding 40}) {:padding 40 :min-zoom 0.01})
zoom (/ (:width vport) zoom (/ (:width vport)
(:width srect))] (:width srect))]
(-> local (-> local