Skip to content

Instantly share code, notes, and snippets.

@clindsey
Created January 28, 2017 20:31
Show Gist options
  • Save clindsey/e8eb4ed6729218f78843a1c1f6533a71 to your computer and use it in GitHub Desktop.
Save clindsey/e8eb4ed6729218f78843a1c1f6533a71 to your computer and use it in GitHub Desktop.
triangle-nest-1.0.0
<canvas
id="js-canvas"
height="410"
width="480"
></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/randomcolor/0.4.4/randomColor.min.js"></script>
setTimeout(() => {
const canvasEl = document.getElementById('js-canvas');
const $ = canvasEl.getContext('2d');
const {
width,
height
} = canvasEl;
const centerX = width / 2;
const centerY = height / 2;
const radius = Math.min(width, height) / 2;
const pointsUp = buildPoints(3, Math.PI * 1.5);
const pointsDown = buildPoints(3, Math.PI * 0.5);
const colors = ['0000ff', '00ff00', 'ff0000'];
const colorPoints = pointsUp.map(([x, y]) => ({color: colors.pop(), x: x * radius + centerX, y: y * radius + centerY}));
const colorPicker = calculateColor(colorPoints, radius);
triangleNest($, centerX, centerY, radius, [pointsDown, pointsUp], colorPicker, 3);
}, 0);
function triangleNest ($, x, y, radius, [centerPoints, outerPoints], colorPicker, iteration) {
const newRadius = radius / 2;
if (!iteration) {
drawPolygon($, x, y, newRadius, centerPoints, colorPicker(x, y));
} else {
triangleNest($, x, y, newRadius, [outerPoints, centerPoints], colorPicker, iteration - 1);
}
outerPoints.forEach(([pointX, pointY], edgeIndex) => {
const newX = pointX * newRadius + x;
const newY = pointY * newRadius + y;
if (!iteration) {
drawPolygon($, newX, newY, newRadius, outerPoints, colorPicker(newX, newY));
} else {
triangleNest($, newX, newY, newRadius, [centerPoints, outerPoints], colorPicker, iteration - 1);
}
});
}
function calculateColor (colorPoints, radius) {
const maxRadius = radius * 1.6783; // refactor, magic number
const colorFactors = colorPoints.map(({color, x, y}) => {
const colorInt = parseInt(color, 16);
return {
x,
y,
r: colorInt >> 16 & 0xff,
g: colorInt >> 8 & 0xff,
b: colorInt >> 0 & 0xff
};
});
const pointA = [colorFactors[0].x, colorFactors[0].y];
const pointB = [colorFactors[1].x, colorFactors[1].y];
const pointC = [colorFactors[2].x, colorFactors[2].y];
const totalArea = measureArea(pointA, pointB, pointC);
return (pointX, pointY) => {
const pointD = [pointX, pointY];
const factorA = measureArea(pointA, pointB, pointD) / totalArea;
const factorB = measureArea(pointB, pointC, pointD) / totalArea;
const factorC = 1 - (factorA + factorB)
const r = (colorFactors[0].r * factorA) + (colorFactors[1].r * factorB) + (colorFactors[2].r * factorC);
const g = (colorFactors[0].g * factorA) + (colorFactors[1].g * factorB) + (colorFactors[2].g * factorC);
const b = (colorFactors[0].b * factorA) + (colorFactors[1].b * factorB) + (colorFactors[2].b * factorC);
return '#' + ((b | g << 8 | r << 16) | 0x1000000).toString(16).substring(1);
};
}
function measureArea (pointA, pointB, pointC) {
const side1 = measureDistance(pointA, pointB);
const side2 = measureDistance(pointB, pointC);
const side3 = measureDistance(pointC, pointA);
const perimeter = (side1 + side2 + side3) / 2;
return Math.sqrt(perimeter * ((perimeter - side1) * (perimeter - side2) * (perimeter - side3)));
}
function measureDistance ([x1, y1], [x2, y2]) {
return Math.sqrt(((x2 - x1) * (x2 - x1)) + ((y2 - y1) * (y2 - y1)));
}
function drawPolygon ($, x, y, radius, [firstPoint, ...otherPoints], color) {
$.lineWidth = 1;
$.strokeStyle = color;
$.fillStyle = color;
$.beginPath();
$.moveTo(x + firstPoint[0] * radius, y + firstPoint[1] * radius);
[...otherPoints, firstPoint].forEach(nextPoint => {
$.lineTo(x + nextPoint[0] * radius, y + nextPoint[1] * radius);
});
$.fill();
$.stroke();
}
function buildPoints (edgeCount, rotationOffset = 0) {
const stepSize = (Math.PI * 2) / edgeCount;
return Array(...(new Array(edgeCount))).map((_, edgeIndex) => [
Math.cos(edgeIndex * stepSize + rotationOffset),
Math.sin(edgeIndex * stepSize + rotationOffset)
]);
}
canvas {
display: block;
margin: 0 auto;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment