mirror of
https://github.com/penpot/penpot.git
synced 2025-05-21 20:26:13 +02:00
🐛 Add shadow to artboard make it lose the fill
This commit is contained in:
parent
e601e2acca
commit
3a9d348cab
10 changed files with 113 additions and 52 deletions
|
@ -42,6 +42,7 @@
|
||||||
|
|
||||||
### :bug: Bugs fixed
|
### :bug: Bugs fixed
|
||||||
|
|
||||||
|
- Add shadow to artboard make it lose the fill [Taiga #3139](https://tree.taiga.io/project/penpot/issue/3139)
|
||||||
- Avoid numeric inputs to change its value without focusing them [Taiga #3140](https://tree.taiga.io/project/penpot/issue/3140)
|
- Avoid numeric inputs to change its value without focusing them [Taiga #3140](https://tree.taiga.io/project/penpot/issue/3140)
|
||||||
- Fix comments modal when changing pages [Taiga #2597](https://tree.taiga.io/project/penpot/issue/2508)
|
- Fix comments modal when changing pages [Taiga #2597](https://tree.taiga.io/project/penpot/issue/2508)
|
||||||
- Copy paste inside a text layer leaves pasted text transparent [Taiga #3096](https://tree.taiga.io/project/penpot/issue/3096)
|
- Copy paste inside a text layer leaves pasted text transparent [Taiga #3096](https://tree.taiga.io/project/penpot/issue/3096)
|
||||||
|
|
|
@ -33,10 +33,10 @@
|
||||||
(let [xf-get-bounds (comp (map #(get objects %)) (map #(calc-bounds % objects)))
|
(let [xf-get-bounds (comp (map #(get objects %)) (map #(calc-bounds % objects)))
|
||||||
padding (filters/calculate-padding object)
|
padding (filters/calculate-padding object)
|
||||||
obj-bounds (-> (filters/get-filters-bounds object)
|
obj-bounds (-> (filters/get-filters-bounds object)
|
||||||
(update :x - padding)
|
(update :x - (:horizontal padding))
|
||||||
(update :y - padding)
|
(update :y - (:vertical padding))
|
||||||
(update :width + (* 2 padding))
|
(update :width + (* 2 (:horizontal padding)))
|
||||||
(update :height + (* 2 padding)))]
|
(update :height + (* 2 (:vertical padding))))]
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(and (= :group (:type object))
|
(and (= :group (:type object))
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.common.pages.helpers :as cph]
|
||||||
[app.main.ui.context :as muc]
|
[app.main.ui.context :as muc]
|
||||||
[app.main.ui.shapes.attrs :as attrs]
|
[app.main.ui.shapes.attrs :as attrs]
|
||||||
[app.main.ui.shapes.gradients :as grad]
|
[app.main.ui.shapes.gradients :as grad]
|
||||||
|
@ -327,8 +328,12 @@
|
||||||
(obj/clone))
|
(obj/clone))
|
||||||
|
|
||||||
props (cond-> props
|
props (cond-> props
|
||||||
(d/not-empty? (:shadow shape))
|
(or
|
||||||
(obj/set! "filter" (dm/fmt "url(#filter_%)" render-id)))
|
;; There are any shadows
|
||||||
|
(and (d/not-empty? (:shadow shape)) (not (cph/frame-shape? shape)))
|
||||||
|
;; There are no strokes and a blur
|
||||||
|
(and (some? (:blur shape)) (not (cph/frame-shape? shape)) (empty? (:strokes shape))))
|
||||||
|
(obj/set! "filter" (dm/fmt "url(#filter_%)" render-id)))
|
||||||
|
|
||||||
svg-defs (:svg-defs shape {})
|
svg-defs (:svg-defs shape {})
|
||||||
svg-attrs (:svg-attrs shape {})
|
svg-attrs (:svg-attrs shape {})
|
||||||
|
@ -391,7 +396,19 @@
|
||||||
(obj/set! "fillOpacity" "none")))
|
(obj/set! "fillOpacity" "none")))
|
||||||
(add-style (obj/get (attrs/extract-stroke-attrs value position render-id) "style")))))
|
(add-style (obj/get (attrs/extract-stroke-attrs value position render-id) "style")))))
|
||||||
|
|
||||||
(mf/defc shape-custom-strokes
|
|
||||||
|
(mf/defc shape-fills
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[props]
|
||||||
|
(let [child (obj/get props "children")
|
||||||
|
shape (obj/get props "shape")
|
||||||
|
elem-name (obj/get child "type")
|
||||||
|
render-id (mf/use-ctx muc/render-ctx)]
|
||||||
|
|
||||||
|
[:g {:id (dm/fmt "fills-%" (:id shape))}
|
||||||
|
[:> elem-name (build-fill-props shape child render-id)]]))
|
||||||
|
|
||||||
|
(mf/defc shape-strokes
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
(let [child (obj/get props "children")
|
(let [child (obj/get props "children")
|
||||||
|
@ -401,13 +418,9 @@
|
||||||
stroke-props (-> (obj/new)
|
stroke-props (-> (obj/new)
|
||||||
(obj/set! "id" (dm/fmt "strokes-%" (:id shape)))
|
(obj/set! "id" (dm/fmt "strokes-%" (:id shape)))
|
||||||
(cond->
|
(cond->
|
||||||
(some? (:blur shape))
|
(and (some? (:blur shape)) (not (cph/frame-shape? shape)))
|
||||||
(obj/set! "filter" (dm/fmt "url(#filter_blur_%)" render-id))))]
|
(obj/set! "filter" (dm/fmt "url(#filter_blur_%)" render-id))))]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:g {:id (dm/fmt "fills-%" (:id shape))}
|
|
||||||
[:> elem-name (build-fill-props shape child render-id)]]
|
|
||||||
|
|
||||||
(when
|
(when
|
||||||
(d/not-empty? (:strokes shape))
|
(d/not-empty? (:strokes shape))
|
||||||
[:> :g stroke-props
|
[:> :g stroke-props
|
||||||
|
@ -416,3 +429,16 @@
|
||||||
shape (assoc value :points (:points shape))]
|
shape (assoc value :points (:points shape))]
|
||||||
[:& shape-custom-stroke {:shape shape :index index}
|
[:& shape-custom-stroke {:shape shape :index index}
|
||||||
[:> elem-name props]]))])]))
|
[:> elem-name props]]))])]))
|
||||||
|
|
||||||
|
(mf/defc shape-custom-strokes
|
||||||
|
{::mf/wrap-props false}
|
||||||
|
[props]
|
||||||
|
(let [child (obj/get props "children")
|
||||||
|
shape (obj/get props "shape")]
|
||||||
|
|
||||||
|
[:*
|
||||||
|
[:& shape-fills {:shape shape}
|
||||||
|
child]
|
||||||
|
|
||||||
|
[:& shape-strokes {:shape shape}
|
||||||
|
child]]))
|
||||||
|
|
|
@ -170,7 +170,6 @@
|
||||||
([shape filters blur-value]
|
([shape filters blur-value]
|
||||||
|
|
||||||
(let [svg-root? (and (= :svg-raw (:type shape)) (not= :svg (get-in shape [:content :tag])))
|
(let [svg-root? (and (= :svg-raw (:type shape)) (not= :svg (get-in shape [:content :tag])))
|
||||||
frame? (= :frame (:type shape))
|
|
||||||
{:keys [x y width height]} (:selrect shape)]
|
{:keys [x y width height]} (:selrect shape)]
|
||||||
(if svg-root?
|
(if svg-root?
|
||||||
;; When is a raw-svg but not the root we use the whole svg as bound for the filter. Is the maximum
|
;; When is a raw-svg but not the root we use the whole svg as bound for the filter. Is the maximum
|
||||||
|
@ -183,6 +182,7 @@
|
||||||
(map (partial filter-bounds shape)))
|
(map (partial filter-bounds shape)))
|
||||||
;; We add the selrect so the minimum size will be the selrect
|
;; We add the selrect so the minimum size will be the selrect
|
||||||
filter-bounds (conj filter-bounds (-> shape :points gsh/points->selrect))
|
filter-bounds (conj filter-bounds (-> shape :points gsh/points->selrect))
|
||||||
|
|
||||||
x1 (apply min (map :x1 filter-bounds))
|
x1 (apply min (map :x1 filter-bounds))
|
||||||
y1 (apply min (map :y1 filter-bounds))
|
y1 (apply min (map :y1 filter-bounds))
|
||||||
x2 (apply max (map :x2 filter-bounds))
|
x2 (apply max (map :x2 filter-bounds))
|
||||||
|
@ -195,18 +195,30 @@
|
||||||
|
|
||||||
;; We should move the frame filter coordinates because they should be
|
;; We should move the frame filter coordinates because they should be
|
||||||
;; relative with the frame. By default they come as absolute
|
;; relative with the frame. By default they come as absolute
|
||||||
{:x (if frame? (- x1 x) x1)
|
{:x x1
|
||||||
:y (if frame? (- y1 y) y1)
|
:y y1
|
||||||
:width (- x2 x1)
|
:width (- x2 x1)
|
||||||
:height (- y2 y1)})))))
|
:height (- y2 y1)})))))
|
||||||
|
|
||||||
(defn calculate-padding [shape]
|
(defn calculate-padding [shape]
|
||||||
(let [stroke-width (apply max 0 (map #(case (:stroke-alignment % :center)
|
(let [stroke-width (apply max 0 (map #(case (:stroke-alignment % :center)
|
||||||
:center (/ (:stroke-width % 0) 2)
|
:center (/ (:stroke-width % 0) 2)
|
||||||
:outer (:stroke-width % 0)
|
:outer (:stroke-width % 0)
|
||||||
0) (:strokes shape)))
|
0) (:strokes shape)))
|
||||||
margin (apply max 0 (map #(gsh/shape-stroke-margin % stroke-width) (:strokes shape)))]
|
|
||||||
(+ stroke-width margin)))
|
margin (apply max 0 (map #(gsh/shape-stroke-margin % stroke-width) (:strokes shape)))
|
||||||
|
|
||||||
|
|
||||||
|
shadow-width (apply max 0 (map #(case (:style % :drop-shadow)
|
||||||
|
:drop-shadow (+ (mth/abs (:offset-x %)) (* (:spread %) 2) (* (:blur %) 2) 10)
|
||||||
|
0) (:shadow shape)))
|
||||||
|
|
||||||
|
shadow-height (apply max 0 (map #(case (:style % :drop-shadow)
|
||||||
|
:drop-shadow (+ (mth/abs (:offset-y %)) (* (:spread %) 2) (* (:blur %) 2) 10)
|
||||||
|
0) (:shadow shape)))]
|
||||||
|
|
||||||
|
{:horizontal (+ stroke-width margin shadow-width)
|
||||||
|
:vertical (+ stroke-width margin shadow-height)}))
|
||||||
|
|
||||||
(defn change-filter-in
|
(defn change-filter-in
|
||||||
"Adds the previous filter as `filter-in` parameter"
|
"Adds the previous filter as `filter-in` parameter"
|
||||||
|
@ -220,10 +232,10 @@
|
||||||
bounds (get-filters-bounds shape filters (or (-> shape :blur :value) 0))
|
bounds (get-filters-bounds shape filters (or (-> shape :blur :value) 0))
|
||||||
padding (calculate-padding shape)
|
padding (calculate-padding shape)
|
||||||
selrect (:selrect shape)
|
selrect (:selrect shape)
|
||||||
filter-x (/ (- (:x bounds) (:x selrect) padding) (:width selrect))
|
filter-x (/ (- (:x bounds) (:x selrect) (:horizontal padding)) (:width selrect))
|
||||||
filter-y (/ (- (:y bounds) (:y selrect) padding) (:height selrect))
|
filter-y (/ (- (:y bounds) (:y selrect) (:vertical padding)) (:height selrect))
|
||||||
filter-width (/ (+ (:width bounds) (* 2 padding)) (:width selrect))
|
filter-width (/ (+ (:width bounds) (* 2 (:horizontal padding))) (:width selrect))
|
||||||
filter-height (/ (+ (:height bounds) (* 2 padding)) (:height selrect))]
|
filter-height (/ (+ (:height bounds) (* 2 (:vertical padding))) (:height selrect))]
|
||||||
(when (> (count filters) 2)
|
(when (> (count filters) 2)
|
||||||
[:filter {:id filter-id
|
[:filter {:id filter-id
|
||||||
:x filter-x
|
:x filter-x
|
||||||
|
|
|
@ -7,9 +7,10 @@
|
||||||
(ns app.main.ui.shapes.frame
|
(ns app.main.ui.shapes.frame
|
||||||
(:require
|
(:require
|
||||||
[app.common.data.macros :as dm]
|
[app.common.data.macros :as dm]
|
||||||
|
[app.common.geom.shapes :as gsh]
|
||||||
|
[app.main.ui.context :as muc]
|
||||||
[app.main.ui.shapes.attrs :as attrs]
|
[app.main.ui.shapes.attrs :as attrs]
|
||||||
[app.main.ui.shapes.custom-stroke :refer [shape-custom-strokes]]
|
[app.main.ui.shapes.custom-stroke :refer [shape-fills shape-strokes]]
|
||||||
[app.main.ui.shapes.filters :as filters]
|
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[debug :refer [debug?]]
|
[debug :refer [debug?]]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
@ -27,13 +28,12 @@
|
||||||
[{:keys [shape render-id]}]
|
[{:keys [shape render-id]}]
|
||||||
(when (= :frame (:type shape))
|
(when (= :frame (:type shape))
|
||||||
(let [{:keys [x y width height]} shape
|
(let [{:keys [x y width height]} shape
|
||||||
padding (filters/calculate-padding shape)
|
|
||||||
props (-> (attrs/extract-style-attrs shape)
|
props (-> (attrs/extract-style-attrs shape)
|
||||||
(obj/merge!
|
(obj/merge!
|
||||||
#js {:x (- x padding)
|
#js {:x x
|
||||||
:y (- y padding)
|
:y y
|
||||||
:width (+ width (* 2 padding))
|
:width width
|
||||||
:height (+ height (* 2 padding))}))
|
:height height}))
|
||||||
path? (some? (.-d props))]
|
path? (some? (.-d props))]
|
||||||
[:clipPath {:id (frame-clip-id shape render-id) :class "frame-clip"}
|
[:clipPath {:id (frame-clip-id shape render-id) :class "frame-clip"}
|
||||||
(if path?
|
(if path?
|
||||||
|
@ -63,22 +63,32 @@
|
||||||
(let [childs (unchecked-get props "childs")
|
(let [childs (unchecked-get props "childs")
|
||||||
shape (unchecked-get props "shape")
|
shape (unchecked-get props "shape")
|
||||||
{:keys [x y width height]} shape
|
{:keys [x y width height]} shape
|
||||||
|
transform (gsh/transform-matrix shape)
|
||||||
|
|
||||||
props (-> (attrs/extract-style-attrs shape)
|
props (-> (attrs/extract-style-attrs shape)
|
||||||
(obj/merge!
|
(obj/merge!
|
||||||
#js {:x x
|
#js {:x x
|
||||||
:y y
|
:y y
|
||||||
|
:transform transform
|
||||||
:width width
|
:width width
|
||||||
:height height
|
:height height
|
||||||
:className "frame-background"}))
|
:className "frame-background"}))
|
||||||
path? (some? (.-d props))]
|
path? (some? (.-d props))
|
||||||
|
render-id (mf/use-ctx muc/render-ctx)]
|
||||||
|
|
||||||
[:*
|
[:*
|
||||||
[:& shape-custom-strokes {:shape shape}
|
[:g {:clip-path (frame-clip-url shape render-id)}
|
||||||
(if path?
|
[:*
|
||||||
[:> :path props]
|
[:& shape-fills {:shape shape}
|
||||||
[:> :rect props])]
|
(if path?
|
||||||
(for [item childs]
|
[:> :path props]
|
||||||
[:& shape-wrapper {:shape item
|
[:> :rect props])]
|
||||||
:key (dm/str (:id item))}])])))
|
|
||||||
|
(for [item childs]
|
||||||
|
[:& shape-wrapper {:shape item
|
||||||
|
:key (dm/str (:id item))}])
|
||||||
|
[:& shape-strokes {:shape shape}
|
||||||
|
(if path?
|
||||||
|
[:> :path props]
|
||||||
|
[:> :rect props])]]]])))
|
||||||
|
|
||||||
|
|
|
@ -50,14 +50,11 @@
|
||||||
|
|
||||||
wrapper-props
|
wrapper-props
|
||||||
(cond-> wrapper-props
|
(cond-> wrapper-props
|
||||||
(some #(= (:type shape) %) [:group :svg-raw])
|
(some #(= (:type shape) %) [:group :svg-raw :frame])
|
||||||
(obj/set! "filter" (filters/filter-str filter-id shape)))
|
(obj/set! "filter" (filters/filter-str filter-id shape)))
|
||||||
|
|
||||||
wrapper-props
|
wrapper-props
|
||||||
(cond-> wrapper-props
|
(cond-> wrapper-props
|
||||||
(= :frame type)
|
|
||||||
(obj/set! "clipPath" (frame/frame-clip-url shape render-id))
|
|
||||||
|
|
||||||
(= :group type)
|
(= :group type)
|
||||||
(attrs/add-style-attrs shape render-id))]
|
(attrs/add-style-attrs shape render-id))]
|
||||||
|
|
||||||
|
|
|
@ -32,12 +32,17 @@
|
||||||
|
|
||||||
(defn- calculate-size
|
(defn- calculate-size
|
||||||
[frame zoom]
|
[frame zoom]
|
||||||
(let [{:keys [_ _ width height]} (filters/get-filters-bounds frame)]
|
(let [{:keys [_ _ width height]} (filters/get-filters-bounds frame)
|
||||||
|
padding (filters/calculate-padding frame)
|
||||||
|
x (- (:horizontal padding))
|
||||||
|
y (- (:vertical padding))
|
||||||
|
width (+ width (* 2 (:horizontal padding)))
|
||||||
|
height (+ height (* 2 (:vertical padding)))]
|
||||||
{:base-width width
|
{:base-width width
|
||||||
:base-height height
|
:base-height height
|
||||||
:width (* width zoom)
|
:width (* width zoom)
|
||||||
:height (* height zoom)
|
:height (* height zoom)
|
||||||
:vbox (str "0 0 " width " " height)}))
|
:vbox (str x " " y " " width " " height)}))
|
||||||
|
|
||||||
(defn- calculate-wrapper
|
(defn- calculate-wrapper
|
||||||
[size1 size2 zoom]
|
[size1 size2 zoom]
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
(def type->options
|
(def type->options
|
||||||
{:multiple [:fill :stroke :image :text :shadow :blur]
|
{:multiple [:fill :stroke :image :text :shadow :blur]
|
||||||
:frame [:layout :fill :stroke]
|
:frame [:layout :fill :stroke :shadow :blur]
|
||||||
:group [:layout :svg]
|
:group [:layout :svg]
|
||||||
:rect [:layout :fill :stroke :shadow :blur :svg]
|
:rect [:layout :fill :stroke :shadow :blur :svg]
|
||||||
:circle [:layout :fill :stroke :shadow :blur :svg]
|
:circle [:layout :fill :stroke :shadow :blur :svg]
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
[app.main.store :as st]
|
[app.main.store :as st]
|
||||||
[app.main.ui.shapes.bool :as bool]
|
[app.main.ui.shapes.bool :as bool]
|
||||||
[app.main.ui.shapes.circle :as circle]
|
[app.main.ui.shapes.circle :as circle]
|
||||||
|
[app.main.ui.shapes.filters :as filters]
|
||||||
[app.main.ui.shapes.frame :as frame]
|
[app.main.ui.shapes.frame :as frame]
|
||||||
[app.main.ui.shapes.group :as group]
|
[app.main.ui.shapes.group :as group]
|
||||||
[app.main.ui.shapes.image :as image]
|
[app.main.ui.shapes.image :as image]
|
||||||
|
@ -190,9 +191,18 @@
|
||||||
frame (get objects (:id frame))
|
frame (get objects (:id frame))
|
||||||
|
|
||||||
zoom (:zoom local 1)
|
zoom (:zoom local 1)
|
||||||
width (* (:width frame) zoom)
|
|
||||||
height (* (:height frame) zoom)
|
{:keys [_ _ width height]} (filters/get-filters-bounds frame)
|
||||||
vbox (str "0 0 " (:width frame 0) " " (:height frame 0))
|
padding (filters/calculate-padding frame)
|
||||||
|
x (- (:horizontal padding))
|
||||||
|
y (- (:vertical padding))
|
||||||
|
width (+ width (* 2 (:horizontal padding)))
|
||||||
|
height (+ height (* 2 (:vertical padding)))
|
||||||
|
|
||||||
|
vbox (str x " " y " " width " " height)
|
||||||
|
|
||||||
|
width (* width zoom)
|
||||||
|
height (* height zoom)
|
||||||
|
|
||||||
render (mf/use-memo
|
render (mf/use-memo
|
||||||
(mf/deps objects)
|
(mf/deps objects)
|
||||||
|
|
|
@ -403,9 +403,9 @@
|
||||||
modifier-ids (into [frame-id] (cph/get-children-ids objects frame-id))
|
modifier-ids (into [frame-id] (cph/get-children-ids objects frame-id))
|
||||||
objects (reduce update-fn objects modifier-ids)
|
objects (reduce update-fn objects modifier-ids)
|
||||||
frame (assoc-in frame [:modifiers :displacement] modifier)
|
frame (assoc-in frame [:modifiers :displacement] modifier)
|
||||||
|
|
||||||
width (* (:width frame) zoom)
|
width (* (:width frame) zoom)
|
||||||
height (* (:height frame) zoom)
|
height (* (:height frame) zoom)
|
||||||
|
|
||||||
vbox (str "0 0 " (:width frame 0)
|
vbox (str "0 0 " (:width frame 0)
|
||||||
" " (:height frame 0))
|
" " (:height frame 0))
|
||||||
wrapper (mf/use-memo
|
wrapper (mf/use-memo
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue