Skip to content

Instantly share code, notes, and snippets.

@Brideau
Last active October 30, 2015 03:14
Show Gist options
  • Save Brideau/e613b01862b2a586be41 to your computer and use it in GitHub Desktop.
Save Brideau/e613b01862b2a586be41 to your computer and use it in GitHub Desktop.
Perspective Vibrations

Exploring some ways to provide perspective and give a faux 3D effect.

<!DOCTYPE html>
<meta charset="utf-8">
<html>
<head>
<title></title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.6/d3.min.js" charset="utf-8"></script>
</head>
<body>
<canvas width="960" height="500"></canvas>
<script type="text/javascript">
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height
planeDist = 1, // Distance from the 'eye' to the viewing plane
closeDepth = 4, // Distance to the close set of squares
farDepth = 10, // Distance to the far set of squares
squareSize = 23,
buffer = 0.2,
focalWidth = 1;
// Adjusts the size of squares based on their distance from the // viewer. Based on simple similar triangles ratio.
function depthAdjust(distFromAxis, minDistance, planeDist) {
return (planeDist * distFromAxis) / (planeDist + minDistance) * 40;
}
// Gets the size of the squares for each plane
var projFarSize = depthAdjust(squareSize, farDepth, planeDist);
var projCloseSize = depthAdjust(squareSize, closeDepth, planeDist);
// Used to figure out how many squares can fit on the page
function createGrid(objectSize, totalWidth, totalHeight) {
// Size of the square plus its buffer
var buffPixels = objectSize * buffer;
var bufferedSize = objectSize + buffPixels;
// The number that fill fit horzontally and vertically
var xFit = Math.ceil(totalWidth / bufferedSize);
var yFit = Math.ceil(totalHeight / bufferedSize);
// Used to align everything around the center of the screen
var xStart = (totalWidth - (xFit * objectSize + (xFit + 1) * buffPixels)) / 2 + buffPixels;
var yStart = (totalHeight - (yFit * objectSize + (yFit + 1) * buffPixels)) / 2 + buffPixels;
return {
"xFit": xFit,
"yFit": yFit,
"xStart": xStart,
"yStart": yStart
}
}
// Given a value along a sin curve and the distance the object
// is from the plane, return the shifted grid
function shiftObject(position, depth) {
return depthAdjust(squareSize + focalWidth * position, depth, planeDist) - depthAdjust(squareSize, depth, planeDist);
}
var counter = 0;
function generateGrids() {
context.clearRect(0, 0, width, height);
position = Math.sin(Math.PI * counter / 10);
counter = counter > 19 ? 0 : counter + 1;
adjFar = shiftObject(position, farDepth);
gridFar = createGrid(projFarSize, width, height);
adjClose = shiftObject(position, closeDepth);
gridClose = createGrid(projCloseSize, width, height);
for (var i = 0; i < gridFar.xFit; i++) {
for (var j = 0; j < gridFar.yFit; j++) {
// Index * width + buffer - half width
var xPos = gridFar.xStart + i * (projFarSize + buffer * projFarSize) + adjFar;
var yPos = gridFar.yStart + j * (projFarSize + buffer * projFarSize);
context.fillStyle = '#8ED6FF';
context.globalAlpha = 1;
context.fill();
context.fillRect(xPos, yPos, projFarSize, projFarSize);
}
}
for (var i = 0; i < gridClose.xFit; i++) {
for (var j = 0; j < gridClose.yFit; j++) {
// Index * width + buffer - half width
var xPos = gridClose.xStart + i * (projCloseSize + buffer * projCloseSize) + adjClose;
var yPos = gridClose.yStart + j * (projCloseSize + buffer * projCloseSize);
context.fillStyle = '#3AB4FC';
context.globalAlpha = 0.5;
context.fill();
context.fillRect(xPos, yPos, projCloseSize, projCloseSize);
}
}
}
setInterval("generateGrids()", 15);
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment