Skip to content

Instantly share code, notes, and snippets.

@sli
Last active July 4, 2019 23:51
Show Gist options
  • Save sli/a27cf6379d6cee04d5a57d26961665ed to your computer and use it in GitHub Desktop.
Save sli/a27cf6379d6cee04d5a57d26961665ed to your computer and use it in GitHub Desktop.
Chainable SVG library demo.
(ns svg.core
(:require [reagent.core :refer [render-component]]
[svg.lib.core :as s]))
(def sand-color "#efc58d")
(defn cool-image
[]
(-> (s/svg {:view-box "0 0 100 100"
:stroke "none"
:fill "none"
:width 500
:height 500})
(s/linear-gradient {:id :sunset :angle 90}
{:offset "0%" :stop-color "#f70459"}
{:offset "10%" :stop-color "#f76200"}
{:offset "75%" :stop-color "#f73d00"})
(s/linear-gradient {:id :right-highlight :angle 135}
{:offset "0%" :stop-color "#444"}
{:offset "3%" :stop-color "#222"})
(s/linear-gradient {:id :right-shadow :angle 0}
{:offset "97%" :stop-color "#888"}
{:offset "100%" :stop-color "#666"})
(s/radial-gradient {:id :sun}
{:offset "95%" :stop-color "#f90707"}
{:offset "100%" :stop-color "#f90707" :stop-opacity "0"})
(s/fill-canvas :sunset)
(s/circle {:cx 50 :cy 65 :r 40 :fill "url('#sun')" :opacity "0.75"})
(s/path "M25,75 l0,25 15,0 -15,-25" {:fill "url(#right-highlight)"})
(s/path "M25,75 l0,25 -15,0 15,-25" {:fill "url(#right-shadow)"})
(s/path "M75,75 l0,25 15,0 -15,-25" {:fill "url(#right-highlight)"})
(s/path "M75,75 l0,25 -15,0 15,-25" {:fill "url(#right-shadow)"})
(s/circle {:cx 50 :cy 292 :r 200 :fill sand-color})
(s/path "M50,50 l0,50 25,0 -25,-50" {:fill "url(#right-highlight)"})
(s/path "M50,50 l0,50 -25,0 25,-50" {:fill "url(#right-shadow)"})
(s/path "M25,97 l25,2 25,-2 0,3 -50,0 0,-3" {:fill sand-color})
(s/path
"M40,10 a5,5 0 0,1 3,7 l10,0 a7,7 0 0,1 0,14 l-55,0 0,-14 20,0 A5,5 0 1,1 13,10 l22,0"
{:fill sand-color :opacity "0.55"})
(s/path "M60,45 a5,5 0 0,1 0,-10 l40,0 0,10" {:fill sand-color :opacity "0.55"})))
(defn app
[]
[:div
[cool-image]])
(defn start []
(render-component
[app]
(. js/document (getElementById "app"))))
(defn ^:export init []
(start))
(defn stop []
(js/console.log "stop"))
(ns svg.lib.core
(:require #?(:clj [clojure.data.codec.base64 :refer [encode]])
#?(:clj [hiccup.core :refer [html]]
:cljs [reagent.dom.server :refer [render-to-static-markup]])
#?(:cljs [reagent.impl.template :as tmpl])))
(defn primitive
[shape]
(fn [canvas props]
(conj canvas [shape props])))
(defn svg
"Creates the initial SVG canvas that will be chained."
[props & children]
[:svg
(assoc props :xmlns "http://www.w3.org/2000/svg")
[:def]
children])
(def circle (primitive :circle))
(def ellipse (primitive :ellipse))
(def line (primitive :line))
(def rect (primitive :rect))
(defn path
([canvas d]
(conj canvas [:path {:d d}]))
([canvas d props]
(conj canvas [:path (merge props {:d d})])))
(defn fill-canvas
[canvas color]
(conj
canvas
[:rect {:x 0
:y 0
:width "100%"
:height "100%"
:fill (if (keyword? color)
(str "url(#" (name color) ")")
color)}]))
(defn linear-gradient
[canvas {:keys [id angle]} & stops]
(assoc canvas 2 (conj
(nth canvas 2)
[:linearGradient
{:id id :gradient-transform (str "rotate(" angle ")")}
(for [s stops]
#?(:clj [:stop s]
:cljs ^{:key (str id) "-" (:offset s)} [:stop s]))])))
(defn radial-gradient
[canvas props & stops]
(assoc canvas 2 (conj
(nth canvas 2)
[:radialGradient
props
(for [s stops]
#?(:clj [:stop s]
:cljs ^{:key (str (:id props) "-" (:offset s))} [:stop s]))])))
(defn to-data-url
[canvas]
(let [desized-props (dissoc (nth canvas 1) :width :height)
desized-canvas (assoc canvas 1 desized-props)]
(str "data:image/svg+xml;utf8," #?(:clj (html {:mode :xml} desized-canvas)
:cljs (render-to-static-markup desized-canvas)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment