var data = [ { // 0 ref: 'h1', // top horizontal line x1: 0, y1: 0, // use 0 for start, 0.5 for midway, and 1 for end x2: 1, y2: 0, }, { // 1 ref: 'h2', // mid horizontal line x1: 0, y1: 0.5, x2: 1, y2: 0.5, }, { // 2 ref: 'h3', // end horizontal line x1: 0, y1: 1, x2: 1, y2: 1, }, { // 3 ref: 'v1', // left vertical line x1: 0, y1: 0, x2: 0, y2: 1, }, { // 4 ref: 'v2', // mid vertical line x1: 0.5, y1: 0, x2: 0.5, y2: 1, }, { // 5 ref: 'v3', // right vertical line x1: 1, y1: 0, x2: 1, y2: 1, } ] // filter to display morphings var dataMorpingCombinations = [ [0, 3], // A1 [2, 3], // A2 [0, 2, 3], // A3 [1, 3], // A4 [0, 1, 3], // A5 [1, 2, 3], // A6 [0, 1, 2, 3], // A7 [0, 5], // B1 [2, 5], // B2 [0, 2, 5], // B3 [1, 5], // B4 [0, 1, 5], // B5 [1, 2, 5], // B6 [0, 1, 2, 5], // B7 [0, 3, 5], // C1 [2, 3, 5], // C2 [0, 2, 3, 5], // C3 [1, 3, 5], // C4 [0, 1, 3, 5], // C5 [1, 2, 3, 5], // C6 [0, 1, 2, 3, 5], // C7 [0, 4], // D1 [2, 4], // D2 [0, 2, 4], // D3 [1, 4], // D4 [0, 1, 4], // D5 [1, 2, 4], // D6 [0, 1, 2, 4], // D7 [0, 3, 4], // E1 [2, 3, 4], // E2 [0, 2, 3, 4], // E3 [1, 3, 4], // E4 [0, 1, 3, 4], // E5 [1, 2, 3, 4], // E6 [0, 1, 2, 3, 4], // E7 [0, 4, 5], // F1 [2, 4, 5], // F2 [0, 2, 4, 5], // F3 [1, 4, 5], // F4 [0, 1, 4, 5], // F5 [1, 2, 4, 5], // F6 [0, 1, 4, 5], // F7 [0, 3, 4, 5], // G1 [2, 3, 4, 5], // G2 [0, 2, 3, 4, 5], // G3 [1, 3, 4, 5], // G4 [0, 1, 3, 4, 5], // G5 [1, 2, 3, 4, 5], // G6 [0, 1, 2, 3, 4, 5] // G7 ] // map the morphings above with the data to draw lines var dataMorp = dataMorpingCombinations.map(function(nested) { return nested.map(function(d) { return data[d] }) }) var svg = d3.select('#vis') var lineScale = d3.scaleLinear() .domain([0, 1]) .range([0, 400]) function render(data) { var update = svg.selectAll('line') .data(data, function(d){ return d.ref }) var enter = update.enter() .append('line') enter.merge(enter) .attr('x1', function (d) { return lineScale(d.x1); }) .attr('y1', function (d) { return lineScale(d.y1); }) .attr('x2', function (d) { return lineScale(d.x2); }) .attr('y2', function (d) { return lineScale(d.y2); }) update.exit().remove() } function nav(data, n) { // track if a btn is clicked var activeState = false // append some buttons d3.select('header') .append('nav').append('ul') .attr('class', 'list-reset') .selectAll('.btn') .data(d3.range(n)) .enter().append('li') .attr('class', function (d) { return ("inline-block center btn btn-" + (d +1)); }) .on('mouseover', function hover(d, i) { render(data[i]) }) .on('click', function click(d, i, e) { // update the state of buttons activeState = (activeState) ? false : true console.log('activeState', activeState) // allow users to toggle button if (activeState) { d3.selectAll(e) // filter out all but `this` one .filter(function (d) { return d !== i; }) // `i` is form the `click` function // using a css selector would also have worked: // .filter(':not(:hover)') .style('pointer-events', 'none') .style('opacity', 0.2) render(data[i]) } else { // reset d3.selectAll(e) .style('pointer-events', 'auto') .style('opacity', 1) } }) .text(function (d) { return d+1; }) } // render the nav and the lines nav(dataMorp, 49) render(data)