mirror of
https://github.com/penpot/penpot.git
synced 2025-06-15 12:01:38 +02:00
♻️ Refactor snap files
This commit is contained in:
parent
69bd4cf4bb
commit
590f9956ad
11 changed files with 128 additions and 96 deletions
|
@ -875,6 +875,8 @@
|
||||||
"en" : "Show rules"
|
"en" : "Show rules"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"workspace.header.menu.disable-dynamic-alignment": "Disable dynamic alignment",
|
||||||
|
"workspace.header.menu.enable-dynamic-alignment": "Enable dynamic aligment",
|
||||||
"workspace.header.viewer" : {
|
"workspace.header.viewer" : {
|
||||||
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:153" ],
|
"used-in" : [ "src/uxbox/main/ui/workspace/header.cljs:153" ],
|
||||||
"translations" : {
|
"translations" : {
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
[uxbox.util.geom.matrix :as gmt]
|
[uxbox.util.geom.matrix :as gmt]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.geom.shapes :as geom]
|
[uxbox.util.geom.shapes :as geom]
|
||||||
[uxbox.util.geom.snap :as snap]
|
|
||||||
[uxbox.util.math :as mth]
|
[uxbox.util.math :as mth]
|
||||||
[uxbox.util.router :as rt]
|
[uxbox.util.router :as rt]
|
||||||
[uxbox.util.transit :as t]
|
[uxbox.util.transit :as t]
|
||||||
|
@ -67,7 +66,7 @@
|
||||||
:layers
|
:layers
|
||||||
:element-options
|
:element-options
|
||||||
:rules
|
:rules
|
||||||
})
|
:dynamic-alignment})
|
||||||
|
|
||||||
(s/def ::options-mode #{:design :prototype})
|
(s/def ::options-mode #{:design :prototype})
|
||||||
|
|
||||||
|
@ -1452,6 +1451,7 @@
|
||||||
"ctrl+shift+i" #(st/emit! (toggle-layout-flag :libraries))
|
"ctrl+shift+i" #(st/emit! (toggle-layout-flag :libraries))
|
||||||
"ctrl+shift+l" #(st/emit! (toggle-layout-flag :layers))
|
"ctrl+shift+l" #(st/emit! (toggle-layout-flag :layers))
|
||||||
"ctrl+shift+r" #(st/emit! (toggle-layout-flag :rules))
|
"ctrl+shift+r" #(st/emit! (toggle-layout-flag :rules))
|
||||||
|
"ctrl+shift+d" #(st/emit! (toggle-layout-flag :dynamic-alignment))
|
||||||
"+" #(st/emit! increase-zoom)
|
"+" #(st/emit! increase-zoom)
|
||||||
"-" #(st/emit! decrease-zoom)
|
"-" #(st/emit! decrease-zoom)
|
||||||
"ctrl+g" #(st/emit! create-group)
|
"ctrl+g" #(st/emit! create-group)
|
||||||
|
|
|
@ -19,8 +19,7 @@
|
||||||
[uxbox.common.uuid :as uuid]
|
[uxbox.common.uuid :as uuid]
|
||||||
[uxbox.main.worker :as uw]
|
[uxbox.main.worker :as uw]
|
||||||
[uxbox.util.timers :as ts]
|
[uxbox.util.timers :as ts]
|
||||||
[uxbox.util.geom.shapes :as geom]
|
[uxbox.util.geom.shapes :as geom]))
|
||||||
[uxbox.util.geom.snap :as snap]))
|
|
||||||
|
|
||||||
;; --- Protocols
|
;; --- Protocols
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
[uxbox.util.geom.matrix :as gmt]
|
[uxbox.util.geom.matrix :as gmt]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.geom.shapes :as gsh]
|
[uxbox.util.geom.shapes :as gsh]
|
||||||
[uxbox.util.geom.snap :as snap]))
|
[uxbox.main.snap :as snap]))
|
||||||
|
|
||||||
;; -- Declarations
|
;; -- Declarations
|
||||||
|
|
||||||
|
@ -145,14 +145,15 @@
|
||||||
initial (handler->initial-point shape handler)
|
initial (handler->initial-point shape handler)
|
||||||
stoper (rx/filter ms/mouse-up? stream)
|
stoper (rx/filter ms/mouse-up? stream)
|
||||||
page-id (get state :current-page-id)
|
page-id (get state :current-page-id)
|
||||||
resizing-shapes (map #(get-in state [:workspace-data page-id :objects %]) ids)]
|
resizing-shapes (map #(get-in state [:workspace-data page-id :objects %]) ids)
|
||||||
|
layout (get state :workspace-layout)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
;; (rx/mapcat apply-grid-alignment)
|
;; (rx/mapcat apply-grid-alignment)
|
||||||
(rx/with-latest vector ms/mouse-position-ctrl)
|
(rx/with-latest vector ms/mouse-position-ctrl)
|
||||||
(rx/map normalize-proportion-lock)
|
(rx/map normalize-proportion-lock)
|
||||||
(rx/switch-map (fn [[point :as current]]
|
(rx/switch-map (fn [[point :as current]]
|
||||||
(->> (snap/closest-snap-point page-id resizing-shapes point)
|
(->> (snap/closest-snap-point page-id resizing-shapes layout point)
|
||||||
(rx/map #(conj current %)))))
|
(rx/map #(conj current %)))))
|
||||||
(rx/mapcat (partial resize shape initial resizing-shapes))
|
(rx/mapcat (partial resize shape initial resizing-shapes))
|
||||||
(rx/take-until stoper))
|
(rx/take-until stoper))
|
||||||
|
@ -231,12 +232,13 @@
|
||||||
(watch [_ state stream]
|
(watch [_ state stream]
|
||||||
(let [page-id (get state :current-page-id)
|
(let [page-id (get state :current-page-id)
|
||||||
shapes (mapv #(get-in state [:workspace-data page-id :objects %]) ids)
|
shapes (mapv #(get-in state [:workspace-data page-id :objects %]) ids)
|
||||||
stopper (rx/filter ms/mouse-up? stream)]
|
stopper (rx/filter ms/mouse-up? stream)
|
||||||
|
layout (get state :workspace-layout)]
|
||||||
(rx/concat
|
(rx/concat
|
||||||
(->> ms/mouse-position
|
(->> ms/mouse-position
|
||||||
(rx/take-until stopper)
|
(rx/take-until stopper)
|
||||||
(rx/map #(gpt/to-vec from-position %))
|
(rx/map #(gpt/to-vec from-position %))
|
||||||
(rx/switch-map #(snap/closest-snap-move page-id shapes %))
|
(rx/switch-map #(snap/closest-snap-move page-id shapes layout %))
|
||||||
(rx/map gmt/translate-matrix)
|
(rx/map gmt/translate-matrix)
|
||||||
(rx/map #(set-modifiers ids {:displacement %})))
|
(rx/map #(set-modifiers ids {:displacement %})))
|
||||||
|
|
||||||
|
|
|
@ -7,66 +7,27 @@
|
||||||
;;
|
;;
|
||||||
;; Copyright (c) 2020 UXBOX Labs SL
|
;; Copyright (c) 2020 UXBOX Labs SL
|
||||||
|
|
||||||
(ns uxbox.util.geom.snap
|
(ns uxbox.main.snap
|
||||||
(:require
|
(:require
|
||||||
[cljs.spec.alpha :as s]
|
|
||||||
[clojure.set :as set]
|
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[uxbox.util.math :as mth]
|
|
||||||
[uxbox.common.uuid :refer [zero]]
|
[uxbox.common.uuid :refer [zero]]
|
||||||
[uxbox.util.geom.shapes :as gsh]
|
[uxbox.util.math :as mth]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.main.worker :as uw]))
|
[uxbox.main.worker :as uw]
|
||||||
|
[uxbox.util.geom.snap-points :as sp]))
|
||||||
|
|
||||||
(def ^:private snap-accuracy 10)
|
(def ^:private snap-accuracy 5)
|
||||||
|
|
||||||
(defn- frame-snap-points [{:keys [x y width height]}]
|
(defn- remove-from-snap-points [ids-to-remove]
|
||||||
#{(gpt/point x y)
|
|
||||||
(gpt/point (+ x (/ width 2)) y)
|
|
||||||
(gpt/point (+ x width) y)
|
|
||||||
(gpt/point (+ x width) (+ y (/ height 2)))
|
|
||||||
(gpt/point (+ x width) (+ y height))
|
|
||||||
(gpt/point (+ x (/ width 2)) (+ y height))
|
|
||||||
(gpt/point x (+ y height))
|
|
||||||
(gpt/point x (+ y (/ height 2)))})
|
|
||||||
|
|
||||||
(defn- frame-snap-points-resize [{:keys [x y width height]} handler]
|
|
||||||
(case handler
|
|
||||||
:top-left (gpt/point x y)
|
|
||||||
:top (gpt/point (+ x (/ width 2)) y)
|
|
||||||
:top-right (gpt/point (+ x width) y)
|
|
||||||
:right (gpt/point (+ x width) (+ y (/ height 2)))
|
|
||||||
:bottom-right (gpt/point (+ x width) (+ y height))
|
|
||||||
:bottom (gpt/point (+ x (/ width 2)) (+ y height))
|
|
||||||
:bottom-left (gpt/point x (+ y height))
|
|
||||||
:left (gpt/point x (+ y (/ height 2)))))
|
|
||||||
|
|
||||||
(def ^:private handler->point-idx
|
|
||||||
{:top-left 0
|
|
||||||
:top 0
|
|
||||||
:top-right 1
|
|
||||||
:right 1
|
|
||||||
:bottom-right 2
|
|
||||||
:bottom 2
|
|
||||||
:bottom-left 3
|
|
||||||
:left 3})
|
|
||||||
|
|
||||||
(defn shape-snap-points
|
|
||||||
[shape]
|
|
||||||
(let [modified-path (gsh/transform-apply-modifiers shape)
|
|
||||||
shape-center (gsh/center modified-path)]
|
|
||||||
(case (:type shape)
|
|
||||||
:frame (-> modified-path gsh/shape->rect-shape frame-snap-points)
|
|
||||||
(:path :curve) (into #{shape-center} (-> modified-path gsh/shape->rect-shape :segments))
|
|
||||||
(into #{shape-center} (-> modified-path :segments)))))
|
|
||||||
|
|
||||||
|
|
||||||
(defn remove-from-snap-points [ids-to-remove]
|
|
||||||
(fn [query-result]
|
(fn [query-result]
|
||||||
(->> query-result
|
(->> query-result
|
||||||
(map (fn [[value data]] [value (remove (comp ids-to-remove second) data)]))
|
(map (fn [[value data]] [value (remove (comp ids-to-remove second) data)]))
|
||||||
(filter (fn [[_ data]] (not (empty? data)))))))
|
(filter (fn [[_ data]] (not (empty? data)))))))
|
||||||
|
|
||||||
|
(defn- flatten-to-points
|
||||||
|
[query-result]
|
||||||
|
(mapcat (fn [[v data]] (map (fn [[point _]] point) data)) query-result))
|
||||||
|
|
||||||
(defn- calculate-distance [query-result point coord]
|
(defn- calculate-distance [query-result point coord]
|
||||||
(->> query-result
|
(->> query-result
|
||||||
(map (fn [[value data]] [(mth/abs (- value (coord point))) [(coord point) value]]))))
|
(map (fn [[value data]] [(mth/abs (- value (coord point))) [(coord point) value]]))))
|
||||||
|
@ -78,7 +39,7 @@
|
||||||
(apply min-key first)
|
(apply min-key first)
|
||||||
second)))
|
second)))
|
||||||
|
|
||||||
(defn snap-frame-id [shapes]
|
(defn- snap-frame-id [shapes]
|
||||||
(let [frames (into #{} (map :frame-id shapes))]
|
(let [frames (into #{} (map :frame-id shapes))]
|
||||||
(cond
|
(cond
|
||||||
;; Only shapes from one frame. The common is the only one
|
;; Only shapes from one frame. The common is the only one
|
||||||
|
@ -90,10 +51,6 @@
|
||||||
;; Otherwise the root frame is the common
|
;; Otherwise the root frame is the common
|
||||||
:else zero)))
|
:else zero)))
|
||||||
|
|
||||||
(defn flatten-to-points
|
|
||||||
[query-result]
|
|
||||||
(mapcat (fn [[v data]] (map (fn [[point _]] point) data)) query-result))
|
|
||||||
|
|
||||||
(defn get-snap-points [page-id frame-id filter-shapes point coord]
|
(defn get-snap-points [page-id frame-id filter-shapes point coord]
|
||||||
(let [value (coord point)]
|
(let [value (coord point)]
|
||||||
(->> (uw/ask! {:cmd :snaps/range-query
|
(->> (uw/ask! {:cmd :snaps/range-query
|
||||||
|
@ -132,21 +89,25 @@
|
||||||
(rx/combine-latest snap-as-vector snap-y snap-x)))
|
(rx/combine-latest snap-as-vector snap-y snap-x)))
|
||||||
|
|
||||||
(defn closest-snap-point
|
(defn closest-snap-point
|
||||||
[page-id shapes point]
|
[page-id shapes layout point]
|
||||||
(let [frame-id (snap-frame-id shapes)
|
(if (layout :dynamic-alignment)
|
||||||
filter-shapes (into #{} (map :id shapes))]
|
(let [frame-id (snap-frame-id shapes)
|
||||||
(->> (closest-snap page-id frame-id [point] filter-shapes)
|
filter-shapes (into #{} (map :id shapes))]
|
||||||
(rx/map #(gpt/add point %)))))
|
(->> (closest-snap page-id frame-id [point] filter-shapes)
|
||||||
|
(rx/map #(gpt/add point %))))
|
||||||
|
(rx/of point)))
|
||||||
|
|
||||||
(defn closest-snap-move
|
(defn closest-snap-move
|
||||||
[page-id shapes movev]
|
[page-id shapes layout movev]
|
||||||
(let [frame-id (snap-frame-id shapes)
|
(if (layout :dynamic-alignment)
|
||||||
filter-shapes (into #{} (map :id shapes))
|
(let [frame-id (snap-frame-id shapes)
|
||||||
shapes-points (->> shapes
|
filter-shapes (into #{} (map :id shapes))
|
||||||
;; Unroll all the possible snap-points
|
shapes-points (->> shapes
|
||||||
(mapcat (partial shape-snap-points))
|
;; Unroll all the possible snap-points
|
||||||
|
(mapcat (partial sp/shape-snap-points))
|
||||||
|
|
||||||
;; Move the points in the translation vector
|
;; Move the points in the translation vector
|
||||||
(map #(gpt/add % movev)))]
|
(map #(gpt/add % movev)))]
|
||||||
(->> (closest-snap page-id frame-id shapes-points filter-shapes)
|
(->> (closest-snap page-id frame-id shapes-points filter-shapes)
|
||||||
(rx/map #(gpt/add movev %)))))
|
(rx/map #(gpt/add movev %))))
|
||||||
|
(rx/of movev)))
|
|
@ -24,7 +24,7 @@
|
||||||
[uxbox.util.geom.path :as path]
|
[uxbox.util.geom.path :as path]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.i18n :as i18n :refer [t]]
|
[uxbox.util.i18n :as i18n :refer [t]]
|
||||||
[uxbox.util.geom.snap :as snap]
|
[uxbox.main.snap :as snap]
|
||||||
[uxbox.common.uuid :as uuid]))
|
[uxbox.common.uuid :as uuid]))
|
||||||
|
|
||||||
;; --- Events
|
;; --- Events
|
||||||
|
@ -144,6 +144,7 @@
|
||||||
|
|
||||||
page-id (get state :current-page-id)
|
page-id (get state :current-page-id)
|
||||||
objects (get-in state [:workspace-data page-id :objects])
|
objects (get-in state [:workspace-data page-id :objects])
|
||||||
|
layout (get state :workspace-layout)
|
||||||
|
|
||||||
frames (->> objects
|
frames (->> objects
|
||||||
vals
|
vals
|
||||||
|
@ -167,7 +168,7 @@
|
||||||
(->> mouse
|
(->> mouse
|
||||||
(rx/with-latest vector ms/mouse-position-ctrl)
|
(rx/with-latest vector ms/mouse-position-ctrl)
|
||||||
(rx/switch-map (fn [[point :as current]]
|
(rx/switch-map (fn [[point :as current]]
|
||||||
(->> (snap/closest-snap-point page-id [shape] point)
|
(->> (snap/closest-snap-point page-id [shape] layout point)
|
||||||
(rx/map #(conj current %)))))
|
(rx/map #(conj current %)))))
|
||||||
(rx/map (fn [[pt ctrl? point-snap]] #(update-drawing % initial pt ctrl? point-snap)))
|
(rx/map (fn [[pt ctrl? point-snap]] #(update-drawing % initial pt ctrl? point-snap)))
|
||||||
(rx/take-until stoper))
|
(rx/take-until stoper))
|
||||||
|
|
|
@ -108,6 +108,13 @@
|
||||||
(if (contains? layout :libraries)
|
(if (contains? layout :libraries)
|
||||||
(t locale "workspace.header.menu.hide-libraries")
|
(t locale "workspace.header.menu.hide-libraries")
|
||||||
(t locale "workspace.header.menu.show-libraries"))]]
|
(t locale "workspace.header.menu.show-libraries"))]]
|
||||||
|
|
||||||
|
[:li {:on-click #(st/emit! (dw/toggle-layout-flag :dynamic-alignment))}
|
||||||
|
[:span i/shape-halign-left]
|
||||||
|
[:span
|
||||||
|
(if (contains? layout :dynamic-alignment)
|
||||||
|
(t locale "workspace.header.menu.disable-dynamic-alignment")
|
||||||
|
(t locale "workspace.header.menu.enable-dynamic-alignment"))]]
|
||||||
]]]))
|
]]]))
|
||||||
|
|
||||||
;; --- Header Component
|
;; --- Header Component
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[uxbox.util.debug :as debug]
|
[uxbox.util.debug :as debug]
|
||||||
[uxbox.util.geom.shapes :as geom]
|
[uxbox.util.geom.shapes :as geom]
|
||||||
[uxbox.util.geom.snap :as snap]
|
|
||||||
[uxbox.util.geom.matrix :as gmt]
|
[uxbox.util.geom.matrix :as gmt]
|
||||||
[uxbox.util.geom.point :as gpt]
|
[uxbox.util.geom.point :as gpt]
|
||||||
[uxbox.util.debug :refer [debug?]]
|
[uxbox.util.debug :refer [debug?]]
|
||||||
|
|
|
@ -3,38 +3,39 @@
|
||||||
[rumext.alpha :as mf]
|
[rumext.alpha :as mf]
|
||||||
[beicon.core :as rx]
|
[beicon.core :as rx]
|
||||||
[uxbox.main.refs :as refs]
|
[uxbox.main.refs :as refs]
|
||||||
[uxbox.util.geom.snap :as snap]
|
[uxbox.main.snap :as snap]
|
||||||
|
[uxbox.util.geom.snap-points :as sp]
|
||||||
[uxbox.util.geom.point :as gpt]))
|
[uxbox.util.geom.point :as gpt]))
|
||||||
|
|
||||||
(def ^:private line-color "#D383DA")
|
(def ^:private line-color "#D383DA")
|
||||||
|
|
||||||
(mf/defc snap-point [{:keys [point]}]
|
(mf/defc snap-point [{:keys [point zoom]}]
|
||||||
(let [{:keys [x y]} point
|
(let [{:keys [x y]} point
|
||||||
cross-width 3]
|
cross-width (/ 3 zoom)]
|
||||||
[:g
|
[:g
|
||||||
[:line {:x1 (- x cross-width)
|
[:line {:x1 (- x cross-width)
|
||||||
:y1 (- y cross-width)
|
:y1 (- y cross-width)
|
||||||
:x2 (+ x cross-width)
|
:x2 (+ x cross-width)
|
||||||
:y2 (+ y cross-width)
|
:y2 (+ y cross-width)
|
||||||
:style {:stroke line-color :stroke-width "1"}}]
|
:style {:stroke line-color :stroke-width (str (/ 1 zoom))}}]
|
||||||
[:line {:x1 (- x cross-width)
|
[:line {:x1 (- x cross-width)
|
||||||
:y1 (+ y cross-width)
|
:y1 (+ y cross-width)
|
||||||
:x2 (+ x cross-width)
|
:x2 (+ x cross-width)
|
||||||
:y2 (- y cross-width)
|
:y2 (- y cross-width)
|
||||||
:style {:stroke line-color :stroke-width "1"}}]]))
|
:style {:stroke line-color :stroke-width (str (/ 1 zoom))}}]]))
|
||||||
|
|
||||||
(mf/defc snap-line [{:keys [snap point]}]
|
(mf/defc snap-line [{:keys [snap point zoom]}]
|
||||||
[:line {:x1 (:x snap)
|
[:line {:x1 (:x snap)
|
||||||
:y1 (:y snap)
|
:y1 (:y snap)
|
||||||
:x2 (:x point)
|
:x2 (:x point)
|
||||||
:y2 (:y point)
|
:y2 (:y point)
|
||||||
:style {:stroke line-color :stroke-width "1"}
|
:style {:stroke line-color :stroke-width (str (/ 1 zoom))}
|
||||||
:opacity 0.4}])
|
:opacity 0.4}])
|
||||||
|
|
||||||
(defn get-snap [coord {:keys [shapes page-id filter-shapes]}]
|
(defn get-snap [coord {:keys [shapes page-id filter-shapes]}]
|
||||||
(->> (rx/from shapes)
|
(->> (rx/from shapes)
|
||||||
(rx/flat-map (fn [shape]
|
(rx/flat-map (fn [shape]
|
||||||
(->> (snap/shape-snap-points shape)
|
(->> (sp/shape-snap-points shape)
|
||||||
(map #(vector (:frame-id shape) %)))))
|
(map #(vector (:frame-id shape) %)))))
|
||||||
(rx/flat-map (fn [[frame-id point]]
|
(rx/flat-map (fn [[frame-id point]]
|
||||||
(->> (snap/get-snap-points page-id frame-id filter-shapes point coord)
|
(->> (snap/get-snap-points page-id frame-id filter-shapes point coord)
|
||||||
|
@ -42,7 +43,7 @@
|
||||||
(rx/reduce conj [])))
|
(rx/reduce conj [])))
|
||||||
|
|
||||||
(mf/defc snap-feedback-points
|
(mf/defc snap-feedback-points
|
||||||
[{:keys [shapes page-id filter-shapes] :as props}]
|
[{:keys [shapes page-id filter-shapes zoom] :as props}]
|
||||||
(let [state (mf/use-state [])
|
(let [state (mf/use-state [])
|
||||||
subject (mf/use-memo #(rx/subject))]
|
subject (mf/use-memo #(rx/subject))]
|
||||||
|
|
||||||
|
@ -65,16 +66,19 @@
|
||||||
(if (not-empty snaps)
|
(if (not-empty snaps)
|
||||||
[:g.point {:key (str "point-" (:x point) "-" (:y point) "-" (name coord))}
|
[:g.point {:key (str "point-" (:x point) "-" (:y point) "-" (name coord))}
|
||||||
[:& snap-point {:key (str "point-" (:x point) "-" (:y point) "-" (name coord))
|
[:& snap-point {:key (str "point-" (:x point) "-" (:y point) "-" (name coord))
|
||||||
:point point}]
|
:point point
|
||||||
|
:zoom zoom}]
|
||||||
|
|
||||||
(for [snap snaps]
|
(for [snap snaps]
|
||||||
[:& snap-point {:key (str "snap-" (:x point) "-" (:y point) "-" (:x snap) "-" (:y snap) "-" (name coord))
|
[:& snap-point {:key (str "snap-" (:x point) "-" (:y point) "-" (:x snap) "-" (:y snap) "-" (name coord))
|
||||||
:point snap}])
|
:point snap
|
||||||
|
:zoom zoom}])
|
||||||
|
|
||||||
(for [snap snaps]
|
(for [snap snaps]
|
||||||
[:& snap-line {:key (str "line-" (:x point) "-" (:y point) "-" (:x snap) "-" (:y snap) "-" (name coord))
|
[:& snap-line {:key (str "line-" (:x point) "-" (:y point) "-" (:x snap) "-" (:y snap) "-" (name coord))
|
||||||
:snap snap
|
:snap snap
|
||||||
:point point}])]))]))
|
:point point
|
||||||
|
:zoom zoom}])]))]))
|
||||||
|
|
||||||
(mf/defc snap-feedback [{:keys []}]
|
(mf/defc snap-feedback [{:keys []}]
|
||||||
(let [page-id (mf/deref refs/workspace-page-id)
|
(let [page-id (mf/deref refs/workspace-page-id)
|
||||||
|
@ -84,9 +88,11 @@
|
||||||
filter-shapes (mf/deref refs/selected-shapes-with-children)
|
filter-shapes (mf/deref refs/selected-shapes-with-children)
|
||||||
current-transform (mf/deref refs/current-transform)
|
current-transform (mf/deref refs/current-transform)
|
||||||
snap-data (mf/deref refs/workspace-snap-data)
|
snap-data (mf/deref refs/workspace-snap-data)
|
||||||
shapes (if drawing [drawing] selected-shapes)]
|
shapes (if drawing [drawing] selected-shapes)
|
||||||
|
zoom (mf/deref refs/selected-zoom)]
|
||||||
(when (or drawing current-transform)
|
(when (or drawing current-transform)
|
||||||
[:& snap-feedback-points {:shapes shapes
|
[:& snap-feedback-points {:shapes shapes
|
||||||
:page-id page-id
|
:page-id page-id
|
||||||
:filter-shapes filter-shapes}])))
|
:filter-shapes filter-shapes
|
||||||
|
:zoom zoom}])))
|
||||||
|
|
||||||
|
|
55
frontend/src/uxbox/util/geom/snap_points.cljs
Normal file
55
frontend/src/uxbox/util/geom/snap_points.cljs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
;; 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/.
|
||||||
|
;;
|
||||||
|
;; This Source Code Form is "Incompatible With Secondary Licenses", as
|
||||||
|
;; defined by the Mozilla Public License, v. 2.0.
|
||||||
|
;;
|
||||||
|
;; Copyright (c) 2020 UXBOX Labs SL
|
||||||
|
|
||||||
|
(ns uxbox.util.geom.snap-points
|
||||||
|
(:require
|
||||||
|
[cljs.spec.alpha :as s]
|
||||||
|
[clojure.set :as set]
|
||||||
|
[uxbox.util.geom.shapes :as gsh]
|
||||||
|
[uxbox.util.geom.point :as gpt]))
|
||||||
|
|
||||||
|
(defn- frame-snap-points [{:keys [x y width height]}]
|
||||||
|
#{(gpt/point x y)
|
||||||
|
(gpt/point (+ x (/ width 2)) y)
|
||||||
|
(gpt/point (+ x width) y)
|
||||||
|
(gpt/point (+ x width) (+ y (/ height 2)))
|
||||||
|
(gpt/point (+ x width) (+ y height))
|
||||||
|
(gpt/point (+ x (/ width 2)) (+ y height))
|
||||||
|
(gpt/point x (+ y height))
|
||||||
|
(gpt/point x (+ y (/ height 2)))})
|
||||||
|
|
||||||
|
(defn- frame-snap-points-resize [{:keys [x y width height]} handler]
|
||||||
|
(case handler
|
||||||
|
:top-left (gpt/point x y)
|
||||||
|
:top (gpt/point (+ x (/ width 2)) y)
|
||||||
|
:top-right (gpt/point (+ x width) y)
|
||||||
|
:right (gpt/point (+ x width) (+ y (/ height 2)))
|
||||||
|
:bottom-right (gpt/point (+ x width) (+ y height))
|
||||||
|
:bottom (gpt/point (+ x (/ width 2)) (+ y height))
|
||||||
|
:bottom-left (gpt/point x (+ y height))
|
||||||
|
:left (gpt/point x (+ y (/ height 2)))))
|
||||||
|
|
||||||
|
(def ^:private handler->point-idx
|
||||||
|
{:top-left 0
|
||||||
|
:top 0
|
||||||
|
:top-right 1
|
||||||
|
:right 1
|
||||||
|
:bottom-right 2
|
||||||
|
:bottom 2
|
||||||
|
:bottom-left 3
|
||||||
|
:left 3})
|
||||||
|
|
||||||
|
(defn shape-snap-points
|
||||||
|
[shape]
|
||||||
|
(let [modified-path (gsh/transform-apply-modifiers shape)
|
||||||
|
shape-center (gsh/center modified-path)]
|
||||||
|
(case (:type shape)
|
||||||
|
:frame (-> modified-path gsh/shape->rect-shape frame-snap-points)
|
||||||
|
(:path :curve) (into #{shape-center} (-> modified-path gsh/shape->rect-shape :segments))
|
||||||
|
(into #{shape-center} (-> modified-path :segments)))))
|
|
@ -14,7 +14,7 @@
|
||||||
[uxbox.common.pages :as cp]
|
[uxbox.common.pages :as cp]
|
||||||
[uxbox.worker.impl :as impl]
|
[uxbox.worker.impl :as impl]
|
||||||
[uxbox.util.range-tree :as rt]
|
[uxbox.util.range-tree :as rt]
|
||||||
[uxbox.util.geom.snap :as snap]))
|
[uxbox.util.geom.snap-points :as snap]))
|
||||||
|
|
||||||
(defonce state (l/atom {}))
|
(defonce state (l/atom {}))
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue