mirror of
https://github.com/penpot/penpot.git
synced 2025-02-15 03:28:25 -05:00
✨ Improved resize/rotation handlers for shapes with tiny height/width
This commit is contained in:
parent
f4be3aa9de
commit
9332d6f36c
5 changed files with 69 additions and 56 deletions
|
@ -8,7 +8,6 @@
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.geom.shapes.path :as gsp]
|
[app.common.geom.shapes.path :as gsp]
|
||||||
[app.common.geom.shapes.rect :as gpr]
|
|
||||||
[app.common.geom.shapes.transforms :as gtr]
|
[app.common.geom.shapes.transforms :as gtr]
|
||||||
[app.common.path.bool :as pb]
|
[app.common.path.bool :as pb]
|
||||||
[app.common.path.shapes-to-path :as stp]))
|
[app.common.path.shapes-to-path :as stp]))
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
(ns app.main.data.workspace.drawing.common
|
(ns app.main.data.workspace.drawing.common
|
||||||
(:require
|
(:require
|
||||||
[app.common.pages :as cp]
|
|
||||||
[app.common.geom.matrix :as gmt]
|
[app.common.geom.matrix :as gmt]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.common.math :as mth]
|
[app.common.math :as mth]
|
||||||
|
[app.common.pages :as cp]
|
||||||
[app.main.data.workspace.common :as dwc]
|
[app.main.data.workspace.common :as dwc]
|
||||||
[app.main.data.workspace.undo :as dwu]
|
[app.main.data.workspace.undo :as dwu]
|
||||||
[app.main.worker :as uw]
|
[app.main.worker :as uw]
|
||||||
|
|
|
@ -51,18 +51,21 @@
|
||||||
:fill "none"}}])))
|
:fill "none"}}])))
|
||||||
|
|
||||||
(defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom]
|
(defn- handlers-for-selection [{:keys [x y width height]} {:keys [type]} zoom]
|
||||||
(let [zoom-width (* width zoom)
|
(let [threshold-small (/ 25 zoom)
|
||||||
zoom-height (* height zoom)
|
threshold-tiny (/ 10 zoom)
|
||||||
|
|
||||||
align (when (or (<= zoom-width small-selrect-side)
|
small-width? (<= width threshold-small)
|
||||||
(<= zoom-height small-selrect-side))
|
tiny-width? (<= width threshold-tiny)
|
||||||
:outside)
|
|
||||||
show-resize-point? (or (not= type :path)
|
small-height? (<= height threshold-small)
|
||||||
(and
|
tiny-height? (<= height threshold-tiny)
|
||||||
(> zoom-width min-selrect-side)
|
|
||||||
(> zoom-height min-selrect-side)))
|
vertical-line? (and (= type :path) tiny-width?)
|
||||||
min-side-top? (or (not= type :path) (> zoom-height min-selrect-side))
|
horizontal-line? (and (= type :path) tiny-height?)
|
||||||
min-side-side? (or (not= type :path) (> zoom-width min-selrect-side))]
|
|
||||||
|
align (if (or small-width? small-height?)
|
||||||
|
:outside
|
||||||
|
:inside)]
|
||||||
(->>
|
(->>
|
||||||
[ ;; TOP-LEFT
|
[ ;; TOP-LEFT
|
||||||
{:type :rotation
|
{:type :rotation
|
||||||
|
@ -81,42 +84,66 @@
|
||||||
:position :bottom-left
|
:position :bottom-left
|
||||||
:props {:cx x :cy (+ y height)}}
|
:props {:cx x :cy (+ y height)}}
|
||||||
|
|
||||||
(when min-side-top?
|
(when-not horizontal-line?
|
||||||
{:type :resize-side
|
(let [x (if small-width? (+ x (/ (- width threshold-small) 2)) x)
|
||||||
:position :top
|
length (if small-width? threshold-small width)]
|
||||||
:props {:x x :y y :length width :angle 0 :align align}})
|
{:type :resize-side
|
||||||
|
:position :top
|
||||||
|
:props {:x x
|
||||||
|
:y y
|
||||||
|
:length length
|
||||||
|
:angle 0
|
||||||
|
:align align}}))
|
||||||
|
|
||||||
(when min-side-side?
|
(when-not horizontal-line?
|
||||||
{:type :resize-side
|
(let [x (if small-width? (+ x (/ (+ width threshold-small) 2)) (+ x width))
|
||||||
:position :right
|
length (if small-width? threshold-small width)]
|
||||||
:props {:x (+ x width) :y y :length height :angle 90 :align align}})
|
{:type :resize-side
|
||||||
|
:position :bottom
|
||||||
|
:props {:x x
|
||||||
|
:y (+ y height)
|
||||||
|
:length length
|
||||||
|
:angle 180
|
||||||
|
:align align}}))
|
||||||
|
|
||||||
(when min-side-top?
|
(when-not vertical-line?
|
||||||
{:type :resize-side
|
(let [y (if small-height? (+ y (/ (- height threshold-small) 2)) y)
|
||||||
:position :bottom
|
length (if small-height? threshold-small height)]
|
||||||
:props {:x (+ x width) :y (+ y height) :length width :angle 180 :align align}})
|
{:type :resize-side
|
||||||
|
:position :right
|
||||||
|
:props {:x (+ x width)
|
||||||
|
:y y
|
||||||
|
:length length
|
||||||
|
:angle 90
|
||||||
|
:align align}}))
|
||||||
|
|
||||||
(when min-side-side?
|
(when-not vertical-line?
|
||||||
{:type :resize-side
|
(let [y (if small-height? (+ y (/ (+ height threshold-small) 2)) (+ y height))
|
||||||
:position :left
|
length (if small-height? threshold-small height)]
|
||||||
:props {:x x :y (+ y height) :length height :angle 270 :align align}})
|
{:type :resize-side
|
||||||
|
:position :left
|
||||||
|
:props {:x x
|
||||||
|
:y y
|
||||||
|
:length length
|
||||||
|
:angle 270
|
||||||
|
:align align}}))
|
||||||
|
|
||||||
(when show-resize-point?
|
(when (and (not tiny-width?) (not tiny-height?))
|
||||||
{:type :resize-point
|
{:type :resize-point
|
||||||
:position :top-left
|
:position :top-left
|
||||||
:props {:cx x :cy y :align align}})
|
:props {:cx x :cy y :align align}})
|
||||||
|
|
||||||
(when show-resize-point?
|
(when (and (not tiny-width?) (not tiny-height?))
|
||||||
{:type :resize-point
|
{:type :resize-point
|
||||||
:position :top-right
|
:position :top-right
|
||||||
:props {:cx (+ x width) :cy y :align align}})
|
:props {:cx (+ x width) :cy y :align align}})
|
||||||
|
|
||||||
(when show-resize-point?
|
(when (and (not tiny-width?) (not tiny-height?))
|
||||||
{:type :resize-point
|
{:type :resize-point
|
||||||
:position :bottom-right
|
:position :bottom-right
|
||||||
:props {:cx (+ x width) :cy (+ y height) :align align}})
|
:props {:cx (+ x width) :cy (+ y height) :align align}})
|
||||||
|
|
||||||
(when show-resize-point?
|
(when (and (not tiny-width?) (not tiny-height?))
|
||||||
{:type :resize-point
|
{:type :resize-point
|
||||||
:position :bottom-left
|
:position :bottom-left
|
||||||
:props {:cx x :cy (+ y height) :align align}})]
|
:props {:cx x :cy (+ y height) :align align}})]
|
||||||
|
@ -137,8 +164,7 @@
|
||||||
:y y
|
:y y
|
||||||
:width size
|
:width size
|
||||||
:height size
|
:height size
|
||||||
:fill (if (debug? :rotation-handler) "blue" "none")
|
:fill (if (debug? :handlers) "blue" "none")
|
||||||
:stroke (if (debug? :rotation-handler) "blue" "none")
|
|
||||||
:stroke-width 0
|
:stroke-width 0
|
||||||
:transform transform
|
:transform transform
|
||||||
:on-mouse-down on-rotate}]))
|
:on-mouse-down on-rotate}]))
|
||||||
|
@ -171,8 +197,7 @@
|
||||||
:width resize-point-circle-radius
|
:width resize-point-circle-radius
|
||||||
:height resize-point-circle-radius
|
:height resize-point-circle-radius
|
||||||
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
|
:transform (when rotation (str/fmt "rotate(%s, %s, %s)" rotation cx' cy'))
|
||||||
:style {:fill (if (debug? :resize-handler) "red" "none")
|
:style {:fill (if (debug? :handlers) "red" "none")
|
||||||
:stroke (if (debug? :resize-handler) "red" "none")
|
|
||||||
:stroke-width 0
|
:stroke-width 0
|
||||||
:cursor cursor}
|
:cursor cursor}
|
||||||
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
|
:on-mouse-down #(on-resize {:x cx' :y cy'} %)}])
|
||||||
|
@ -181,8 +206,7 @@
|
||||||
:r (/ resize-point-circle-radius zoom)
|
:r (/ resize-point-circle-radius zoom)
|
||||||
:cx cx'
|
:cx cx'
|
||||||
:cy cy'
|
:cy cy'
|
||||||
:style {:fill (if (debug? :resize-handler) "red" "none")
|
:style {:fill (if (debug? :handlers) "red" "none")
|
||||||
:stroke (if (debug? :resize-handler) "red" "none")
|
|
||||||
:stroke-width 0
|
:stroke-width 0
|
||||||
:cursor cursor}}])]))
|
:cursor cursor}}])]))
|
||||||
|
|
||||||
|
@ -192,25 +216,18 @@
|
||||||
(let [res-point (if (#{:top :bottom} position)
|
(let [res-point (if (#{:top :bottom} position)
|
||||||
{:y y}
|
{:y y}
|
||||||
{:x x})
|
{:x x})
|
||||||
target-length (max 0 (- length (/ (* resize-point-rect-size 2) zoom)))
|
|
||||||
|
|
||||||
width (if (< target-length 6) length target-length)
|
|
||||||
height (/ resize-side-height zoom)
|
height (/ resize-side-height zoom)
|
||||||
|
|
||||||
offset-x (/ (- length width) 2)
|
|
||||||
offset-y (if (= align :outside) (- height) (- (/ height 2)))
|
offset-y (if (= align :outside) (- height) (- (/ height 2)))
|
||||||
|
|
||||||
target-x (+ x offset-x)
|
|
||||||
target-y (+ y offset-y)]
|
target-y (+ y offset-y)]
|
||||||
[:rect {:x target-x
|
[:rect {:x x
|
||||||
:y target-y
|
:y target-y
|
||||||
:width width
|
:width length
|
||||||
:height height
|
:height height
|
||||||
:transform (gmt/multiply transform
|
:transform (gmt/multiply transform
|
||||||
(gmt/rotate-matrix angle (gpt/point x y)))
|
(gmt/rotate-matrix angle (gpt/point x y)))
|
||||||
:on-mouse-down #(on-resize res-point %)
|
:on-mouse-down #(on-resize res-point %)
|
||||||
:style {:fill (if (debug? :resize-handler) "yellow" "none")
|
:style {:fill (if (debug? :handlers) "yellow" "none")
|
||||||
:stroke (if (debug? :resize-handler) "yellow" "none")
|
|
||||||
:stroke-width 0
|
:stroke-width 0
|
||||||
:cursor (if (#{:left :right} position)
|
:cursor (if (#{:left :right} position)
|
||||||
(cur/resize-ew rotation)
|
(cur/resize-ew rotation)
|
||||||
|
|
|
@ -9,13 +9,13 @@
|
||||||
[app.common.geom.point :as gpt]
|
[app.common.geom.point :as gpt]
|
||||||
[app.common.geom.shapes :as gsh]))
|
[app.common.geom.shapes :as gsh]))
|
||||||
|
|
||||||
(defn- selrect-snap-points [{:keys [x y width height]}]
|
(defn selrect-snap-points [{:keys [x y width height]}]
|
||||||
#{(gpt/point x y)
|
#{(gpt/point x y)
|
||||||
(gpt/point (+ x width) y)
|
(gpt/point (+ x width) y)
|
||||||
(gpt/point (+ x width) (+ y height))
|
(gpt/point (+ x width) (+ y height))
|
||||||
(gpt/point x (+ y height))})
|
(gpt/point x (+ y height))})
|
||||||
|
|
||||||
(defn- frame-snap-points [{:keys [x y width height] :as selrect}]
|
(defn frame-snap-points [{:keys [x y width height] :as selrect}]
|
||||||
(into (selrect-snap-points selrect)
|
(into (selrect-snap-points selrect)
|
||||||
#{(gpt/point (+ x (/ width 2)) y)
|
#{(gpt/point (+ x (/ width 2)) y)
|
||||||
(gpt/point (+ x width) (+ y (/ height 2)))
|
(gpt/point (+ x width) (+ y (/ height 2)))
|
||||||
|
|
|
@ -31,11 +31,8 @@
|
||||||
;; Displays in the console log the events through the application
|
;; Displays in the console log the events through the application
|
||||||
:events
|
:events
|
||||||
|
|
||||||
;; Display the boxes that represent the rotation handlers
|
;; Display the boxes that represent the rotation and resize handlers
|
||||||
:rotation-handler
|
:handlers
|
||||||
|
|
||||||
;; Display the boxes that represent the resize handlers
|
|
||||||
:resize-handler
|
|
||||||
|
|
||||||
;; Displays the center of a selection
|
;; Displays the center of a selection
|
||||||
:selection-center
|
:selection-center
|
||||||
|
|
Loading…
Add table
Reference in a new issue