playing with latent vectors. didn't get to where I thought I'd be, but its a start.
Built with blockbuilder.org
license: mit |
playing with latent vectors. didn't get to where I thought I'd be, but its a start.
Built with blockbuilder.org
<!DOCTYPE html> | |
<head> | |
<meta charset="utf-8"> | |
<script src="https://d3js.org/d3.v4.min.js"></script> | |
<style> | |
body { | |
margin:0;position:fixed;top:0;right:0;bottom:0;left:0; | |
background: #222; | |
} | |
</style> | |
</head> | |
<body> | |
<script> | |
var width = 960 | |
var height = 500 | |
var svg = d3.select("body").append("svg") | |
.attr("width", width) | |
.attr("height", height) | |
var drawingLine = d3.line() | |
.x(function(d) { return d.x }) | |
.y(function(d) { return d.y }) | |
.curve(d3.curveBasis) | |
var q = d3.queue() | |
q.defer(d3.json, "https://storage.googleapis.com/fun-data/quickdraw/chair-left-drawings.json") | |
q.defer(d3.json, "https://storage.googleapis.com/fun-data/quickdraw/chair-left-encodings_a.json?q=1") | |
q.defer(d3.json, "https://storage.googleapis.com/fun-data/quickdraw/chair-perspective-left-drawings.json?q=1") | |
q.defer(d3.json, "https://storage.googleapis.com/fun-data/quickdraw/chair-perspective-left-encodings_a.json?q=1") | |
//q.defer(d3.json, "https://storage.googleapis.com/fun-data/quickdraw/chair-right-drawings.json") | |
q.awaitAll(function(err, results) { | |
console.log("results", results) | |
var chairsLeft = results[0] | |
var chairsLeftEncodings = results[1] | |
var chairsPerspective = results[2] | |
var chairsPerspectiveEncodings = results[3] | |
chairsLeft.forEach(function(d,i) { | |
d.e = chairsLeftEncodings[i].e | |
}) | |
chairsPerspective.forEach(function(d,i) { | |
d.e = chairsPerspectiveEncodings[i].e | |
}) | |
var chairs = chairsLeft.concat(chairsPerspective.slice(0,29)) | |
chairs.forEach(strokifyDrawing) | |
var randomg = svg.selectAll("g.random") | |
.data(chairs) | |
var cellSize = 3; | |
var renter = randomg.enter().append("g").classed("random", true) | |
var cols = 29 | |
renter.attr("transform", function(d,i) { | |
var x = 15 + 32 * (i % cols); | |
var y = 45 + 250 * Math.floor(i / cols); | |
return "translate(" + [x, y] + ")" | |
}) | |
.each(function(d,i) { | |
//console.log(d) | |
var s = new strip() | |
.data(d.e) | |
.cellWidth(cellSize) | |
.cellHeight(1.5) | |
.onChange(function(data) { | |
rerender(); | |
updateExplanation(); | |
}) | |
.update(d3.select(this)) | |
d3.select(this) | |
.selectAll("path.stroke").data(d.strokes) | |
.enter().append("path").classed("stroke", true) | |
.attr("d", drawingLine) | |
.style("stroke", "#ffefa8") | |
.style("stroke-width", 5) | |
.style("fill", "none") | |
.attr("transform", "translate(5,-40)scale(0.14)") | |
}) | |
}) | |
function strip() { | |
//interactive vector editor | |
var cellWidth = 20; | |
var cellHeight = 20; | |
var rows = 128; | |
var cols = 5; | |
var half = Math.floor(cols/2); | |
var colors = d3.scaleOrdinal() | |
.domain(d3.range(rows)) | |
.range([ | |
"#e41a1c", | |
"#377eb8", | |
"#4daf4a", | |
"#984ea3", | |
"#ff7f00", | |
"#ffff33" | |
]) | |
var data = []; | |
var cb; // callback for onChange | |
this.update = function(g) { | |
var extent = d3.extent(data) | |
var mapping = d3.scaleLinear() | |
.domain(extent) | |
.range([-(cols-1), 0]) | |
//.domain([0, cols-1]) // based on max value | |
//.range([-(cols-1), 0]) | |
var container = g.append("g") | |
.attr("transform", "translate(" + [cellWidth * cols, 0] + ")") | |
var rowsg = container.selectAll("g.row") | |
.data(d3.range(data.length)) | |
rowsg.exit().remove(); | |
var rowsgE = rowsg.enter().append("g").classed("row", true) | |
.attr("transform", function(d) { | |
var x = cellWidth * mapping(data[d]); | |
var y = 0; | |
return "translate(" + [x,y] + ")"; | |
}) | |
var cellsg = rowsgE.selectAll("rect.cell") | |
.data(function(d) { | |
return d3.range(cols).map(function(c) { | |
return { c: c, r: d } | |
}) | |
}) | |
var cellsgE = cellsg.enter().append("rect").classed("cell", true) | |
cellsg = cellsgE.merge(cellsg) | |
cellsg.attr("x", function(d) { return d.c * cellWidth }) | |
.attr("y", function(d) { return d.r * cellHeight }) | |
.attr("width", cellWidth) | |
.attr("height", cellHeight) | |
.style("fill", function(d,i) { | |
var color = d3.hcl(colors(d.r)) | |
if(d.c < half) { | |
return color.darker(1 - d.c/half) | |
} else if(d.c > half) { | |
return color.brighter(d.c/cols) | |
} else { | |
return color; | |
} | |
}) | |
// We convert the relative mouse position to one of the potential | |
// values in our array | |
var mouseScale = d3.scaleLinear() | |
.domain([-cellWidth * cols/2, cellWidth/2 * (cols+1)]) | |
.range([0, cols-1]) | |
var drag = d3.drag() | |
.on("drag", function(d) { | |
var x = d3.event.x; | |
var y = d3.event.y; | |
var v = Math.floor(mouseScale(x)) | |
v = Math.max(0, Math.min(v, cols-1)) | |
if(data[d] === v) return; | |
data[d] = v; | |
rowsg.attr("transform", function(d) { | |
var x = cellWidth * mapping(data[d]); | |
var y = 0; | |
return "translate(" + [x,y] + ")"; | |
}) | |
if(cb) cb(data); | |
}) | |
rowsg.call(drag) | |
return this; | |
} | |
this.data = function(val) { | |
if(val) { data = val; return this; } | |
return data; | |
} | |
this.cellWidth = function(val) { | |
if(val) { cellWidth = val; return this; } | |
return cellWidth; | |
} | |
this.cellHeight = function(val) { | |
if(val) { cellHeight = val; return this; } | |
return cellHeight; | |
} | |
this.onChange = function(val) { | |
if(val) { cb = val; return this; } | |
return val | |
} | |
return this; | |
} | |
function strokifyDrawing(d) { | |
//var drawing = JSON.parse(JSON.stringify(d)) //well that's one way to copy | |
var strokes = d.drawing.map(function(s) { | |
var points = [] | |
s[0].forEach(function(x,i) { | |
points.push({x: x, y: s[1][i] }) | |
}) | |
return points; | |
}) | |
d.strokes = strokes; | |
} | |
</script> | |
</body> |