Fix problems with strokes

This commit is contained in:
alonso.torres 2022-02-21 13:33:17 +01:00
parent 82c6b8daae
commit 40b7cafacc
3 changed files with 45 additions and 37 deletions

View file

@ -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
@ -183,36 +188,37 @@
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

View file

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

View file

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