Skip to content

Instantly share code, notes, and snippets.

@enjalot
Created June 20, 2013 07:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save enjalot/5820790 to your computer and use it in GitHub Desktop.
Save enjalot/5820790 to your computer and use it in GitHub Desktop.
eas3
{"description":"eas3","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"scene.svg":{"default":true,"vim":false,"emacs":false,"fontSize":12},"style.css":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"recording.js":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"fullscreen":false,"play":false,"loop":false,"restart":false,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"thumbnail":"http://i.imgur.com/sr1rhmg.png"}
var svg = d3.select("svg");
//a layer where we will put all our extra stuff
var msvg = svg.append("g");
//we could grab all <g> element, but lets just start with the one's
//that were given enough care to be id'd (i.e. layers in illustrator)
//var allGs = svg.selectAll("g");
var gs = svg.selectAll("g[id]");
//for now we are assuming there is no data attached to these g layers
//TODO: be less intrusive on the svg;
var data = d3.range(gs[0].length).map( function(d) { return {x: 0, y: 0, scale: 1, rotate: 0} });
gs = gs.data(data);
var selected;
//if(!tributary.recordings)
tributary.recordings = [];
tributary.isRecording = false;
/*
var zoom = d3.behavior.zoom()
.on("zoom", function(d,i) {
d.x = d3.event.translate[0];
d.y = d3.event.translate[1];
d.scale = d3.event.scale;
var g = d3.select(this);
g.attr("transform", "translate(" + [d.x, d.y ] + ")scale(" + d.scale + ")");
if(tributary.isRecording) {
tributary.currentRecording.push({x: d.x, y: d.y, scale: d.scale, time: +new Date()});
tributary.currentRecording.plot(svg.select("g.recplot"));
}
})
*/
tributary.startRecording = function() {
d3.timer(rec);
}
function rec() {
//stop this timer if we are done recording
if(!tributary.isRecording || !selected) {
tributary.stopRecording();
return true;
}
var d = selected.datum();
tributary.currentRecording.push({x: d.x, y:d.y, time: +new Date()});
tributary.currentRecording.plot(svg.select("g.recplot"));
}
var drag = d3.behavior.drag()
.on("drag", function(d,i) {
d.x += d3.event.dx;
d.y += d3.event.dy;
var g = d3.select(this)
//g.attr("transform", "translate(" + [d.x, d.y ] + ")");
g.attr("transform", "translate(" + [d.x, d.y ] + ")scale(" + d.scale + ")");
if(tributary.isRecording) {
//tributary.currentRecording.push({x: d.x, y:d.y, time: +new Date()});
//tributary.currentRecording.plot(svg.select("g.recplot"));
}
})
.on("dragstart", function(d,i) {
//TODO: don't always reset?
d.x = 0;
d.y = 0;
})
.on("dragend", function(d,i) {
var g = d3.select(this);
g.attr("transform", null);
if(tributary.isRecording) {
//console.log("recording", tributary.currentRecording.data())
}
});
//custom mouse wheel (scrolling) behavior
var wheel = function(g) {
g.on("mousewheel.wheel", function() {
if(!selected) return;
var d = selected.datum();
var scroll = d3.event.wheelDeltaY;
//d.scale += scroll/100;
//selected.attr("transform", "scale(" + d.scale + ")translate(" + [d.x, d.y ] + ")");
})
return g;
}
tributary.events.off("scrubbah");
tributary.events.on("scrubbah", function(s) {
//console.log("suP", s);
var d = selected.datum();
d[s.marker] = s.d;
selected.attr("transform", "translate(" + [d.x, d.y ] + ")scale(" + d.scale + ")");
})
//SELECTION LOGIC
gs.on("mouseenter", function(d,i) {
if(d.selected) return;
var g = d3.select(this)
g.on("click", select);
return makeBox(g);
})
gs.on("mouseleave", function(d,i) {
if(d.selected) return;
removeBox(d3.select(this));
})
//TODO: use a less likely to collide classname
function removeBox(g) {
g.selectAll("g.bbox")
.remove()
}
function makeBox(g) {
var rect = g.node().getBBox();
var bbg = g.insert("g",":first-child")
.classed("bbox", true)
bbg.append("rect")
.attr(rect)
return bbg;
}
//select a layer for further manipulation
function select(d,i) {
var g = d3.select(this);
//if already selected and clicked again
if(d.selected) {
d.selected = false;
deselectAll();
return;
}
deselectAll(g);
selected = g;
d.selected = true;
makeBox(g);
//g.call(zoom);
g.call(drag);
svg.call(wheel);
//d3.event.cancelBubble = true;
}
function deselectAll(g) {
gs.each(function(d,i) {
//don't deslect ourselves if we are selected
if(g && g.node() === this) return;
d.selected = false;
removeBox(d3.select(this));
removeBehavior(d3.select(this));
//removeZoom(d3.select(this));
})
selected = null;
}
function removeBehavior(g) {
g.on("mousedown.drag", null);
g.on("touchstart.drag", null);
svg.on("mousewheel.wheel", null);
}
function removeZoom(g) {
g.on("mousemove.zoom", null);
g.on("mousewheel.zoom", null);
g.on("mousedown.zoom", null);
g.on("dblclick.zoom", null);
g.on("touchend.zoom", null);
g.on("touchmove.zoom", null);
g.on("touchend.zoom", null);
}
//svg.on("keydown", null)
//console.log(svg)
tributary.recordingUI();
//if(tributary.currentRecording) tributary.currentRecording.plot(svg.select("g.recplot"))
tributary.run = function(g,t) {
}
//ui stuff
document.onselectstart = function(){ return false; }
tributary.recordingUI = function() {
var svg = d3.select("svg")
.append("g")
.classed("recordingui", true);
var recButton = svg.append("g").classed("record", true)
.attr("transform", "translate(" + [24, tributary.sh - 112] + ")");
recButton.append("rect")
.attr({
width: 40,
height: 40,
rx: 20,
ry: 20
});
var recPlot = svg.append("g").classed("recplot", true)
.attr("transform", "translate(" + [86, tributary.sh - 112] + ")");
recButton.on("click", function() {
tributary.isRecording = !tributary.isRecording;
d3.select(this).classed("recording", tributary.isRecording);
if(tributary.isRecording) {
tributary.currentRecording = tributary.recording();
tributary.recordings.push(tributary.currentRecording);
tributary.startRecording();
} else {
//draw the last recording;
tributary.currentRecording.plot(recPlot);
}
});
tributary.stopRecording = function() {
tributary.isRecording = false;
recButton.classed("recording", false);
}
}
tributary.recording = recording;
function recording() {
var layer;
var data = [];
//for the plot
var width = 526;
var height = 28;
function record(g) {
layer = g;
}
record.push = function(d) {
data.push(d);
}
record.data = function() {
return data;
}
record.element = function() {
return layer;
}
record.plot = function(g) {
//plot the recording's data
var xs = [], ys = [], scales = [], rotates = [], ts = [];
data.forEach(function(d) {
xs.push(d.x ? d.x : 0);
ys.push(d.y ? d.y : 0);
scales.push(d.scale ? d.scale : 0);
rotates.push(d.rotate ? d.rotate : 0);
//better have a time
ts.push(d.time);
});
var linescale = d3.scale.linear()
.range([height, 0]);
var xscale = d3.scale.linear()
.domain([0, ts.length])
.range([0, width]);
var line = d3.svg.line()
.x(function(d,i) { return xscale(i); })
.y(function(d, i) { return linescale(d) });
xs.scrubber = scrubbah()
.width(width).height(height)
.marker("x")
.data(xs)
ys.scrubber = scrubbah()
.width(width).height(height)
.marker("y")
.data(ys);
console.log("xs", xs.length);
var plotdata = [xs, ys];//, scales, rotates];
var plots = g.selectAll("g.plot")
.data(plotdata)
plots.enter()
.append("g").classed("plot", true)
.attr("transform", function(d,i) {
return "translate(" + [0, i * (height + 5)] + ")";
})
.append("path")
plots
.each(function(d,i) {
d.scrubber(d3.select(this))
})
.select("path")
.each(function(d,i) {
linescale.domain(d3.extent(d));
d3.select(this).attr("d", line);
this.parentNode.appendChild(this);
})
}
return record;
}
function scrubbah() {
var w = 300
var h = 40;
var data = d3.range(100);
var xscale = d3.scale.ordinal();
var marker;
function dubdub(g) {
console.log("DD", data.length);
xscale
.domain(d3.range(data.length))
.rangeBands([0, w], 0.1)
g.selectAll("rect.bg")
.data([0])
.enter().append("rect")
.attr({
width:w,
height: h
}).classed("bg", true)
var mousedown = false;
var selected;
var bars = g.selectAll("g.bar")
.data(data)
bars.enter()
.append("g").classed("bar", true)
.append("rect").classed("bar", true)
bars.select("rect").attr({
x: function(d,i) { return xscale(i) },
y: function(d,i) { return 0 },
width: xscale.rangeBand(),
height: h
})
.on("mousedown", function(d,i) {
mousedown = true;
selected = d;
d3.select(this).classed("selected", true);
})
.on("mouseup", function(d,i) {
mousedown = false;
})
.on("mouseover", function(d,i) {
//if(!mousedown) return;
bars.select("rect").classed("selected", false);
selected = d;
d3.select(this).classed("selected", true);
tributary.events.trigger("scrubbah", {d: d, marker: marker});
})
g.on("mousedown", function() {
mousedown = true;
})
g.on("mouseup", function() {
mousedown = false;
})
g.on("mouseout", function() {
var to = d3.event.toElement;
var clazz = d3.select(to).attr("class");
var ind = data.indexOf(d3.select(to).datum())
if(ind < 0 && clazz !== "bg") {
mousedown = false;
}
}, true)
}
dubdub.data = function(_) {
if(!arguments.length) return data;
data = _;
return dubdub;
}
dubdub.width = function(_) {
if(!arguments.length) return w;
w = _;
return dubdub;
}
dubdub.height = function(_) {
if(!arguments.length) return h;
h = _;
return dubdub;
}
dubdub.marker = function(_) {
if(!arguments.length) return marker;
marker = _;
return dubdub;
}
return dubdub
}
Display the source blob
Display the rendered blob
Raw
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
.bbox rect {
fill-opacity: 0.1;
fill: #ffffff;
stroke: #FF9900;
stroke-width: 1;
}
.record rect {
fill: #36A221;
}
.recording rect {
fill: #ff0000;
}
.recplot path {
fill: none;
stroke: #5AE6E6;
pointer-events: none;
}
.selected {
fill: #ff0000;
}
.bg {
fill: #ffffff;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment