🎉 Add stroke properties to image shape

This commit is contained in:
Alejandro Alonso 2022-01-28 13:39:17 +01:00 committed by Andrey Antukh
parent 0f459ede50
commit acc3d00fd5
6 changed files with 75 additions and 25 deletions

View file

@ -6,6 +6,7 @@
### :sparkles: New features ### :sparkles: New features
- Add stroke properties for image shapes [Taiga #497](https://tree.taiga.io/project/penpot/us/497)
- On user settings, hide the theme selector as long as we only have one theme [Taiga #2610](https://tree.taiga.io/project/penpot/us/2610) - On user settings, hide the theme selector as long as we only have one theme [Taiga #2610](https://tree.taiga.io/project/penpot/us/2610)
- Automatically open comments from dashboard notifications [Taiga #2605](https://tree.taiga.io/project/penpot/us/2605) - Automatically open comments from dashboard notifications [Taiga #2605](https://tree.taiga.io/project/penpot/us/2605)
- Enhance the behaviour of the artboards list on view mode [Taiga #2634](https://tree.taiga.io/project/penpot/us/2634) - Enhance the behaviour of the artboards list on view mode [Taiga #2634](https://tree.taiga.io/project/penpot/us/2634)

View file

@ -81,6 +81,10 @@
(defn add-fill [attrs shape render-id] (defn add-fill [attrs shape render-id]
(let [fill-attrs (cond (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) (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)]
{:fill (str/format "url(#%s)" fill-color-gradient-id)}) {:fill (str/format "url(#%s)" fill-color-gradient-id)})
@ -88,14 +92,10 @@
(contains? shape :fill-color) (contains? shape :fill-color)
{:fill (:fill-color shape)} {:fill (:fill-color shape)}
(contains? shape :fill-image)
(let [fill-image-id (str "fill-image-" render-id)]
{:fill (str/format "url(#%s)" fill-image-id) })
;; If contains svg-attrs the origin is svg. If it's not svg origin ;; If contains svg-attrs the origin is svg. If it's not svg origin
;; we setup the default fill as transparent (instead of black) ;; we setup the default fill as transparent (instead of black)
(and (not (contains? shape :svg-attrs)) (and (not (contains? shape :svg-attrs))
(not (#{ :svg-raw :group } (:type shape)))) (not (#{:svg-raw :group} (:type shape))))
{:fill "none"} {:fill "none"}
:else :else
@ -206,3 +206,11 @@
[shape] [shape]
(-> (obj/new) (-> (obj/new)
(add-style-attrs shape))) (add-style-attrs shape)))
(defn extract-fill-attrs
[shape]
(let [render-id (mf/use-ctx muc/render-ctx)
fill-styles (-> (obj/get shape "style" (obj/new))
(add-fill shape render-id))]
(-> (obj/new)
(obj/set! "style" fill-styles))))

View file

@ -8,6 +8,7 @@
(:require (:require
[app.common.geom.shapes :as gsh] [app.common.geom.shapes :as gsh]
[app.config :as cfg] [app.config :as cfg]
[app.main.ui.shapes.attrs :as attrs]
[app.main.ui.shapes.embed :as embed] [app.main.ui.shapes.embed :as embed]
[app.util.object :as obj] [app.util.object :as obj]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
@ -23,7 +24,11 @@
fill-image-id (str "fill-image-" render-id) fill-image-id (str "fill-image-" render-id)
uri (cfg/resolve-file-media (:fill-image shape)) uri (cfg/resolve-file-media (:fill-image shape))
embed (embed/use-data-uris [uri]) embed (embed/use-data-uris [uri])
transform (gsh/transform-matrix shape)] 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 [:pattern {:id fill-image-id
:patternUnits "userSpaceOnUse" :patternUnits "userSpaceOnUse"
@ -33,6 +38,9 @@
:width width :width width
:patternTransform transform :patternTransform transform
:data-loading (str (not (contains? embed uri)))} :data-loading (str (not (contains? embed uri)))}
[:image {:xlinkHref (get embed uri uri) [:g
:width width [:> :rect fill-attrs]
:height height}]])))) [:image {:xlinkHref (get embed uri uri)
:width width
:height height}]
]]))))

View file

@ -6,11 +6,12 @@
(ns app.main.ui.shapes.image (ns app.main.ui.shapes.image
(:require (:require
[app.common.geom.shapes :as geom] [app.common.geom.shapes :as gsh]
[app.config :as cfg] [app.config :as cfg]
[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-stroke]]
[app.main.ui.shapes.embed :as embed] [app.main.ui.shapes.embed :as embed]
[app.util.dom :as dom]
[app.util.object :as obj] [app.util.object :as obj]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
@ -23,22 +24,36 @@
uri (cfg/resolve-file-media metadata) uri (cfg/resolve-file-media metadata)
embed (embed/use-data-uris [uri]) embed (embed/use-data-uris [uri])
transform (geom/transform-matrix 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) props (-> (attrs/extract-style-attrs shape)
(obj/merge! (obj/merge!
#js {:x x #js {:x x
:y y :y y
:transform transform :transform transform
:width width :width width
:height height :height height}))]
:preserveAspectRatio "none"
:data-loading (str (not (contains? embed uri)))}))
on-drag-start (fn [event] [:g
;; Prevent browser dragging of the image [:defs
(dom/prevent-default event))] [:pattern {:id fill-image-id
:patternUnits "userSpaceOnUse"
[:> "image" (obj/merge! :x x
props :y y
#js {:xlinkHref (get embed uri uri) :height height
:onDragStart on-drag-start})])) :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}
[:> :rect props]]]))

View file

@ -7,6 +7,7 @@
(ns app.main.ui.shapes.path (ns app.main.ui.shapes.path
(:require (:require
[app.common.logging :as log] [app.common.logging :as log]
[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-stroke]] [app.main.ui.shapes.custom-stroke :refer [shape-custom-stroke]]
[app.util.object :as obj] [app.util.object :as obj]
@ -18,7 +19,10 @@
(mf/defc path-shape (mf/defc path-shape
{::mf/wrap-props false} {::mf/wrap-props false}
[props] [props]
(let [shape (unchecked-get props "shape") (let [shape (-> (unchecked-get props "shape")
(dissoc :fill-color)
(dissoc :fill-opacity)
(dissoc :fill-image))
content (:content shape) content (:content shape)
pdata (mf/with-memo [content] pdata (mf/with-memo [content]
(try (try
@ -30,6 +34,8 @@
:cause e) :cause e)
""))) "")))
render-id (mf/use-ctx muc/render-ctx)
shape (assoc shape :fill-image (str "fill-image-" render-id))
props (-> (attrs/extract-style-attrs shape) props (-> (attrs/extract-style-attrs shape)
(obj/set! "d" pdata))] (obj/set! "d" pdata))]

View file

@ -8,9 +8,11 @@
(:require (:require
[app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]] [app.main.ui.workspace.sidebar.options.menus.blur :refer [blur-menu]]
[app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]] [app.main.ui.workspace.sidebar.options.menus.constraints :refer [constraint-attrs constraints-menu]]
[app.main.ui.workspace.sidebar.options.menus.fill :refer [fill-attrs fill-menu]]
[app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]] [app.main.ui.workspace.sidebar.options.menus.layer :refer [layer-attrs layer-menu]]
[app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu]] [app.main.ui.workspace.sidebar.options.menus.measures :refer [measure-attrs measures-menu]]
[app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu]] [app.main.ui.workspace.sidebar.options.menus.shadow :refer [shadow-menu]]
[app.main.ui.workspace.sidebar.options.menus.stroke :refer [stroke-attrs stroke-menu]]
[rumext.alpha :as mf])) [rumext.alpha :as mf]))
(mf/defc options (mf/defc options
@ -19,7 +21,9 @@
type (:type shape) type (:type shape)
measure-values (select-keys shape measure-attrs) measure-values (select-keys shape measure-attrs)
layer-values (select-keys shape layer-attrs) layer-values (select-keys shape layer-attrs)
constraint-values (select-keys shape constraint-attrs)] constraint-values (select-keys shape constraint-attrs)
fill-values (select-keys shape fill-attrs)
stroke-values (select-keys shape stroke-attrs)]
[:* [:*
[:& measures-menu {:ids ids [:& measures-menu {:ids ids
:type type :type type
@ -32,6 +36,14 @@
:type type :type type
:values layer-values}] :values layer-values}]
[:& fill-menu {:ids ids
:type type
:values fill-values}]
[:& stroke-menu {:ids ids
:type type
:values stroke-values}]
[:& shadow-menu {:ids ids [:& shadow-menu {:ids ids
:values (select-keys shape [:shadow])}] :values (select-keys shape [:shadow])}]