mirror of
https://github.com/penpot/penpot.git
synced 2025-05-25 15:36:11 +02:00
✨ Fix problems with strokes
This commit is contained in:
parent
82c6b8daae
commit
40b7cafacc
3 changed files with 45 additions and 37 deletions
|
@ -6,7 +6,6 @@
|
||||||
|
|
||||||
(ns app.main.ui.shapes.custom-stroke
|
(ns app.main.ui.shapes.custom-stroke
|
||||||
(:require
|
(:require
|
||||||
[app.common.data :as d]
|
|
||||||
[app.common.geom.shapes :as gsh]
|
[app.common.geom.shapes :as gsh]
|
||||||
[app.main.ui.context :as muc]
|
[app.main.ui.context :as muc]
|
||||||
[app.util.object :as obj]
|
[app.util.object :as obj]
|
||||||
|
@ -25,16 +24,18 @@
|
||||||
(-> props (obj/merge #js {:style style}))))
|
(-> props (obj/merge #js {:style style}))))
|
||||||
|
|
||||||
(mf/defc inner-stroke-clip-path
|
(mf/defc inner-stroke-clip-path
|
||||||
[{:keys [render-id]}]
|
[{:keys [shape render-id index]}]
|
||||||
(let [clip-id (str "inner-stroke-" render-id)
|
(let [suffix (if index (str "-" index) "")
|
||||||
shape-id (str "stroke-shape-" render-id)]
|
clip-id (str "inner-stroke-" render-id "-" (:id shape) suffix)
|
||||||
|
shape-id (str "stroke-shape-" render-id "-" (:id shape) suffix)]
|
||||||
[:> "clipPath" #js {:id clip-id}
|
[:> "clipPath" #js {:id clip-id}
|
||||||
[:use {:xlinkHref (str "#" shape-id)}]]))
|
[:use {:xlinkHref (str "#" shape-id)}]]))
|
||||||
|
|
||||||
(mf/defc outer-stroke-mask
|
(mf/defc outer-stroke-mask
|
||||||
[{:keys [shape render-id]}]
|
[{:keys [shape render-id index]}]
|
||||||
(let [stroke-mask-id (str "outer-stroke-" render-id)
|
(let [suffix (if index (str "-" index) "")
|
||||||
shape-id (str "stroke-shape-" render-id)
|
stroke-mask-id (str "outer-stroke-" render-id "-" (:id shape) suffix)
|
||||||
|
shape-id (str "stroke-shape-" render-id "-" (:id shape) suffix)
|
||||||
stroke-width (case (:stroke-alignment shape :center)
|
stroke-width (case (:stroke-alignment shape :center)
|
||||||
:center (/ (:stroke-width shape 0) 2)
|
:center (/ (:stroke-width shape 0) 2)
|
||||||
:outer (:stroke-width shape 0)
|
:outer (:stroke-width shape 0)
|
||||||
|
@ -44,7 +45,8 @@
|
||||||
:style #js {:fill "none" :stroke "white" :strokeWidth (* stroke-width 2)}}]
|
:style #js {:fill "none" :stroke "white" :strokeWidth (* stroke-width 2)}}]
|
||||||
|
|
||||||
[:use {:xlinkHref (str "#" shape-id)
|
[:use {:xlinkHref (str "#" shape-id)
|
||||||
:style #js {:fill "black"}}]]))
|
:style #js {:fill "black"
|
||||||
|
:stroke "none"}}]]))
|
||||||
|
|
||||||
(mf/defc cap-markers
|
(mf/defc cap-markers
|
||||||
[{:keys [shape render-id]}]
|
[{:keys [shape render-id]}]
|
||||||
|
@ -149,7 +151,7 @@
|
||||||
[:rect {:x 3 :y 2.5 :width 0.5 :height 1}]])]))
|
[:rect {:x 3 :y 2.5 :width 0.5 :height 1}]])]))
|
||||||
|
|
||||||
(mf/defc stroke-defs
|
(mf/defc stroke-defs
|
||||||
[{:keys [shape render-id]}]
|
[{:keys [shape render-id index]}]
|
||||||
|
|
||||||
(let [open-path? (and (= :path (:type shape)) (gsh/open-path? shape))]
|
(let [open-path? (and (= :path (:type shape)) (gsh/open-path? shape))]
|
||||||
(cond
|
(cond
|
||||||
|
@ -157,18 +159,21 @@
|
||||||
(= :inner (:stroke-alignment shape :center))
|
(= :inner (:stroke-alignment shape :center))
|
||||||
(> (:stroke-width shape 0) 0))
|
(> (:stroke-width shape 0) 0))
|
||||||
[:& inner-stroke-clip-path {:shape shape
|
[:& inner-stroke-clip-path {:shape shape
|
||||||
:render-id render-id}]
|
:render-id render-id
|
||||||
|
:index index}]
|
||||||
|
|
||||||
(and (not open-path?)
|
(and (not open-path?)
|
||||||
(= :outer (:stroke-alignment shape :center))
|
(= :outer (:stroke-alignment shape :center))
|
||||||
(> (:stroke-width shape 0) 0))
|
(> (:stroke-width shape 0) 0))
|
||||||
[:& outer-stroke-mask {:shape shape
|
[:& outer-stroke-mask {:shape shape
|
||||||
:render-id render-id}]
|
:render-id render-id
|
||||||
|
:index index}]
|
||||||
|
|
||||||
(or (some? (:stroke-cap-start shape))
|
(or (some? (:stroke-cap-start shape))
|
||||||
(some? (:stroke-cap-end shape)))
|
(some? (:stroke-cap-end shape)))
|
||||||
[:& cap-markers {:shape shape
|
[:& cap-markers {:shape shape
|
||||||
:render-id render-id}])))
|
:render-id render-id
|
||||||
|
:index index}])))
|
||||||
|
|
||||||
;; Outer alignment: display the shape in two layers. One
|
;; Outer alignment: display the shape in two layers. One
|
||||||
;; without stroke (only fill), and another one only with stroke
|
;; without stroke (only fill), and another one only with stroke
|
||||||
|
@ -179,40 +184,41 @@
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
|
|
||||||
(let [render-id (mf/use-ctx muc/render-ctx)
|
(let [render-id (mf/use-ctx muc/render-ctx)
|
||||||
child (obj/get props "children")
|
child (obj/get props "children")
|
||||||
base-props (obj/get child "props")
|
base-props (obj/get child "props")
|
||||||
elem-name (obj/get child "type")
|
elem-name (obj/get child "type")
|
||||||
stroke-mask-id (str "outer-stroke-" render-id)
|
shape (obj/get props "shape")
|
||||||
shape-id (str "stroke-shape-" render-id)
|
index (obj/get props "index")
|
||||||
|
stroke-width (:stroke-width shape)
|
||||||
|
|
||||||
style-str (->> (obj/get base-props "style")
|
suffix (if index (str "-" index) "")
|
||||||
(js->clj)
|
stroke-mask-id (str "outer-stroke-" render-id "-" (:id shape) suffix)
|
||||||
(mapv (fn [[k v]]
|
shape-id (str "stroke-shape-" render-id "-" (:id shape) suffix)]
|
||||||
(-> (d/name k)
|
|
||||||
(str/kebab)
|
|
||||||
(str ":" v))))
|
|
||||||
(str/join ";"))]
|
|
||||||
|
|
||||||
[:g.outer-stroke-shape
|
[:g.outer-stroke-shape
|
||||||
[:defs
|
[:defs
|
||||||
|
[:& stroke-defs {:shape shape :render-id render-id :index index}]
|
||||||
[:> elem-name (-> (obj/clone base-props)
|
[:> elem-name (-> (obj/clone base-props)
|
||||||
(obj/set! "id" shape-id)
|
(obj/set! "id" shape-id)
|
||||||
(obj/set! "data-style" style-str)
|
(obj/set!
|
||||||
(obj/without ["style"]))]]
|
"style"
|
||||||
|
(-> (obj/get base-props "style")
|
||||||
|
(obj/clone)
|
||||||
|
(obj/without ["fill" "fillOpacity" "stroke" "strokeWidth" "strokeOpacity" "strokeStyle" "strokeDasharray"]))))]]
|
||||||
|
|
||||||
[:use {:xlinkHref (str "#" shape-id)
|
[:use {:xlinkHref (str "#" shape-id)
|
||||||
:mask (str "url(#" stroke-mask-id ")")
|
:mask (str "url(#" stroke-mask-id ")")
|
||||||
:style (-> (obj/get base-props "style")
|
:style (-> (obj/get base-props "style")
|
||||||
(obj/clone)
|
(obj/clone)
|
||||||
(obj/update! "strokeWidth" * 2)
|
(obj/set! "strokeWidth" (* stroke-width 2))
|
||||||
(obj/without ["fill" "fillOpacity"])
|
(obj/without ["fill" "fillOpacity"])
|
||||||
(obj/set! "fill" "none"))}]
|
(obj/set! "fill" "none"))}]
|
||||||
|
|
||||||
[:use {:xlinkHref (str "#" shape-id)
|
[:use {:xlinkHref (str "#" shape-id)
|
||||||
:style (-> (obj/get base-props "style")
|
:style (-> (obj/get base-props "style")
|
||||||
(obj/clone)
|
(obj/clone)
|
||||||
(obj/without ["stroke" "strokeWidth" "strokeOpacity" "strokeStyle" "strokeDasharray"]))}]]))
|
(obj/set! "stroke" "none"))}]]))
|
||||||
|
|
||||||
|
|
||||||
;; Inner alignment: display the shape with double width stroke,
|
;; Inner alignment: display the shape with double width stroke,
|
||||||
|
@ -225,12 +231,14 @@
|
||||||
base-props (obj/get child "props")
|
base-props (obj/get child "props")
|
||||||
elem-name (obj/get child "type")
|
elem-name (obj/get child "type")
|
||||||
shape (obj/get props "shape")
|
shape (obj/get props "shape")
|
||||||
|
index (obj/get props "index")
|
||||||
transform (obj/get base-props "transform")
|
transform (obj/get base-props "transform")
|
||||||
|
|
||||||
stroke-width (:stroke-width shape 0)
|
stroke-width (:stroke-width shape 0)
|
||||||
|
|
||||||
clip-id (str "inner-stroke-" render-id)
|
suffix (if index (str "-" index) "")
|
||||||
shape-id (str "stroke-shape-" render-id)
|
clip-id (str "inner-stroke-" render-id "-" (:id shape) suffix)
|
||||||
|
shape-id (str "stroke-shape-" render-id "-" (:id shape) suffix)
|
||||||
|
|
||||||
clip-path (str "url('#" clip-id "')")
|
clip-path (str "url('#" clip-id "')")
|
||||||
shape-props (-> base-props
|
shape-props (-> base-props
|
||||||
|
@ -240,12 +248,12 @@
|
||||||
|
|
||||||
[:g.inner-stroke-shape {:transform transform}
|
[:g.inner-stroke-shape {:transform transform}
|
||||||
[:defs
|
[:defs
|
||||||
|
[:& stroke-defs {:shape shape :render-id render-id :index index}]
|
||||||
[:> elem-name shape-props]]
|
[:> elem-name shape-props]]
|
||||||
|
|
||||||
[:use {:xlinkHref (str "#" shape-id)
|
[:use {:xlinkHref (str "#" shape-id)
|
||||||
:clipPath clip-path}]]))
|
:clipPath clip-path}]]))
|
||||||
|
|
||||||
|
|
||||||
; The SVG standard does not implement yet the 'stroke-alignment'
|
; The SVG standard does not implement yet the 'stroke-alignment'
|
||||||
; attribute, to define the position of the stroke relative to the
|
; attribute, to define the position of the stroke relative to the
|
||||||
; stroke axis (inner, center, outer). Here we implement a patch to be
|
; stroke axis (inner, center, outer). Here we implement a patch to be
|
||||||
|
@ -254,8 +262,10 @@
|
||||||
(mf/defc shape-custom-stroke
|
(mf/defc shape-custom-stroke
|
||||||
{::mf/wrap-props false}
|
{::mf/wrap-props false}
|
||||||
[props]
|
[props]
|
||||||
|
|
||||||
(let [child (obj/get props "children")
|
(let [child (obj/get props "children")
|
||||||
shape (obj/get props "shape")
|
shape (obj/get props "shape")
|
||||||
|
index (obj/get props "index")
|
||||||
stroke-width (:stroke-width shape 0)
|
stroke-width (:stroke-width shape 0)
|
||||||
stroke-style (:stroke-style shape :none)
|
stroke-style (:stroke-style shape :none)
|
||||||
stroke-position (:stroke-alignment shape :center)
|
stroke-position (:stroke-alignment shape :center)
|
||||||
|
@ -268,11 +278,11 @@
|
||||||
|
|
||||||
(cond
|
(cond
|
||||||
(and has-stroke? inner? closed?)
|
(and has-stroke? inner? closed?)
|
||||||
[:& inner-stroke {:shape shape}
|
[:& inner-stroke {:shape shape :index index}
|
||||||
child]
|
child]
|
||||||
|
|
||||||
(and has-stroke? outer? closed?)
|
(and has-stroke? outer? closed?)
|
||||||
[:& outer-stroke {:shape shape}
|
[:& outer-stroke {:shape shape :index index}
|
||||||
child]
|
child]
|
||||||
|
|
||||||
:else
|
:else
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
[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.attrs :as attrs]
|
||||||
[app.main.ui.shapes.custom-stroke :as cs]
|
|
||||||
[app.main.ui.shapes.export :as ed]
|
[app.main.ui.shapes.export :as ed]
|
||||||
[app.main.ui.shapes.fills :as fills]
|
[app.main.ui.shapes.fills :as fills]
|
||||||
[app.main.ui.shapes.filters :as filters]
|
[app.main.ui.shapes.filters :as filters]
|
||||||
|
@ -69,6 +68,5 @@
|
||||||
(> (count (:fills shape)) 1)
|
(> (count (:fills shape)) 1)
|
||||||
(some :fill-color-gradient (:fills shape)))
|
(some :fill-color-gradient (:fills shape)))
|
||||||
[:& fills/fills {:shape shape :render-id render-id}])
|
[:& 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}]]
|
[:& frame/frame-clip-def {:shape shape :render-id render-id}]]
|
||||||
children]]))
|
children]]))
|
||||||
|
|
|
@ -60,7 +60,7 @@
|
||||||
:direction (if (:rtl? data) "rtl" "ltr")
|
:direction (if (:rtl? data) "rtl" "ltr")
|
||||||
:whiteSpace "pre"}
|
:whiteSpace "pre"}
|
||||||
(attrs/add-fill data (get-gradient-id index)))})]
|
(attrs/add-fill data (get-gradient-id index)))})]
|
||||||
[:& shape-custom-stroke {:shape shape}
|
[:& shape-custom-stroke {:shape shape :index index}
|
||||||
[:> :text props (:text data)]]))]]))
|
[:> :text props (:text data)]]))]]))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue