Ability to add multiple fills to a shape

This commit is contained in:
Alejandro Alonso 2022-02-04 09:53:42 +01:00 committed by Alonso Torres
parent aecb8a1464
commit 23a9c74297
25 changed files with 475 additions and 243 deletions

View file

@ -79,14 +79,15 @@
"z")}))
attrs))
(defn add-fill [attrs shape render-id]
(let [fill-attrs (cond
(defn add-fill [attrs shape render-id index]
(let [
fill-attrs (cond
(contains? shape :fill-image)
(let [fill-image-id (str "fill-image-" render-id)]
{:fill (str/format "url(#%s)" fill-image-id)})
(contains? shape :fill-color-gradient)
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id)]
(let [fill-color-gradient-id (str "fill-color-gradient_" render-id "_" index)]
{:fill (str/format "url(#%s)" fill-color-gradient-id)})
(contains? shape :fill-color)
@ -193,9 +194,23 @@
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))]
(add-layer-props shape))
styles (cond (or (some? (:fill-image shape))
(= :image (:type shape))
(> (count (:fills shape)) 1)
(some #(some? (:fill-color-gradient %)) (:fills shape)))
(obj/set! styles "fill" (str "url(#fill-" render-id ")"))
;; imported svgs can have fill and fill-opacity attributes
(obj/contains? svg-styles "fill")
(-> styles
(obj/set! "fill" (obj/get svg-styles "fill"))
(obj/set! "fillOpacity" (obj/get svg-styles "fillOpacity")))
:else
(add-fill styles (get-in shape [:fills 0]) render-id 0))]
(-> props
(obj/merge! svg-attrs)
@ -208,10 +223,10 @@
(add-style-attrs shape)))
(defn extract-fill-attrs
[shape]
[shape index]
(let [render-id (mf/use-ctx muc/render-ctx)
fill-styles (-> (obj/get shape "style" (obj/new))
(add-fill shape render-id))]
(add-fill shape render-id index))]
(-> (obj/new)
(obj/set! "style" fill-styles))))

View file

@ -103,11 +103,6 @@
(-> (add! :rx)
(add! :ry)))
(cond-> image?
(-> (add! :fill-color)
(add! :fill-opacity)
(add! :fill-color-gradient)))
(cond-> path?
(-> (add! :stroke-cap-start)
(add! :stroke-cap-end)))
@ -293,6 +288,7 @@
:penpot:background-overlay ((d/nilf str) (:background-overlay interaction))
:penpot:preserve-scroll ((d/nilf str) (:preserve-scroll interaction))}])])))
(mf/defc export-data
[{:keys [shape]}]
(let [props (-> (obj/new) (add-data shape) (add-library-refs shape))]

View file

@ -1,46 +0,0 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.main.ui.shapes.fill-image
(:require
[app.common.geom.shapes :as gsh]
[app.config :as cfg]
[app.main.ui.shapes.attrs :as attrs]
[app.main.ui.shapes.embed :as embed]
[app.util.object :as obj]
[rumext.alpha :as mf]))
(mf/defc fill-image-pattern
{::mf/wrap-props false}
[props]
(let [shape (obj/get props "shape")
render-id (obj/get props "render-id")]
(when (contains? shape :fill-image)
(let [{:keys [x y width height]} (:selrect shape)
fill-image-id (str "fill-image-" render-id)
uri (cfg/resolve-file-media (:fill-image shape))
embed (embed/use-data-uris [uri])
transform (gsh/transform-matrix shape)
shape-without-image (dissoc shape :fill-image)
fill-attrs (-> (attrs/extract-fill-attrs shape-without-image)
(obj/set! "width" width)
(obj/set! "height" height))]
[:pattern {:id fill-image-id
:patternUnits "userSpaceOnUse"
:x x
:y y
:height height
:width width
:patternTransform transform
:data-loading (str (not (contains? embed uri)))}
[:g
[:> :rect fill-attrs]
[:image {:xlinkHref (get embed uri uri)
:width width
:height height}]
]]))))

View file

@ -0,0 +1,64 @@
;; This Source Code Form is subject to the terms of the Mozilla Public
;; License, v. 2.0. If a copy of the MPL was not distributed with this
;; file, You can obtain one at http://mozilla.org/MPL/2.0/.
;;
;; Copyright (c) UXBOX Labs SL
(ns app.main.ui.shapes.fills
(:require
[app.common.data :as d]
[app.common.geom.shapes :as gsh]
[app.config :as cfg]
[app.main.ui.shapes.attrs :as attrs]
[app.main.ui.shapes.embed :as embed]
[app.main.ui.shapes.gradients :as grad]
[app.util.object :as obj]
[rumext.alpha :as mf]))
(mf/defc fills
{::mf/wrap-props false}
[props]
(let [shape (obj/get props "shape")
render-id (obj/get props "render-id")
{:keys [x y width height]} (:selrect shape)
{:keys [metadata]} shape
fill-id (str "fill-" render-id)
has-image (or metadata (:fill-image shape))
uri (if metadata
(cfg/resolve-file-media metadata)
(cfg/resolve-file-media (:fill-image shape)))
embed (embed/use-data-uris [uri])
transform (gsh/transform-matrix shape)
pattern-attrs (cond-> #js {:id fill-id
:patternUnits "userSpaceOnUse"
:x x
:y y
:height height
:width width
:data-loading (str (not (contains? embed uri)))}
(= :path (:type shape))
(obj/set! "patternTransform" transform))]
[:*
(for [[index value] (-> (d/enumerate (:fills shape [])) reverse)]
(cond (some? (:fill-color-gradient value))
(case (:type (:fill-color-gradient value))
:linear [:> grad/linear-gradient #js {:id (str (name :fill-color-gradient) "_" render-id "_" index)
:gradient (:fill-color-gradient value)
:shape shape}]
:radial [:> grad/radial-gradient #js {:id (str (name :fill-color-gradient) "_" render-id "_" index)
:gradient (:fill-color-gradient value)
:shape shape}])))
[:> :pattern pattern-attrs
[:g
(for [[index value] (-> (d/enumerate (:fills shape [])) reverse)]
[:> :rect (-> (attrs/extract-fill-attrs value index)
(obj/set! "width" width)
(obj/set! "height" height))])
(when has-image
[:image {:xlinkHref (get embed uri uri)
:width width
:height height}])]]]))

View file

@ -51,10 +51,6 @@
shape (unchecked-get props "shape")
{:keys [x y width height]} shape
has-background? (or (some? (:fill-color shape))
(some? (:fill-color-gradient shape)))
has-stroke? (not= :none (:stroke-style shape))
props (-> (attrs/extract-style-attrs shape)
(obj/merge!
#js {:x x
@ -63,8 +59,8 @@
:height height
:className "frame-background"}))]
[:*
(when (or has-background? has-stroke?)
[:> :rect props])
[:> :rect props]
(for [item childs]
[:& shape-wrapper {:shape item
:key (:id item)}])])))

View file

@ -7,11 +7,8 @@
(ns app.main.ui.shapes.image
(:require
[app.common.geom.shapes :as gsh]
[app.config :as cfg]
[app.main.ui.context :as muc]
[app.main.ui.shapes.attrs :as attrs]
[app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
[app.main.ui.shapes.embed :as embed]
[app.util.object :as obj]
[rumext.alpha :as mf]))
@ -20,19 +17,8 @@
[props]
(let [shape (unchecked-get props "shape")
{:keys [x y width height metadata]} shape
uri (cfg/resolve-file-media metadata)
embed (embed/use-data-uris [uri])
{:keys [x y width height]} shape
transform (gsh/transform-matrix shape)
fill-attrs (-> (attrs/extract-fill-attrs shape)
(obj/set! "width" width)
(obj/set! "height" height))
render-id (mf/use-ctx muc/render-ctx)
fill-image-id (str "fill-image-" render-id)
shape (assoc shape :fill-image fill-image-id)
props (-> (attrs/extract-style-attrs shape)
(obj/merge! (attrs/extract-border-radius-attrs shape))
(obj/merge!
@ -44,19 +30,6 @@
path? (some? (.-d props))]
[:g
[:defs
[:pattern {:id fill-image-id
:patternUnits "userSpaceOnUse"
:x x
:y y
:height height
:width width
:data-loading (str (not (contains? embed uri)))}
[:g
[:> :rect fill-attrs]
[:image {:xlinkHref (get embed uri uri)
:width width
:height height}]]]]
[:& shape-custom-stroke {:shape shape}
(if path?
[:> :path props]

View file

@ -13,8 +13,6 @@
[app.util.path.format :as upf]
[rumext.alpha :as mf]))
;; --- Path Shape
(mf/defc path-shape
{::mf/wrap-props false}
[props]

View file

@ -12,7 +12,7 @@
[app.main.ui.shapes.attrs :as attrs]
[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.fills :as fills]
[app.main.ui.shapes.filters :as filters]
[app.main.ui.shapes.frame :as frame]
[app.main.ui.shapes.gradients :as grad]
@ -63,9 +63,12 @@
[:defs
[:& defs/svg-defs {:shape shape :render-id render-id}]
[:& filters/filters {:shape shape :filter-id filter-id}]
[:& grad/gradient {:shape shape :attr :fill-color-gradient}]
[:& grad/gradient {:shape shape :attr :stroke-color-gradient}]
[:& fim/fill-image-pattern {:shape shape :render-id render-id}]
(when (or (some? (:fill-image shape))
(= :image (:type shape))
(> (count (:fills shape)) 1)
(some :fill-color-gradient (:fills shape)))
[:& fills/fills {:shape shape :render-id render-id}])
[:& cs/stroke-defs {:shape shape :render-id render-id}]
[:& frame/frame-clip-def {:shape shape :render-id render-id}]]
children]]))