mirror of
https://github.com/penpot/penpot.git
synced 2025-05-10 23:47:10 +02:00
✨ Add import blend modes
This commit is contained in:
parent
0647fa832a
commit
e880d94f51
6 changed files with 101 additions and 79 deletions
|
@ -141,23 +141,28 @@
|
||||||
styles (-> svg-attrs (:style {}) (clj->js))]
|
styles (-> svg-attrs (:style {}) (clj->js))]
|
||||||
[attrs styles]))
|
[attrs styles]))
|
||||||
|
|
||||||
|
(defn add-style-attrs
|
||||||
|
[props shape]
|
||||||
|
(let [render-id (mf/use-ctx muc/render-ctx)
|
||||||
|
svg-defs (:svg-defs shape {})
|
||||||
|
svg-attrs (:svg-attrs shape {})
|
||||||
|
|
||||||
|
[svg-attrs svg-styles] (mf/use-memo
|
||||||
|
(mf/deps render-id svg-defs svg-attrs)
|
||||||
|
#(extract-svg-attrs render-id svg-defs svg-attrs))
|
||||||
|
|
||||||
|
styles (-> (obj/get props "style" (obj/new))
|
||||||
|
(obj/merge! svg-styles)
|
||||||
|
(add-fill shape render-id)
|
||||||
|
(add-stroke shape render-id)
|
||||||
|
(add-layer-props shape))]
|
||||||
|
|
||||||
|
(-> props
|
||||||
|
(obj/merge! svg-attrs)
|
||||||
|
(add-border-radius shape)
|
||||||
|
(obj/set! "style" styles))))
|
||||||
|
|
||||||
(defn extract-style-attrs
|
(defn extract-style-attrs
|
||||||
([shape]
|
[shape]
|
||||||
(let [render-id (mf/use-ctx muc/render-ctx)
|
(-> (obj/new)
|
||||||
svg-defs (:svg-defs shape {})
|
(add-style-attrs shape)))
|
||||||
svg-attrs (:svg-attrs shape {})
|
|
||||||
|
|
||||||
[svg-attrs svg-styles] (mf/use-memo
|
|
||||||
(mf/deps render-id svg-defs svg-attrs)
|
|
||||||
#(extract-svg-attrs render-id svg-defs svg-attrs))
|
|
||||||
|
|
||||||
styles (-> (obj/new)
|
|
||||||
(obj/merge! svg-styles)
|
|
||||||
(add-fill shape render-id)
|
|
||||||
(add-stroke shape render-id)
|
|
||||||
(add-layer-props shape))]
|
|
||||||
|
|
||||||
(-> (obj/new)
|
|
||||||
(obj/merge! svg-attrs)
|
|
||||||
(add-border-radius shape)
|
|
||||||
(obj/set! "style" styles)))))
|
|
||||||
|
|
|
@ -20,33 +20,29 @@
|
||||||
(let [frame (unchecked-get props "frame")
|
(let [frame (unchecked-get props "frame")
|
||||||
shape (unchecked-get props "shape")
|
shape (unchecked-get props "shape")
|
||||||
childs (unchecked-get props "childs")
|
childs (unchecked-get props "childs")
|
||||||
expand-mask (unchecked-get props "expand-mask")
|
|
||||||
pointer-events (unchecked-get props "pointer-events")
|
pointer-events (unchecked-get props "pointer-events")
|
||||||
|
|
||||||
{:keys [id x y width height]} shape
|
{:keys [id x y width height masked-group?]} shape
|
||||||
|
|
||||||
show-mask? (and (:masked-group? shape) (not expand-mask))
|
[mask childs] (if masked-group?
|
||||||
mask (when show-mask? (first childs))
|
[(first childs) (rest childs)]
|
||||||
childs (if show-mask? (rest childs) childs)
|
[nil childs])
|
||||||
|
|
||||||
mask-props (when (and mask (not expand-mask))
|
[mask-wrapper mask-props]
|
||||||
#js {:clipPath (clip-str mask)
|
(if masked-group?
|
||||||
:mask (mask-str mask)})
|
["g" (-> (obj/new)
|
||||||
mask-wrapper (if (and mask (not expand-mask))
|
(obj/set! "clipPath" (clip-str mask))
|
||||||
"g"
|
(obj/set! "mask" (mask-str mask)))]
|
||||||
mf/Fragment)
|
[mf/Fragment nil])]
|
||||||
|
|
||||||
props (-> (attrs/extract-style-attrs shape))]
|
[:> mask-wrapper mask-props
|
||||||
|
(when masked-group?
|
||||||
|
[:> render-mask #js {:frame frame :mask mask}])
|
||||||
|
|
||||||
[:> :g (attrs/extract-style-attrs shape)
|
(for [item childs]
|
||||||
[:> mask-wrapper mask-props
|
[:& shape-wrapper {:frame frame
|
||||||
(when mask
|
:shape item
|
||||||
[:> render-mask #js {:frame frame :mask mask}])
|
:key (:id item)}])]))))
|
||||||
|
|
||||||
(for [item childs]
|
|
||||||
[:& shape-wrapper {:frame frame
|
|
||||||
:shape item
|
|
||||||
:key (:id item)}])]]))))
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,12 @@
|
||||||
[app.common.data :as d]
|
[app.common.data :as d]
|
||||||
[app.common.uuid :as uuid]
|
[app.common.uuid :as uuid]
|
||||||
[app.main.ui.context :as muc]
|
[app.main.ui.context :as muc]
|
||||||
|
[app.main.ui.shapes.attrs :as attrs]
|
||||||
[app.main.ui.shapes.custom-stroke :as cs]
|
[app.main.ui.shapes.custom-stroke :as cs]
|
||||||
|
[app.main.ui.shapes.export :as ed]
|
||||||
[app.main.ui.shapes.fill-image :as fim]
|
[app.main.ui.shapes.fill-image :as fim]
|
||||||
[app.main.ui.shapes.filters :as filters]
|
[app.main.ui.shapes.filters :as filters]
|
||||||
[app.main.ui.shapes.gradients :as grad]
|
[app.main.ui.shapes.gradients :as grad]
|
||||||
[app.main.ui.shapes.export :as ed]
|
|
||||||
[app.main.ui.shapes.svg-defs :as defs]
|
[app.main.ui.shapes.svg-defs :as defs]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
[rumext.alpha :as mf]))
|
[rumext.alpha :as mf]))
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
|
|
||||||
{:keys [x y width height type]} shape
|
{:keys [x y width height type]} shape
|
||||||
frame? (= :frame type)
|
frame? (= :frame type)
|
||||||
|
group? (= :group type)
|
||||||
|
|
||||||
wrapper-props
|
wrapper-props
|
||||||
(-> (obj/clone props)
|
(-> (obj/clone props)
|
||||||
|
@ -42,16 +44,23 @@
|
||||||
(obj/set! "ref" ref)
|
(obj/set! "ref" ref)
|
||||||
(obj/set! "id" (str "shape-" (:id shape)))
|
(obj/set! "id" (str "shape-" (:id shape)))
|
||||||
(obj/set! "filter" (filters/filter-str filter-id shape))
|
(obj/set! "filter" (filters/filter-str filter-id shape))
|
||||||
(obj/set! "style" styles)
|
(obj/set! "style" styles))
|
||||||
|
|
||||||
(cond-> frame?
|
wrapper-props
|
||||||
(-> (obj/set! "x" x)
|
(cond-> wrapper-props
|
||||||
(obj/set! "y" y)
|
frame?
|
||||||
(obj/set! "width" width)
|
(-> (obj/set! "x" x)
|
||||||
(obj/set! "height" height)
|
(obj/set! "y" y)
|
||||||
(obj/set! "xmlnsXlink" "http://www.w3.org/1999/xlink")
|
(obj/set! "width" width)
|
||||||
(obj/set! "xmlns" "http://www.w3.org/2000/svg")
|
(obj/set! "height" height)
|
||||||
(obj/set! "xmlns:penpot" "https://penpot.app/xmlns"))))
|
(obj/set! "xmlnsXlink" "http://www.w3.org/1999/xlink")
|
||||||
|
(obj/set! "xmlns" "http://www.w3.org/2000/svg")
|
||||||
|
(obj/set! "xmlns:penpot" "https://penpot.app/xmlns")))
|
||||||
|
|
||||||
|
wrapper-props
|
||||||
|
(cond-> wrapper-props
|
||||||
|
group?
|
||||||
|
(attrs/add-style-attrs shape))
|
||||||
|
|
||||||
wrapper-tag (if frame? "svg" "g")]
|
wrapper-tag (if frame? "svg" "g")]
|
||||||
|
|
||||||
|
|
|
@ -83,20 +83,19 @@
|
||||||
(when (and shape (not (:hidden shape)))
|
(when (and shape (not (:hidden shape)))
|
||||||
[:*
|
[:*
|
||||||
(if-not svg-element?
|
(if-not svg-element?
|
||||||
[:g.shape-wrapper
|
(case (:type shape)
|
||||||
(case (:type shape)
|
:path [:> path/path-wrapper opts]
|
||||||
:path [:> path/path-wrapper opts]
|
:text [:> text/text-wrapper opts]
|
||||||
:text [:> text/text-wrapper opts]
|
:group [:> group-wrapper opts]
|
||||||
:group [:> group-wrapper opts]
|
:rect [:> rect-wrapper opts]
|
||||||
:rect [:> rect-wrapper opts]
|
:image [:> image-wrapper opts]
|
||||||
:image [:> image-wrapper opts]
|
:circle [:> circle-wrapper opts]
|
||||||
:circle [:> circle-wrapper opts]
|
:svg-raw [:> svg-raw-wrapper opts]
|
||||||
:svg-raw [:> svg-raw-wrapper opts]
|
|
||||||
|
|
||||||
;; Only used when drawing a new frame.
|
;; Only used when drawing a new frame.
|
||||||
:frame [:> frame-wrapper {:shape shape}]
|
:frame [:> frame-wrapper {:shape shape}]
|
||||||
|
|
||||||
nil)]
|
nil)
|
||||||
|
|
||||||
;; Don't wrap svg elements inside a <g> otherwise some can break
|
;; Don't wrap svg elements inside a <g> otherwise some can break
|
||||||
[:> svg-raw-wrapper opts])
|
[:> svg-raw-wrapper opts])
|
||||||
|
|
|
@ -42,9 +42,8 @@
|
||||||
childs (mf/deref childs-ref)]
|
childs (mf/deref childs-ref)]
|
||||||
|
|
||||||
[:> shape-container {:shape shape}
|
[:> shape-container {:shape shape}
|
||||||
[:g.group-shape
|
[:& group-shape
|
||||||
[:& group-shape
|
{:frame frame
|
||||||
{:frame frame
|
:shape shape
|
||||||
:shape shape
|
:childs childs}]]))))
|
||||||
:childs childs}]]]))))
|
|
||||||
|
|
||||||
|
|
|
@ -96,14 +96,15 @@
|
||||||
(defn get-svg-data
|
(defn get-svg-data
|
||||||
[type node]
|
[type node]
|
||||||
|
|
||||||
(if (search-data-node? type)
|
(let [node-attrs (add-attrs {} (:attrs node))]
|
||||||
(let [data-tags #{:ellipse :rect :path :text :foreignObject :image}]
|
(if (search-data-node? type)
|
||||||
(->> node
|
(let [data-tags #{:ellipse :rect :path :text :foreignObject :image}]
|
||||||
(node-seq)
|
(->> node
|
||||||
(filter #(contains? data-tags (:tag %)))
|
(node-seq)
|
||||||
(map #(:attrs %))
|
(filter #(contains? data-tags (:tag %)))
|
||||||
(reduce add-attrs {})))
|
(map #(:attrs %))
|
||||||
(:attrs node)))
|
(reduce add-attrs node-attrs)))
|
||||||
|
node-attrs)))
|
||||||
|
|
||||||
(def has-position? #{:frame :rect :image :text})
|
(def has-position? #{:frame :rect :image :text})
|
||||||
|
|
||||||
|
@ -188,7 +189,7 @@
|
||||||
(parse-path svg-data)))
|
(parse-path svg-data)))
|
||||||
|
|
||||||
(defn add-fill
|
(defn add-fill
|
||||||
[props type node svg-data]
|
[props node svg-data]
|
||||||
|
|
||||||
(let [fill (:fill svg-data)]
|
(let [fill (:fill svg-data)]
|
||||||
(cond-> props
|
(cond-> props
|
||||||
|
@ -206,7 +207,7 @@
|
||||||
:fill-opacity (-> svg-data (:fill-opacity "1") d/parse-double)))))
|
:fill-opacity (-> svg-data (:fill-opacity "1") d/parse-double)))))
|
||||||
|
|
||||||
(defn add-stroke
|
(defn add-stroke
|
||||||
[props type node svg-data]
|
[props node svg-data]
|
||||||
|
|
||||||
(let [stroke-style (get-meta node :stroke-style keyword)
|
(let [stroke-style (get-meta node :stroke-style keyword)
|
||||||
stroke-alignment (get-meta node :stroke-alignment keyword)
|
stroke-alignment (get-meta node :stroke-alignment keyword)
|
||||||
|
@ -303,6 +304,18 @@
|
||||||
(not (empty? exports))
|
(not (empty? exports))
|
||||||
(assoc :exports exports))))
|
(assoc :exports exports))))
|
||||||
|
|
||||||
|
(defn add-layer-options
|
||||||
|
[props svg-data]
|
||||||
|
(let [blend-mode (get svg-data :mix-blend-mode)
|
||||||
|
opacity (-> (get svg-data :opacity) d/parse-double)]
|
||||||
|
|
||||||
|
(cond-> props
|
||||||
|
(some? blend-mode)
|
||||||
|
(assoc :blend-mode (keyword blend-mode))
|
||||||
|
|
||||||
|
(some? opacity)
|
||||||
|
(assoc :opacity opacity))))
|
||||||
|
|
||||||
(defn get-image-name
|
(defn get-image-name
|
||||||
[node]
|
[node]
|
||||||
(get-in node [:attrs :penpot:name]))
|
(get-in node [:attrs :penpot:name]))
|
||||||
|
@ -325,8 +338,9 @@
|
||||||
|
|
||||||
(-> {}
|
(-> {}
|
||||||
(add-position type node svg-data)
|
(add-position type node svg-data)
|
||||||
(add-fill type node svg-data)
|
(add-fill node svg-data)
|
||||||
(add-stroke type node svg-data)
|
(add-stroke node svg-data)
|
||||||
|
(add-layer-options svg-data)
|
||||||
(add-shadows node)
|
(add-shadows node)
|
||||||
(add-blur node)
|
(add-blur node)
|
||||||
(add-exports node)
|
(add-exports node)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue