Skip to content

Instantly share code, notes, and snippets.

@eesur
Last active May 23, 2017 10:56
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 eesur/fa54ecebcb9106937a959c3c6242dc07 to your computer and use it in GitHub Desktop.
Save eesur/fa54ecebcb9106937a959c3c6242dc07 to your computer and use it in GitHub Desktop.
d3 | Sol LeWitt’s Wall Drawing #118 (1971)
var width = window.innerWidth
var height = window.innerHeight
var svg = d3.select('svg')
.attr('width', width)
.attr('width', height)
var g = svg.select('#vis')
// create 50 items that have x and y uniformly random
var data = d3.range(50).map(function (n) {
return {
x: Math.floor(d3.randomUniform(1, width-10)()),
y: Math.floor(d3.randomUniform(1, height-10)()),
id: n
}
})
// scale for some colour differentiation
var sequentialScale = d3.scaleSequential()
.domain([0, 50])
.interpolator(d3.interpolateRainbow)
// append the 50 circles driven by the data
g.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', 2)
.attr('cx', function (d) { return d.x; })
.attr('cy', function (d) { return d.y; })
.style('fill', function (d, i) { return sequentialScale(i); })
// loop 50 times (length of data)
data.forEach(function (o, n) {
// append 50 lines driven by the data
g.selectAll('line.id-' + n)
.data(data)
.enter()
.append('line')
.attr('class', 'id-' + n)
// append a line form a reference (point in data)
.attr('x1', data[n].x)
.attr('y1', data[n].y)
// connecting to all other points (all points in data)
.attr('x2', function (d) { return d.x; })
.attr('y2', function (d) { return d.y; })
.attr('stroke', function (d, i) { return sequentialScale(i); })
})
// add some interaction so we can see the sets of lines :)
var voronoi = d3.voronoi()
.x(function (d) { return d.x; })
.y(function (d) { return d.y; })
.size([width, height])(data)
// draw the polygons
var voronoiPolygons = g.append('g')
.attr('class', 'voronoi-polygons')
var binding = voronoiPolygons
.selectAll('path')
.data(voronoi.polygons())
binding.enter().append('path')
// .style('stroke', 'tomato')
.style('fill', 'transparent')
.attr('d', function (d) { return ("M" + (d.join('L')) + "Z"); })
.on('mouseover', function (d) {
g.selectAll(':not(.id-' + d.data.id + ')')
.style('opacity', 0.1)
})
.on('mouseout', function () { return g.selectAll('line').style('opacity', 0.9); })

Sol LeWitt’s Wall Drawing #118 (1971)

On a wall surface, any continuous stretch of wall, using a hard pencil, place fifty points at random. The points should be evenly distributed over the area of the wall. All of the points should be connected by straight lines.


notes: interaction is using a voronoi there's an awesome post by Peter Beshai

Other coded examples by amiccolis via http://solvingsol.com/ and in p5js by Pol Guezennec 2017

And physical ones diaart and ericdoeringer

image

todo: try in canvas as interacting/updating 5000 lines (50*50) in svg is a bit much

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<style>
html {
height: 99%;
}
body {
font-family: Consolas, monaco, monospace;
width: 100%;
height: 100%;
background: #130C0E;
margin: 0;
padding: 0;
}
svg {
width: 100%;
height: 100%;
}
line {
stroke-opacity: 0.6;
stroke-width: 0.5;
}
</style>
</head>
<body>
<!-- <header>
<p>Wall Drawing #118 (1971)</p>
</header> -->
<svg>
<g id="vis"></g>
</svg>
<script src="//d3js.org/d3.v4.min.js" charset="utf-8"></script>
<!-- d3 code -->
<script src=".script-compiled.js" charset="utf-8"></script>
</body>
</html>
const width = window.innerWidth
const height = window.innerHeight
const svg = d3.select('svg')
.attr('width', width)
.attr('width', height)
const g = svg.select('#vis')
// create 50 items that have x and y uniformly random
const data = d3.range(50).map(n => {
return {
x: Math.floor(d3.randomUniform(1, width-10)()),
y: Math.floor(d3.randomUniform(1, height-10)()),
id: n
}
})
// scale for some colour differentiation
const sequentialScale = d3.scaleSequential()
.domain([0, 50])
.interpolator(d3.interpolateRainbow)
// append the 50 circles driven by the data
g.selectAll('circle')
.data(data)
.enter()
.append('circle')
.attr('r', 2)
.attr('cx', d => d.x)
.attr('cy', d => d.y)
.style('fill', (d, i) => sequentialScale(i))
// loop 50 times (length of data)
data.forEach((o, n) => {
// append 50 lines driven by the data
g.selectAll('line.id-' + n)
.data(data)
.enter()
.append('line')
.attr('class', 'id-' + n)
// append a line form a reference (point in data)
.attr('x1', data[n].x)
.attr('y1', data[n].y)
// connecting to all other points (all points in data)
.attr('x2', d => d.x)
.attr('y2', d => d.y)
.attr('stroke', (d, i) => sequentialScale(i))
})
// add some interaction so we can see the sets of lines :)
const voronoi = d3.voronoi()
.x(d => d.x)
.y(d => d.y)
.size([width, height])(data)
// draw the polygons
const voronoiPolygons = g.append('g')
.attr('class', 'voronoi-polygons')
const binding = voronoiPolygons
.selectAll('path')
.data(voronoi.polygons())
binding.enter().append('path')
// .style('stroke', 'tomato')
.style('fill', 'transparent')
.attr('d', d => `M${d.join('L')}Z`)
.on('mouseover', d => {
g.selectAll(':not(.id-' + d.data.id + ')')
.style('opacity', 0.1)
})
.on('mouseout', () => g.selectAll('line').style('opacity', 0.9))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment