Built with blockbuilder.org
Created
December 21, 2017 15:50
-
-
Save mathiasmadsen/8d838cb4389a9370a0238354583cef59 to your computer and use it in GitHub Desktop.
kp-test
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
license: mit |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<html> | |
<head> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.1/lodash.min.js"></script> | |
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.js" charset="utf-8"></script> | |
<style> | |
* { | |
font-family: Helvetica, Verdana, sans-serif; | |
} | |
.marker { | |
position: fixed; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 400px; | |
border: 1px solid #ccc; | |
} | |
</style> | |
</head> | |
<body> | |
<svg width="1000" height="20000"></svg> | |
<div class="marker"></div> | |
<script> | |
var data = {categoryX: 300, points: [{"x":450,"y":300},{"x":500,"y":300},{"x":500,"y":350},{"x":500,"y":450},{"x":500,"y":566.63},{"x":300,"y":594.08},{"x":300,"y":650.37},{"x":300,"y":723.46},{"x":300,"y":864.01},{"x":300,"y":879.88},{"x":300,"y":1138.35},{"x":300,"y":1158.8},{"x":300,"y":1220.25},{"x":300,"y":1489.94},{"x":300,"y":1583.51},{"x":300,"y":1627.55},{"x":300,"y":1739.97},{"x":300,"y":1800.63},{"x":300,"y":1885.21},{"x":300,"y":1979.47},{"x":300,"y":2057.81},{"x":150,"y":2059.57},{"x":300,"y":2097.48},{"x":300,"y":2152.41},{"x":300,"y":2152.46},{"x":300,"y":2157.54},{"x":300,"y":2157.56},{"x":300,"y":2174.22},{"x":300,"y":2188.61},{"x":300,"y":2213.54},{"x":300,"y":2231.43},{"x":300,"y":2252},{"x":300,"y":2275.33},{"x":300,"y":2291.35},{"x":300,"y":2319.71},{"x":300,"y":2328.22},{"x":300,"y":2345.74},{"x":250,"y":2345.91},{"x":300,"y":2367.61},{"x":300,"y":2409.25},{"x":300,"y":2429.13},{"x":300,"y":2447.6},{"x":300,"y":2467.67},{"x":300,"y":2473.07},{"x":200,"y":2473.24},{"x":300,"y":2485.47},{"x":300,"y":2528.83},{"x":300,"y":2664.08},{"x":300,"y":2664.16},{"x":250,"y":2665.75},{"x":300,"y":2681.58},{"x":250,"y":2682.98},{"x":250,"y":2683.03},{"x":300,"y":2703.05},{"x":250,"y":2707.75},{"x":300,"y":2719.75},{"x":300,"y":2725.5},{"x":250,"y":2727.59},{"x":300,"y":2741.92},{"x":250,"y":2758.02},{"x":300,"y":2758.88},{"x":300,"y":2766},{"x":250,"y":2768.52},{"x":300,"y":2781.85},{"x":250,"y":2783.5},{"x":300,"y":2790.62},{"x":300,"y":2797.6},{"x":300,"y":2803.05},{"x":300,"y":2822.51},{"x":300,"y":2842.45},{"x":300,"y":2859.41},{"x":250,"y":2861.83},{"x":250,"y":2861.9},{"x":300,"y":2878.11},{"x":300,"y":2899.3},{"x":300,"y":2899.39},{"x":150,"y":2900.16},{"x":300,"y":2915.11},{"x":300,"y":2954.28},{"x":300,"y":2963.22},{"x":300,"y":2993.16},{"x":300,"y":3024.93},{"x":300,"y":3034.73},{"x":300,"y":3053.71},{"x":100,"y":3108.65},{"x":300,"y":3108.78},{"x":100,"y":3170.02},{"x":300,"y":3307.02},{"x":300,"y":3347},{"x":100,"y":3386.84},{"x":300,"y":3388.35},{"x":300,"y":3392.8},{"x":300,"y":3409.08},{"x":200,"y":3482.29},{"x":300,"y":3490.06},{"x":100,"y":3490.08},{"x":300,"y":3521.3},{"x":300,"y":3525.8},{"x":300,"y":3527.47},{"x":100,"y":3527.71},{"x":350,"y":3785.85},{"x":300,"y":3817.04},{"x":100,"y":3879.62},{"x":300,"y":3990.06},{"x":100,"y":3994.39},{"x":300,"y":4033.28},{"x":150,"y":4040},{"x":300,"y":4168.39},{"x":300,"y":4203.66},{"x":300,"y":4309.47},{"x":300,"y":4355.49},{"x":300,"y":4438.63},{"x":300,"y":4501.4},{"x":300,"y":4527.18},{"x":300,"y":4527.24},{"x":300,"y":4527.32},{"x":300,"y":4705.31},{"x":200,"y":4790.07},{"x":300,"y":4790.17},{"x":300,"y":4831.58},{"x":300,"y":4909.79},{"x":300,"y":4978.06},{"x":300,"y":5024.68},{"x":300,"y":5341.95},{"x":300,"y":5404.04},{"x":300,"y":5707.09},{"x":300,"y":5846.84},{"x":300,"y":5918.93},{"x":300,"y":5956.66},{"x":300,"y":6008.86},{"x":300,"y":6032.41},{"x":300,"y":6074.86},{"x":300,"y":6160.47},{"x":300,"y":6494.77},{"x":300,"y":6544.9},{"x":300,"y":6554.59},{"x":300,"y":6572.89},{"x":300,"y":6620.47},{"x":300,"y":6628.18},{"x":300,"y":6651.49},{"x":300,"y":6690.64},{"x":300,"y":6734.86},{"x":300,"y":6784.42},{"x":300,"y":6897.47},{"x":50,"y":6978.9},{"x":300,"y":7053.46},{"x":300,"y":7064.33},{"x":300,"y":7081.25},{"x":200,"y":7169.69},{"x":300,"y":7169.81},{"x":300,"y":7209.83},{"x":300,"y":7258.2},{"x":100,"y":7352.41},{"x":300,"y":7365.26},{"x":300,"y":7437.33},{"x":300,"y":7556.63},{"x":300,"y":7589.71},{"x":300,"y":7626.93},{"x":300,"y":7649.84},{"x":300,"y":7666.02},{"x":300,"y":7689.28},{"x":300,"y":7705.31},{"x":300,"y":7727.3},{"x":300,"y":7744.38},{"x":300,"y":7766.83},{"x":300,"y":7817.81},{"x":300,"y":7862.84},{"x":400,"y":7882.63},{"x":300,"y":8036.55},{"x":300,"y":8192.58},{"x":300,"y":8419.56},{"x":300,"y":8566.87},{"x":300,"y":8667.14},{"x":300,"y":8780.15},{"x":300,"y":8784.1},{"x":300,"y":8827.76},{"x":300,"y":8855.53},{"x":300,"y":8890.78},{"x":300,"y":8939.6},{"x":300,"y":8997.51},{"x":300,"y":9169.01},{"x":300,"y":9314.37},{"x":300,"y":9399.17},{"x":300,"y":9594.91},{"x":500,"y":9756.56},{"x":200,"y":10109.02}]}; | |
var svg = d3.select('svg'); | |
var distancePath = svg.append('path') | |
.attr('fill', 'none') | |
.attr('stroke', 'none').node(); | |
var source; | |
var target; | |
var gap = 100; | |
var totalDistance = 0; | |
_.each(data.points, function(target) { | |
if (!source) { | |
target.d = 'M' + target.x + ',' + target.y; | |
} else { | |
if (source.y > target.y - gap) { | |
// if they're sufficiently close to each other | |
if (source.x === target.x) { | |
target.d = drawLine(target.x, target.y); | |
setDistance(source, target); | |
} else { | |
target.d = drawCurve(source.x, source.y, target.x, target.y); | |
setDistance(source, target); | |
target.y1 = target.y - source.y; | |
target.interpolate1 = d3.interpolate(0, target.distance); | |
} | |
} else { | |
target.d = ''; | |
if (source.x !== data.categoryX) { | |
// if the source repo owner isn't the same as the contributor, move the line back | |
target.d += drawCurve(source.x, source.y, data.categoryX, source.y + gap / 3); | |
setDistance(source, target); | |
target.y1 = gap / 3; | |
target.interpolate1 = d3.interpolate(0, target.distance); | |
} | |
x = target.x; | |
y = target.y; | |
if (target.x !== data.categoryX) { | |
x = data.categoryX; | |
y = target.y - gap / 3; | |
} | |
target.d += drawLine(x, y); | |
target.y2 = y - (target.y1 || 0); | |
setDistance(source, target); | |
if (target.x !== data.categoryX) { | |
target.d += drawCurve(x, y, target.x, target.y); | |
var currentDistance = target.distance; | |
setDistance(source, target); | |
target.y3 = gap / 3; | |
target.interpolate2 = d3.interpolate(0, target.distance - currentDistance); | |
} | |
} | |
target.totalDistance = (totalDistance += target.distance); | |
} | |
source = target; | |
}); | |
var path = svg.append('path') | |
.attr('d', _.pluck(data.points, 'd').join(' ')) | |
.attr('fill-opacity', 0) | |
.attr('stroke', '#3FB8AF') | |
.attr('stroke-width', 4) | |
.attr('stroke-linecap', 'round') | |
.attr('stroke-dasharray', totalDistance) | |
.attr('stroke-dashoffset', totalDistance); | |
var circle = svg.selectAll('circle') | |
.data(data.points).enter().append('circle') | |
.attr('fill', '#fff') | |
.attr('stroke', '#3FB8AF') | |
.attr('stroke-width', 2) | |
.attr('cx', function(d) {return d.x}) | |
.attr('cy', function(d) {return d.y}) | |
.attr('r', 4); | |
window.addEventListener('scroll', _.throttle(windowScroll, 200)); | |
function windowScroll() { | |
var top = scrollY + 400; | |
var source; | |
var target = _.find(data.points, function(point) { | |
if (point.y >= top) { | |
return true; | |
} | |
source = point; | |
return false; | |
}); | |
if (source && target) { | |
var distance = 0; | |
var distanceFromSource = top - source.y; | |
if (!target.interpolate1) { | |
// if there's no interpolate1 | |
if (!target.interpolate2) { | |
// and there's no interpolate2, must mean it's a straight line | |
distance = distanceFromSource + source.totalDistance; | |
} else { | |
// if there's a interpolate2, must mean there's a straight line | |
// and then a curve at the end, so figure out if we're in straight line or curve part | |
if (distanceFromSource <= target.y2) { | |
// it's in straight line part | |
distance = distanceFromSource + source.totalDistance; | |
} else { | |
// if it's in last curve part, first interpolate the curve | |
// and then add that back to the straight part and the previous total distance | |
var partialDistance = (distanceFromSource - target.y2) / target.y3; | |
distance = target.interpolate2(partialDistance) + target.y2 + source.totalDistance; | |
} | |
} | |
} else { | |
// if there's interpolate1, must mean there's a first curve | |
if (distanceFromSource <= target.y1) { | |
// so if it's within the first curve, interpolate that and add it to total distance | |
var partialDistance = distanceFromSource / target.y1; | |
distance = target.interpolate1(partialDistance) + source.totalDistance; | |
} else if (distanceFromSource <= (target.y1 + target.y2)) { | |
// if we're in line part, add curve to it | |
distance = target.interpolate1(1) + (distanceFromSource - target.y1) + source.totalDistance; | |
} else if (interpolate2) { | |
var partialDistance = (distanceFromSource - target.y2 - target.y1) / target.y3; | |
distance = target.interpolate1(1) + target.y2 + target.interpolate2(partialDistance); | |
} | |
} | |
// var partialDistance = (top - source.y) / (target.y - source.y); | |
// var distance = target.interpolater(partialDistance) + source.totalDistance; | |
path.transition().duration(200) | |
.attr('stroke-dashoffset', totalDistance - (distance || 0)); | |
} | |
}; | |
function drawLine(x, y) { | |
return 'L' + x + ',' + y; | |
} | |
function drawCurve(x1, y1, x2, y2) { | |
var cy = (y1 + y2) / 2; | |
return 'C' + x1 + ',' + cy + ' ' + x2 + ',' + cy + ' ' + x2 + ',' + y2; | |
} | |
function setDistance(source, target) { | |
var distancePathD = 'M' + source.x + ',' + source.y + ' ' + target.d; | |
distancePath.setAttribute('d', distancePathD); | |
target.distance = parseFloat(distancePath.getTotalLength().toFixed(2)); | |
} | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment