diff --git a/common/app/common/geom/shapes.cljc b/common/app/common/geom/shapes.cljc index 50d9e07bb..f99994ee7 100644 --- a/common/app/common/geom/shapes.cljc +++ b/common/app/common/geom/shapes.cljc @@ -266,6 +266,7 @@ (d/export gpr/points->selrect) (d/export gtr/transform-shape) (d/export gtr/transform-matrix) +(d/export gtr/inverse-transform-matrix) (d/export gtr/transform-point-center) (d/export gtr/transform-rect) (d/export gtr/update-group-selrect) diff --git a/common/app/common/geom/shapes/transforms.cljc b/common/app/common/geom/shapes/transforms.cljc index d126c8cdd..698524501 100644 --- a/common/app/common/geom/shapes/transforms.cljc +++ b/common/app/common/geom/shapes/transforms.cljc @@ -38,6 +38,18 @@ (and (not no-flip) flip-y) (gmt/scale (gpt/point 1 -1))) (gmt/translate (gpt/negate shape-center)))))) +(defn inverse-transform-matrix + ([shape] + (let [shape-center (or (gco/center-shape shape) + (gpt/point 0 0))] + (inverse-transform-matrix shape shape-center))) + ([shape center] + (let [] + (-> (gmt/matrix) + (gmt/translate center) + (gmt/multiply (:transform-inverse shape (gmt/matrix))) + (gmt/translate (gpt/negate center)))))) + (defn transform-point-center "Transform a point around the shape center" [point center matrix] @@ -257,6 +269,30 @@ apply-transform-rect)] (apply-transform-fn shape transform))) +(defn transform-gradients [shape modifiers] + (let [angle (d/check-num (get modifiers :rotation)) + ;; Gradients are represented with unit vectors so its center is 0.5, 0.5 + center (gpt/point 0.5 0.5) + transform (gmt/rotate-matrix angle center) + transform-gradient + (fn [{:keys [start-x start-y end-x end-y] :as gradient}] + (let [start-point (gpt/point start-x start-y) + end-point (gpt/point end-x end-y) + {start-x :x start-y :y} (gpt/transform start-point transform) + {end-x :x end-y :y} (gpt/transform end-point transform)] + + (assoc gradient + :start-x start-x + :start-y start-y + :end-x end-x + :end-y end-y)))] + (cond-> shape + (:fill-color-gradient shape) + (update :fill-color-gradient transform-gradient) + + (:stroke-color-gradient shape) + (update :stroke-color-gradient transform-gradient)))) + (defn set-flip [shape modifiers] (let [rx (get-in modifiers [:resize-vector :x]) ry (get-in modifiers [:resize-vector :y])] @@ -271,6 +307,7 @@ (-> shape (set-flip (:modifiers shape)) (apply-transform transform) + (transform-gradients (:modifiers shape)) (dissoc :modifiers))) shape))) @@ -296,3 +333,4 @@ (assoc :selrect new-selrect) (assoc :points new-points) (apply-transform-rect (gmt/matrix))))) + diff --git a/frontend/src/app/main/ui/shapes/gradients.cljs b/frontend/src/app/main/ui/shapes/gradients.cljs index 7d60bb88d..fe10056a9 100644 --- a/frontend/src/app/main/ui/shapes/gradients.cljs +++ b/frontend/src/app/main/ui/shapes/gradients.cljs @@ -14,15 +14,21 @@ [app.util.object :as obj] [app.common.uuid :as uuid] [app.main.ui.context :as muc] - [app.common.geom.point :as gpt])) + [app.common.geom.point :as gpt] + [app.common.geom.matrix :as gmt] + [app.common.geom.shapes :as gsh])) (mf/defc linear-gradient [{:keys [id gradient shape]}] - (let [{:keys [x y width height]} shape] + (let [{:keys [x y width height]} (:selrect shape) + transform (case (:type shape) + :path (gmt/matrix) + (gsh/inverse-transform-matrix shape (gpt/point 0.5 0.5)))] [:linearGradient {:id id :x1 (:start-x gradient) :y1 (:start-y gradient) :x2 (:end-x gradient) - :y2 (:end-y gradient)} + :y2 (:end-y gradient) + :gradient-transform transform} (for [{:keys [offset color opacity]} (:stops gradient)] [:stop {:key (str id "-stop-" offset) :offset (or offset 0) @@ -30,7 +36,10 @@ :stop-opacity opacity}])])) (mf/defc radial-gradient [{:keys [id gradient shape]}] - (let [{:keys [x y width height]} shape] + (let [{:keys [x y width height]} (:selrect shape) + transform (case (:type shape) + :path (gmt/matrix) + (gsh/inverse-transform-matrix shape))] (let [[x y] (if (= (:type shape) :frame) [0 0] [x y]) translate-vec (gpt/point (+ x (* width (:start-x gradient))) (+ y (* height (:start-y gradient)))) @@ -51,10 +60,10 @@ scale-vec (gpt/point (* scale-factor-y (/ height 2)) (* scale-factor-x (/ width 2))) - tr-translate (str/fmt "translate(%s, %s)" (:x translate-vec) (:y translate-vec)) - tr-rotate (str/fmt "rotate(%s)" angle) - tr-scale (str/fmt "scale(%s, %s)" (:x scale-vec) (:y scale-vec)) - transform (str/fmt "%s %s %s" tr-translate tr-rotate tr-scale)] + transform (gmt/multiply transform + (gmt/translate-matrix translate-vec) + (gmt/rotate-matrix angle) + (gmt/scale-matrix scale-vec))] [:radialGradient {:id id :cx 0 :cy 0