Skip to content

Instantly share code, notes, and snippets.

@max-l
Last active December 11, 2018 17:06
Show Gist options
  • Save max-l/95abb17b61bc990e5f12fff86f5ed46c to your computer and use it in GitHub Desktop.
Save max-l/95abb17b61bc990e5f12fff86f5ed46c to your computer and use it in GitHub Desktop.
sink3
license: mit
<!DOCTYPE html>
<meta charset="utf-8">
<head>
<style>
path {fill: none;stroke: #000;stroke-width: 3px;}
circle {fill: steelblue;stroke: #fff;stroke-width: 1px;}
sink {}
</style>
</head>
<body>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
//stopz dad a
var svg = d3.select("body")
.append("svg")
.attr("width", 900)
.attr("height", 600)
.attr("class", "sink")
const radius = 5
const stepDistance = 5
const redrawInterval = 40
var data = []
const faucet = [[71, 64],[119, 95],[130, 139]]
const vacuum = [[391, 64],[344, 95],[335, 139]]
const tub = [[75, 120],[75, 200],
[370, 200], [370,120]]
let liquidHeight = 50
let surfaceY = tub[0][1]+ liquidHeight
const topLeft = [tub[0][0],surfaceY]
const rightBottom = [370,200]
const faucetPath = svg.append("path")
.data([faucet])
.attr("d", d3.line().curve(d3.curveCardinal))
const vacuumPath = svg.append("path")
.data([vacuum])
.attr("d", d3.line().curve(d3.curveCardinal))
svg.append("path")
.data([tub])
.attr("d", d3.line())
const translateAlong = path => {
const l = path.getTotalLength() ;
return (d, i, a) => t => {
const p = path.getPointAtLength(t * l)
return `translate(${p.x},${p.y})`;
};
}
const initPoints = (pointCount) => {
const rnd = d3.randomUniform(1, 10)
d3.range(pointCount).map(i=> {
data.push({
id: i, x:topLeft[0], y:topLeft[1],
slope: rnd() / 10,
x_dir: 1,y_dir: 1,
state:0
})
})
}
initPoints(5)
const rndDelay = d3.randomUniform(500, 1500)
redraw(data);
d3.interval(() => redraw(update(data)), redrawInterval)
function redraw(data){
var circle = svg.selectAll("circle")
.data(data)
circle.enter().append("circle")
.attr("r", radius)
.transition()
.ease(d3.easeQuad)
.delay(rndDelay)
.duration(2000)
.attrTween("transform", translateAlong(faucetPath.node()))
.on("end", (d,i,j) => {
const lastP = faucet[2]
d.state = 1
d.x = lastP[0]
d.y = lastP[1]
d3.select(j[i])
.attr("transform","translate(0,0)")
})
circle.filter(d => d.state == 1)
//.attr("transform","translate(0,0)")
.attr("r", radius)
.attr("cx", d => d.x)
.attr("cy", d => d.y)
}
const update = data =>
data.map(d => calcPointB(d, stepDistance, d.slope))
const calcPointB = (p, d, m) => {
const getDir = (coord, dir, maxCood, minCoord) =>
(Math.ceil(coord) <= minCoord + radius) ? 1 :
(Math.ceil(coord) >= maxCood - radius) ? -1 : dir
const sqrt = Math.sqrt
const pow2 = a=>Math.pow(a, 2)
p.x_dir = getDir(p.x, p.x_dir, rightBottom[0], topLeft[0]);
p.y_dir = getDir(p.y, p.y_dir, rightBottom[1], surfaceY);
p.x = p.x +
(d * sqrt(1 / (1 + pow2(m))) * p.x_dir)
p.y = p.y +
(m * d * sqrt(1 / (1 + pow2(m))) * p.y_dir);
return p;
}
</script>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment