Skip to content

Instantly share code, notes, and snippets.

@racsoraul
Last active August 29, 2015 14:24
Show Gist options
  • Save racsoraul/49563404361e13cb813b to your computer and use it in GitHub Desktop.
Save racsoraul/49563404361e13cb813b to your computer and use it in GitHub Desktop.
SVG Plant Generator
<svg viewBox="0 0 550 400" preserveAspectRatio="xMidYMax meet">
<g id="stems" fill="none" stroke="green"></g>
<g id="leaves"></g>
</svg>
<br />
<button id="create">Create</button>
// Based on the plant generator by Kevin Lindsey
// http://www.kevlindev.com/alife/plants/plants.svg
class EventManager {
constructor() {
this.eventLookup = {};
}
off(event, callback) {
var listeners = this.eventLookup[event];
if (event === "*") this.eventLookup = {};
else if(!callback) this.eventLookup[event] = [];
else _.remove(listeners, { callback });
}
on(event, callback, scope) {
var listeners = this.eventLookup[event];
if (!listeners) this.eventLookup[event] = listeners = [];
listeners.push({ callback, scope });
return () => _.remove(listeners, { callback });
}
once(event, callback, scope) {
var on = (...data) => {
this.off(event, on);
callback.apply(scope, data);
};
return this.on(event, on);
}
fire(event, ...data) {
var listeners = this.eventLookup[event];
if (!listeners) return;
listeners.forEach(list => {
try {
return list.callback.apply(list.scope, data);
} catch(e) {
return _.isError(e) ? e : new Error(e);
}
});
}
}
var events = new EventManager();
var ns = "http://www.w3.org/2000/svg";
var d = "M0,0 Q5,-5 10,0 5,5 0,0z";
var stems = $("#stems");
var leaves = $("#leaves");
var svg = $("svg");
var leafCount = 30;
var plants = 10;
var centerX = 275;
var offsetX = 175;
$("#create").on("click", generate);
generate();
function generate() {
leaves.empty();
stems.empty();
_.times(plants, createPlant);
stems.children().each(function() {
var tween = TweenMax.to(this, _.random(2, 4), {
drawSVG: true,
delay: _.random(2),
onStart: () => TweenLite.set(this, { opacity: 1 }),
onUpdate: () => events.fire(this.id, tween.progress())
});
});
}
function createPlant() {
var points = createPoints();
var stem = createPath(stems);
var length = points.length;
var values = points.map(point => `${point.x},${point.y}`);
var height = points[length - 1].y;
var id = _.uniqueId("grow");
TweenLite.set(stem, {
opacity: 0,
drawSVG: 0,
attr: { id, d: `M${values.join(" ")}` }
});
for (var i = 0; i < leafCount; i++) {
var point = points[length - 1 - i];
var scale = {
x: 1 + 0.1 * i,
y: 1 + 0.05 * i
};
createLeaf(point, scale, height, id);
}
}
function createLeaf(point, scale, height, grow) {
var leaf = createPath(leaves);
var start = height / point.y;
var off = events.on(grow, growLeaf);
function growLeaf(growth) {
if (growth >= start) {
// Remove listener
off();
TweenLite.set(leaf, {
x: point.x,
y: point.y,
scaleX: scale.x,
scaleY: scale.y,
rotation: _.random(180) - 180,
fill: `rgb(0,${_.random(110, 160)},0)`,
attr: { d }
});
TweenLite.from(leaf, 1, { scale: 0 });
}
}
}
function createPoints() {
var x = _.random(centerX - offsetX, centerX + offsetX);
var y = 400;
var dy = 5;
var offset = 0.007;
var count = _.random(30, 65);
var points = [{ x, y }];
for (var i = 1; i <= count; i++) {
points.push({
x: points[i - 1].x + i * offset * (_.random(21) - 10),
y: 395 - dy * i
});
}
return points;
}
function createPath(parent) {
return $(document.createElementNS(ns, "path")).appendTo(parent);
}
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/gsap/1.17.0/TweenMax.min.js"></script>
<script src="//s3-us-west-2.amazonaws.com/s.cdpn.io/16327/DrawSVGPlugin.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/lodash.js/3.9.3/lodash.min.js"></script>
body {
background: #eee;
}
* {
box-sizing: border-box;
}
svg {
width: 100%;
height: 100%;
position: absolute;
}
button {
position: absolute;
top: 15px;
left: 15px;
background: yellowgreen;
border: 1px solid rgba(0,0,0,0.2);
padding: 10px 16px;
font-weight: bold;
color: #222;
transition: all 0.1s;
box-shadow: 0 1px 4px 0 rgba(0, 0, 0, 0.37);
&:focus {
outline: none;
}
&:hover {
border: 1px solid rgba(0,0,0,0.5);
color: black;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment