mirror of
https://github.com/penpot/penpot.git
synced 2025-01-10 08:50:57 -05:00
Implement svg transform/matrix attribute calculation.
This commit is contained in:
parent
669cdd1395
commit
0f9742a83b
1 changed files with 75 additions and 14 deletions
|
@ -1,17 +1,78 @@
|
|||
(ns uxbox.svg)
|
||||
(ns uxbox.svg
|
||||
"A svg related utils."
|
||||
(:require [cuerdas.core :as str]
|
||||
[uxbox.matrix :as mtx]
|
||||
[uxbox.math :as mth]
|
||||
[uxbox.util.data :refer (without-keys)]))
|
||||
|
||||
(defn translate
|
||||
[x y]
|
||||
(str "translate(" x "," y ")"))
|
||||
(defn translate-matrix
|
||||
([x]
|
||||
(translate-matrix x x))
|
||||
([x y]
|
||||
(mtx/matrix [[1 0 x]
|
||||
[0 1 y]
|
||||
[0 0 1]])))
|
||||
|
||||
(defn rotate
|
||||
[d]
|
||||
(str "rotate(" d ")"))
|
||||
(defn scale-matrix
|
||||
([w]
|
||||
(scale-matrix w w))
|
||||
([w h]
|
||||
(mtx/matrix [[w 0 0]
|
||||
[0 h 0]
|
||||
[0 0 1]])))
|
||||
|
||||
(defn transform
|
||||
[{:keys [center] :as opts}]
|
||||
(let [r (get opts :rotate 0)
|
||||
{:keys [x y]} center]
|
||||
(str (translate x y)
|
||||
(rotate r)
|
||||
(translate (- x) (- y)))))
|
||||
(defn rotation-matrix
|
||||
[^number degrees]
|
||||
(let [v1 (mth/cos (mth/radiants degrees))
|
||||
v2 (mth/sin (mth/radiants degrees))
|
||||
v3 (mth/neg v2)]
|
||||
(mtx/matrix [[v1 v3 0]
|
||||
[v2 v1 0]
|
||||
[0 0 1]])))
|
||||
|
||||
(defn apply-translate
|
||||
[{:keys [x y]}]
|
||||
(translate-matrix x y))
|
||||
|
||||
(defn apply-scale
|
||||
[{:keys [width height view-box]}]
|
||||
(if (and width height)
|
||||
(let [orig-width (nth view-box 2)
|
||||
orig-height (nth view-box 3)
|
||||
scale-x (/ width orig-width)
|
||||
scale-y (/ height orig-height)]
|
||||
(scale-matrix scale-x scale-y))
|
||||
(scale-matrix 1 1)))
|
||||
|
||||
(defn apply-rotation
|
||||
[{:keys [rotation x y width height view-box] :or {rotation 0}}]
|
||||
(let [width (nth view-box 2)
|
||||
height (nth view-box 3)
|
||||
x (- width (/ width 2))
|
||||
y (- height (/ height 2))]
|
||||
(mtx/multiply (translate-matrix x y)
|
||||
(rotation-matrix rotation)
|
||||
(translate-matrix (- x)
|
||||
(- y)))))
|
||||
|
||||
(def interpret-attrs (juxt apply-translate
|
||||
apply-scale
|
||||
apply-rotation))
|
||||
|
||||
(defn calculate-transform
|
||||
[attrs]
|
||||
(let [result (->> (interpret-attrs attrs)
|
||||
(apply mtx/multiply)
|
||||
(deref)
|
||||
(take 6)
|
||||
(flatten))]
|
||||
(->> (map #(nth result %) [0 3 1 4 2 5])
|
||||
(str/join ",")
|
||||
(str/format "matrix(%s)"))))
|
||||
|
||||
(defn apply-transform
|
||||
[attrs]
|
||||
(let [transform (calculate-transform attrs)]
|
||||
(-> attrs
|
||||
(without-keys [:rotation :width :height :x :y :view-box])
|
||||
(assoc :transform transform))))
|
||||
|
|
Loading…
Reference in a new issue