From 40b7cafacce3afe8114c59f356c92feb05bd02b5 Mon Sep 17 00:00:00 2001 From: "alonso.torres" Date: Mon, 21 Feb 2022 13:33:17 +0100 Subject: [PATCH] :sparkles: Fix problems with strokes --- .../src/app/main/ui/shapes/custom_stroke.cljs | 78 +++++++++++-------- frontend/src/app/main/ui/shapes/shape.cljs | 2 - .../src/app/main/ui/shapes/text/svg_text.cljs | 2 +- 3 files changed, 45 insertions(+), 37 deletions(-) diff --git a/frontend/src/app/main/ui/shapes/custom_stroke.cljs b/frontend/src/app/main/ui/shapes/custom_stroke.cljs index 04e688a6fa..3300bda301 100644 --- a/frontend/src/app/main/ui/shapes/custom_stroke.cljs +++ b/frontend/src/app/main/ui/shapes/custom_stroke.cljs @@ -6,7 +6,6 @@ (ns app.main.ui.shapes.custom-stroke (:require - [app.common.data :as d] [app.common.geom.shapes :as gsh] [app.main.ui.context :as muc] [app.util.object :as obj] @@ -25,16 +24,18 @@ (-> props (obj/merge #js {:style style})))) (mf/defc inner-stroke-clip-path - [{:keys [render-id]}] - (let [clip-id (str "inner-stroke-" render-id) - shape-id (str "stroke-shape-" render-id)] + [{:keys [shape render-id index]}] + (let [suffix (if index (str "-" index) "") + 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} [:use {:xlinkHref (str "#" shape-id)}]])) (mf/defc outer-stroke-mask - [{:keys [shape render-id]}] - (let [stroke-mask-id (str "outer-stroke-" render-id) - shape-id (str "stroke-shape-" render-id) + [{:keys [shape render-id index]}] + (let [suffix (if index (str "-" index) "") + 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) :center (/ (:stroke-width shape 0) 2) :outer (:stroke-width shape 0) @@ -44,7 +45,8 @@ :style #js {:fill "none" :stroke "white" :strokeWidth (* stroke-width 2)}}] [:use {:xlinkHref (str "#" shape-id) - :style #js {:fill "black"}}]])) + :style #js {:fill "black" + :stroke "none"}}]])) (mf/defc cap-markers [{:keys [shape render-id]}] @@ -149,7 +151,7 @@ [:rect {:x 3 :y 2.5 :width 0.5 :height 1}]])])) (mf/defc stroke-defs - [{:keys [shape render-id]}] + [{:keys [shape render-id index]}] (let [open-path? (and (= :path (:type shape)) (gsh/open-path? shape))] (cond @@ -157,18 +159,21 @@ (= :inner (:stroke-alignment shape :center)) (> (:stroke-width shape 0) 0)) [:& inner-stroke-clip-path {:shape shape - :render-id render-id}] + :render-id render-id + :index index}] (and (not open-path?) (= :outer (:stroke-alignment shape :center)) (> (:stroke-width shape 0) 0)) [:& outer-stroke-mask {:shape shape - :render-id render-id}] + :render-id render-id + :index index}] (or (some? (:stroke-cap-start shape)) (some? (:stroke-cap-end shape))) [:& cap-markers {:shape shape - :render-id render-id}]))) + :render-id render-id + :index index}]))) ;; Outer alignment: display the shape in two layers. One ;; without stroke (only fill), and another one only with stroke @@ -179,40 +184,41 @@ {::mf/wrap-props false} [props] - (let [render-id (mf/use-ctx muc/render-ctx) - child (obj/get props "children") - base-props (obj/get child "props") - elem-name (obj/get child "type") - stroke-mask-id (str "outer-stroke-" render-id) - shape-id (str "stroke-shape-" render-id) + (let [render-id (mf/use-ctx muc/render-ctx) + child (obj/get props "children") + base-props (obj/get child "props") + elem-name (obj/get child "type") + shape (obj/get props "shape") + index (obj/get props "index") + stroke-width (:stroke-width shape) - style-str (->> (obj/get base-props "style") - (js->clj) - (mapv (fn [[k v]] - (-> (d/name k) - (str/kebab) - (str ":" v)))) - (str/join ";"))] + suffix (if index (str "-" index) "") + stroke-mask-id (str "outer-stroke-" render-id "-" (:id shape) suffix) + shape-id (str "stroke-shape-" render-id "-" (:id shape) suffix)] [:g.outer-stroke-shape [:defs + [:& stroke-defs {:shape shape :render-id render-id :index index}] [:> elem-name (-> (obj/clone base-props) (obj/set! "id" shape-id) - (obj/set! "data-style" style-str) - (obj/without ["style"]))]] + (obj/set! + "style" + (-> (obj/get base-props "style") + (obj/clone) + (obj/without ["fill" "fillOpacity" "stroke" "strokeWidth" "strokeOpacity" "strokeStyle" "strokeDasharray"]))))]] [:use {:xlinkHref (str "#" shape-id) :mask (str "url(#" stroke-mask-id ")") :style (-> (obj/get base-props "style") (obj/clone) - (obj/update! "strokeWidth" * 2) + (obj/set! "strokeWidth" (* stroke-width 2)) (obj/without ["fill" "fillOpacity"]) (obj/set! "fill" "none"))}] [:use {:xlinkHref (str "#" shape-id) :style (-> (obj/get base-props "style") (obj/clone) - (obj/without ["stroke" "strokeWidth" "strokeOpacity" "strokeStyle" "strokeDasharray"]))}]])) + (obj/set! "stroke" "none"))}]])) ;; Inner alignment: display the shape with double width stroke, @@ -225,12 +231,14 @@ base-props (obj/get child "props") elem-name (obj/get child "type") shape (obj/get props "shape") + index (obj/get props "index") transform (obj/get base-props "transform") stroke-width (:stroke-width shape 0) - clip-id (str "inner-stroke-" render-id) - shape-id (str "stroke-shape-" render-id) + suffix (if index (str "-" index) "") + 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 "')") shape-props (-> base-props @@ -240,12 +248,12 @@ [:g.inner-stroke-shape {:transform transform} [:defs + [:& stroke-defs {:shape shape :render-id render-id :index index}] [:> elem-name shape-props]] [:use {:xlinkHref (str "#" shape-id) :clipPath clip-path}]])) - ; The SVG standard does not implement yet the 'stroke-alignment' ; attribute, to define the position of the stroke relative to the ; stroke axis (inner, center, outer). Here we implement a patch to be @@ -254,8 +262,10 @@ (mf/defc shape-custom-stroke {::mf/wrap-props false} [props] + (let [child (obj/get props "children") shape (obj/get props "shape") + index (obj/get props "index") stroke-width (:stroke-width shape 0) stroke-style (:stroke-style shape :none) stroke-position (:stroke-alignment shape :center) @@ -268,11 +278,11 @@ (cond (and has-stroke? inner? closed?) - [:& inner-stroke {:shape shape} + [:& inner-stroke {:shape shape :index index} child] (and has-stroke? outer? closed?) - [:& outer-stroke {:shape shape} + [:& outer-stroke {:shape shape :index index} child] :else diff --git a/frontend/src/app/main/ui/shapes/shape.cljs b/frontend/src/app/main/ui/shapes/shape.cljs index 33ee5c8be4..5a036c82fb 100644 --- a/frontend/src/app/main/ui/shapes/shape.cljs +++ b/frontend/src/app/main/ui/shapes/shape.cljs @@ -10,7 +10,6 @@ [app.common.uuid :as uuid] [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.export :as ed] [app.main.ui.shapes.fills :as fills] [app.main.ui.shapes.filters :as filters] @@ -69,6 +68,5 @@ (> (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]])) diff --git a/frontend/src/app/main/ui/shapes/text/svg_text.cljs b/frontend/src/app/main/ui/shapes/text/svg_text.cljs index cd729f181b..e41564a954 100644 --- a/frontend/src/app/main/ui/shapes/text/svg_text.cljs +++ b/frontend/src/app/main/ui/shapes/text/svg_text.cljs @@ -60,7 +60,7 @@ :direction (if (:rtl? data) "rtl" "ltr") :whiteSpace "pre"} (attrs/add-fill data (get-gradient-id index)))})] - [:& shape-custom-stroke {:shape shape} + [:& shape-custom-stroke {:shape shape :index index} [:> :text props (:text data)]]))]]))