Skip to content

Instantly share code, notes, and snippets.

@ManuelBlanc
Last active November 6, 2018 19:59
Show Gist options
  • Save ManuelBlanc/69cc1b4ee5cf1d5b8533bd82b14559bf to your computer and use it in GitHub Desktop.
Save ManuelBlanc/69cc1b4ee5cf1d5b8533bd82b14559bf to your computer and use it in GitHub Desktop.
Projection Test
license: mit
<!DOCTYPE html>
<meta charset="utf-8">
<style>
.focus {
fill: darkslategray;
}
.plane {
shape-rendering: crispEdges;
stroke: dimgray;
stroke-width: 3;
}
.info-line {
stroke: slategray;
stroke-width: 1.5;
}
.ball {
fill: crimson;
}
.projection {
shape-rendering: crispEdges;
stroke: crimson;
stroke-width: 5;
}
</style>
<svg width="500" height="400"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
"use strict";
const svg = d3.select("svg"),
width = +svg.attr("width"),
height = +svg.attr("height"),
g = svg.append("g").attr("transform", `translate(${width/2},${height/2})`);
const plane = g.append("line")
.attr("class", "plane")
.attr("x1", -width/2)
.attr("y1", 0)
.attr("x2", +width/2)
.attr("y2", 0)
let ang = 0.8, ball_radius = 40, orbit_radius = 250, fx = 0, fy = 100;
const line1 = g.append("line")
.attr("class", "info-line")
.attr("x1", fx)
.attr("y1", fy);
const line2 = g.append("line")
.attr("class", "info-line")
.attr("x1", fx)
.attr("y1", fy);
const ball = g.append("circle")
.attr("class", "ball")
.attr("r", ball_radius);
const projection = g.append("line")
.attr("class", "projection");
const focus = g.append("circle")
.attr("class", "focus")
.attr("cx", fx)
.attr("cy", fy)
.attr("r", 3);
const update = (select) => {
ang *= -1;
const sin_t = (t) => Math.sin(ang * t)
const cos_t = (t) => Math.cos(ang * t)
const tan_t = (t) => Math.tan(ang * t)
const ball_x = (t) => fx + orbit_radius*sin_t(t, ang);
const ball_y = (t) => fy - orbit_radius*cos_t(t, ang);
const radius_offset_x = (t) => ball_radius*cos_t(t);
const radius_offset_y = (t) => ball_radius*sin_t(t);
select(ball)
.attrTween("cx", () => ball_x)
.attrTween("cy", () => ball_y);
select(line1)
.attrTween("x2", () => (t) => ball_x(t) + radius_offset_x(t))
.attrTween("y2", () => (t) => ball_y(t) + radius_offset_y(t));
select(line2)
.attrTween("x2", () => (t) => ball_x(t) - radius_offset_x(t))
.attrTween("y2", () => (t) => ball_y(t) - radius_offset_y(t));
const shit = Math.atan2(ball_radius, orbit_radius)
select(projection)
.attrTween("x1", () => (t) => fy*Math.tan(+shit + ang * t))
.attrTween("x2", () => (t) => fy*Math.tan(-shit + ang * t));
};
const ease = (t) => {
return (t < 0.5) ? d3.easeCubic(2*t)-1 : d3.easeCubic(2*t-1);
};
const transition_factory = (duration) => (selection) => {
return selection.transition().duration(duration).ease(ease);
};
const ANIMATION_DURATION = 2000
const transition = transition_factory(ANIMATION_DURATION);
update(transition_factory(0));
update(transition);
d3.interval(() => update(transition), ANIMATION_DURATION);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment