Add import blend modes

This commit is contained in:
alonso.torres 2021-06-08 12:23:50 +02:00
parent 0647fa832a
commit e880d94f51
6 changed files with 101 additions and 79 deletions

View file

@ -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)))))

View file

@ -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)}])]]))))

View file

@ -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")]

View file

@ -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])

View file

@ -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}]]]))))

View file

@ -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)