What's the best way to add SVG elements to the dom in Clojurescript ? The Twitterbuzz example uses Google Closure lib's Graphics objects, but say I didn't care about IE compatibility, is there a way I could add elements the way html is (dom/build [:svg [:g [:text "something like this ?"]]])
I tried Closure's graphics lib but I don't get to use a lot of handy SVG features. I tried Apogee, but that serializes the SVG code and I would prefer direct DOM manipulation.
Asked
Active
Viewed 3,085 times
4

Hendekagon
- 4,565
- 2
- 28
- 43
4 Answers
4
dom/build constructs DOM elements without the namespace. You need to either enhance dom/build or write one for SVG. I use the following code to create SVG elements.
(defn element-ns
"Create a namespaced dom element"
[namespace tag & args]
(let [[tag attrs children] (normalize-args tag args)
parent (. js/document createElementNS namespace (name tag))
[parent children] (if (string? (first children))
[(set-text (element-ns namespace tag attrs) (first children))
(rest children)]
[parent children])]
(doseq [[k v] attrs]
(. parent setAttributeNS nil (name k) v))
(apply append parent children)))
(defn build-svg
"Build up a svg element from nested vectors."
[x]
(if (vector? x)
(let [[parent children] (if (keyword? (first x))
[(apply element-ns "http://www.w3.org/2000/svg" (take-while element-arg? x))
(drop-while element-arg? x)]
[(first x) (rest x)])
children (map build-svg children)]
(apply append parent children))
x))

Synk
- 116
- 3
-
Where are `element-arg?` `normalize-args`, `set-text`, and `append` defined? – noisesmith Feb 25 '14 at 00:38
2
What about using Enlive for SVG? This is what I plan to use for several real time projects.

humasect
- 552
- 5
- 9
-
because AFAIK, Enlive is a HTML templating lib which is good for generating HTML on the server, whereas I'm generating SVG on the client at runtime. Also I don't think it supports XML namespaces which I'd need for SVG – Hendekagon Feb 06 '12 at 04:54
-
Ahh I see, my apologies - have a look at 'Enfocus' for ClojureScript land. I will be generating svg from both client and server as well – humasect Feb 12 '12 at 19:01
0
If you want to load svg as an external asset try loading it as text and appending it to a div leveraging cljs-d3:
(defn load-svg-as-text []
(fn []
(let [on-complete (fn [error externalSVGText]
(-> d3
(.select "#viewport")
(.html externalSVGText))
)]
(-> d3
(.text "images/smartcity.svg" on-complete)))))
I got the idea from AmeliaBR nice answer in this js thread and then ported it to ClojureScript

headwinds
- 1,781
- 15
- 26