mirror of
https://github.com/penpot/penpot.git
synced 2025-02-10 17:18:21 -05:00
🐛 Change text disposition on resize
This commit is contained in:
parent
8b1f8d1418
commit
7446fe77b3
7 changed files with 90 additions and 47 deletions
|
@ -152,6 +152,28 @@
|
|||
:top
|
||||
:scale)))
|
||||
|
||||
(defn clean-modifiers
|
||||
"Remove redundant modifiers"
|
||||
[{:keys [displacement resize-vector resize-vector-2] :as modifiers}]
|
||||
|
||||
(cond-> modifiers
|
||||
;; Displacement with value 0. We don't move in any direction
|
||||
(and (some? displacement)
|
||||
(mth/almost-zero? (:e displacement))
|
||||
(mth/almost-zero? (:f displacement)))
|
||||
(dissoc :displacement)
|
||||
|
||||
;; Resize with value very close to 1 means no resize
|
||||
(and (some? resize-vector)
|
||||
(mth/almost-zero? (- 1.0 (:x resize-vector)))
|
||||
(mth/almost-zero? (- 1.0 (:y resize-vector))))
|
||||
(dissoc :resize-origin :resize-vector)
|
||||
|
||||
(and (some? resize-vector)
|
||||
(mth/almost-zero? (- 1.0 (:x resize-vector-2)))
|
||||
(mth/almost-zero? (- 1.0 (:y resize-vector-2))))
|
||||
(dissoc :resize-origin-2 :resize-vector-2)))
|
||||
|
||||
(defn calc-child-modifiers
|
||||
[parent child modifiers ignore-constraints transformed-parent-rect]
|
||||
(let [constraints-h
|
||||
|
@ -192,5 +214,7 @@
|
|||
|
||||
(:resize-transform modifiers)
|
||||
(assoc :resize-transform (:resize-transform modifiers)
|
||||
:resize-transform-inverse (:resize-transform-inverse modifiers)))))
|
||||
:resize-transform-inverse (:resize-transform-inverse modifiers))
|
||||
|
||||
:always
|
||||
(clean-modifiers))))
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
text-align (:text-align data "start")
|
||||
base #js {:fontSize (str (:font-size data (:font-size txt/default-text-attrs)) "px")
|
||||
:lineHeight (:line-height data (:line-height txt/default-text-attrs))
|
||||
:margin "inherit"}]
|
||||
:margin 0}]
|
||||
(cond-> base
|
||||
(some? line-height) (obj/set! "lineHeight" line-height)
|
||||
(some? text-align) (obj/set! "textAlign" text-align))))
|
||||
|
|
|
@ -78,10 +78,11 @@
|
|||
[:defs
|
||||
(for [[index data] (d/enumerate position-data)]
|
||||
(when (some? (:fill-color-gradient data))
|
||||
[:& grad/gradient {:id (str "fill-color-gradient_" (get-gradient-id index))
|
||||
:key index
|
||||
:attr :fill-color-gradient
|
||||
:shape data}]))])
|
||||
(let [id (dm/str "fill-color-gradient_" (get-gradient-id index))]
|
||||
[:& grad/gradient {:id id
|
||||
:key id
|
||||
:attr :fill-color-gradient
|
||||
:shape data}])))])
|
||||
|
||||
[:> :g group-props
|
||||
(for [[index data] (d/enumerate position-data)]
|
||||
|
@ -91,7 +92,7 @@
|
|||
|
||||
alignment-bl (when (cfg/check-browser? :safari) "text-before-edge")
|
||||
dominant-bl (when-not (cfg/check-browser? :safari) "ideographic")
|
||||
rtl? (= "rtl"(:direction data))
|
||||
rtl? (= "rtl" (:direction data))
|
||||
props (-> #js {:key (dm/str "text-" (:id shape) "-" index)
|
||||
:x (if rtl? (+ (:x data) (:width data)) (:x data))
|
||||
:y y
|
||||
|
@ -110,7 +111,7 @@
|
|||
(obj/set! "fill" (str "url(#fill-" index "-" render-id ")")))})
|
||||
shape (assoc shape :fills (:fills data))]
|
||||
|
||||
[:& (mf/provider muc/render-ctx) {:value (str render-id "_" (:id shape) "_" index)}
|
||||
[:& (mf/provider muc/render-ctx) {:key index :value (str render-id "_" (:id shape) "_" index)}
|
||||
[:& shape-custom-strokes {:shape shape :position index :render-id render-id}
|
||||
[:> :text props (:text data)]]]))]]))
|
||||
|
||||
|
|
|
@ -82,7 +82,6 @@
|
|||
|
||||
frame? (= :frame type)
|
||||
group? (= :group type)
|
||||
text? (= :text type)
|
||||
mask? (and group? masked-group?)]
|
||||
|
||||
(cond
|
||||
|
@ -104,10 +103,6 @@
|
|||
(dom/query-all shape-defs ".svg-def")
|
||||
(dom/query-all shape-defs ".svg-mask-wrapper")))
|
||||
|
||||
text?
|
||||
[shape-node
|
||||
(dom/query shape-node ".text-shape")]
|
||||
|
||||
:else
|
||||
[shape-node])))
|
||||
|
||||
|
@ -177,8 +172,7 @@
|
|||
(cond
|
||||
;; Text shapes need special treatment because their resize only change
|
||||
;; the text area, not the change size/position
|
||||
(or (dom/class? node "text-shape")
|
||||
(dom/class? node "frame-thumbnail"))
|
||||
(dom/class? node "frame-thumbnail")
|
||||
(let [[transform] (transform-no-resize shape transform modifiers)]
|
||||
(set-transform-att! node "transform" transform))
|
||||
|
||||
|
@ -233,7 +227,13 @@
|
|||
(fn []
|
||||
(when (some? modifiers)
|
||||
(d/mapm (fn [id {modifiers :modifiers}]
|
||||
(let [center (gsh/center-shape (get objects id))]
|
||||
(let [shape (get objects id)
|
||||
center (gsh/center-shape shape)
|
||||
modifiers (cond-> modifiers
|
||||
;; For texts we only use the displacement because
|
||||
;; resize needs to recalculate the text layout
|
||||
(= :text (:type shape))
|
||||
(select-keys [:displacement :rotation]))]
|
||||
(gsh/modifiers->transform center modifiers)))
|
||||
modifiers))))
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
(ns app.main.ui.workspace.shapes.text
|
||||
(:require
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.math :as mth]
|
||||
[app.main.data.workspace.texts :as dwt]
|
||||
[app.main.refs :as refs]
|
||||
|
@ -32,24 +33,23 @@
|
|||
(dwt/apply-text-modifier text-modifier))]
|
||||
|
||||
[:> shape-container {:shape shape}
|
||||
[:*
|
||||
[:g.text-shape
|
||||
[:& text/text-shape {:shape shape}]]
|
||||
[:g.text-shape {:key (dm/str "text-" (:id shape))}
|
||||
[:& text/text-shape {:shape shape}]]
|
||||
|
||||
(when (and (debug? :text-outline) (d/not-empty? (:position-data shape)))
|
||||
(for [data (:position-data shape)]
|
||||
(let [{:keys [x y width height]} data]
|
||||
[:*
|
||||
;; Text fragment bounding box
|
||||
[:rect {:x x
|
||||
:y (- y height)
|
||||
:width width
|
||||
:height height
|
||||
:style {:fill "none" :stroke "red"}}]
|
||||
(when (and (debug? :text-outline) (d/not-empty? (:position-data shape)))
|
||||
(for [[index data] (d/enumerate (:position-data shape))]
|
||||
(let [{:keys [x y width height]} data]
|
||||
[:g {:key (dm/str index)}
|
||||
;; Text fragment bounding box
|
||||
[:rect {:x x
|
||||
:y (- y height)
|
||||
:width width
|
||||
:height height
|
||||
:style {:fill "none" :stroke "red"}}]
|
||||
|
||||
;; Text baselineazo
|
||||
[:line {:x1 (mth/round x)
|
||||
:y1 (mth/round (- (:y data) (:height data)))
|
||||
:x2 (mth/round (+ x width))
|
||||
:y2 (mth/round (- (:y data) (:height data)))
|
||||
:style {:stroke "blue"}}]])))]]))
|
||||
;; Text baselineazo
|
||||
[:line {:x1 (mth/round x)
|
||||
:y1 (mth/round (- (:y data) (:height data)))
|
||||
:x2 (mth/round (+ x width))
|
||||
:y2 (mth/round (- (:y data) (:height data)))
|
||||
:style {:stroke "blue"}}]])))]))
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
[app.common.attrs :as attrs]
|
||||
[app.common.data :as d]
|
||||
[app.common.data.macros :as dm]
|
||||
[app.common.geom.shapes :as gsh]
|
||||
[app.common.math :as mth]
|
||||
[app.common.pages.helpers :as cph]
|
||||
[app.common.text :as txt]
|
||||
|
@ -28,6 +29,15 @@
|
|||
(defn strip-position-data [shape]
|
||||
(dissoc shape :position-data :transform :transform-inverse))
|
||||
|
||||
(defn process-shape [modifiers {:keys [id] :as shape}]
|
||||
(let [modifier (get modifiers id)
|
||||
modifier (d/update-when modifier :modifiers dissoc :displacement :rotation)
|
||||
shape (cond-> shape
|
||||
(not (gsh/empty-modifiers? modifier))
|
||||
(-> (assoc :grow-type :fixed)
|
||||
(merge modifier) gsh/transform-shape))]
|
||||
(strip-position-data shape)))
|
||||
|
||||
(defn- update-with-editor-state
|
||||
"Updates the shape with the current state in the editor"
|
||||
[shape editor-state]
|
||||
|
@ -88,7 +98,6 @@
|
|||
(fn [node]
|
||||
(when (some? node)
|
||||
(on-update shape node))))]
|
||||
|
||||
[:& fo/text-shape {:key (str "shape-" (:id shape))
|
||||
:ref handle-update
|
||||
:shape shape
|
||||
|
@ -120,7 +129,7 @@
|
|||
|
||||
[:*
|
||||
(for [{:keys [id] :as shape} changed-texts]
|
||||
[:& text-container {:shape shape
|
||||
[:& text-container {:shape (gsh/transform-shape shape)
|
||||
:on-update handle-update-shape
|
||||
:key (str (dm/str "text-container-" id))}])]))
|
||||
|
||||
|
@ -151,24 +160,30 @@
|
|||
|
||||
(defn check-props
|
||||
[new-props old-props]
|
||||
(and (identical? (unchecked-get new-props "objects") (unchecked-get old-props "objects"))
|
||||
(= (unchecked-get new-props "edition") (unchecked-get old-props "edition"))))
|
||||
(and (identical? (unchecked-get new-props "objects")
|
||||
(unchecked-get old-props "objects"))
|
||||
(identical? (unchecked-get new-props "modifiers")
|
||||
(unchecked-get old-props "modifiers"))
|
||||
(= (unchecked-get new-props "edition")
|
||||
(unchecked-get old-props "edition"))))
|
||||
|
||||
(mf/defc viewport-texts
|
||||
{::mf/wrap-props false
|
||||
::mf/wrap [#(mf/memo' % check-props)]}
|
||||
[props]
|
||||
(let [objects (obj/get props "objects")
|
||||
edition (obj/get props "edition")
|
||||
|
||||
xf-texts (comp (filter (comp cph/text-shape? second))
|
||||
(map (fn [[id shape]]
|
||||
[id (strip-position-data shape)])))
|
||||
(let [objects (obj/get props "objects")
|
||||
edition (obj/get props "edition")
|
||||
modifiers (obj/get props "modifiers")
|
||||
|
||||
text-shapes
|
||||
(mf/use-memo
|
||||
(mf/deps objects)
|
||||
#(into {} xf-texts objects))
|
||||
#(into {} (filter (comp cph/text-shape? second)) objects))
|
||||
|
||||
text-shapes
|
||||
(mf/use-memo
|
||||
(mf/deps text-shapes modifiers)
|
||||
#(d/update-vals text-shapes (partial process-shape modifiers)))
|
||||
|
||||
editing-shape (get text-shapes edition)]
|
||||
|
||||
|
@ -183,4 +198,6 @@
|
|||
[:*
|
||||
(when editing-shape
|
||||
[:& viewport-text-editing {:shape editing-shape}])
|
||||
[:& viewport-texts-wrapper {:text-shapes (dissoc text-shapes edition)}]]))
|
||||
|
||||
[:& viewport-texts-wrapper {:text-shapes (dissoc text-shapes edition)
|
||||
:modifiers modifiers}]]))
|
||||
|
|
|
@ -246,6 +246,7 @@
|
|||
[:& stv/viewport-texts {:key (dm/str "texts-" page-id)
|
||||
:page-id page-id
|
||||
:objects base-objects
|
||||
:modifiers modifiers
|
||||
:edition edition}]]]
|
||||
|
||||
[:svg.viewport-controls
|
||||
|
|
Loading…
Add table
Reference in a new issue