0

I have this snippet which puts a full-page <canvas> element into a 45-degree perspective using CSS. However, the transformed canvas exceeds the page's bounds and is clipped:

window.onload = window.onresize = function() {
  // draw a gradient on the canvas
  var canvas = document.querySelector('canvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  var ctx = canvas.getContext('2d');
  var grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
  grad.addColorStop(0, '#ff0000');
  grad.addColorStop(0.5, '#ffff00');
  grad.addColorStop(1, '#00ff00');
  ctx.fillStyle = grad;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
};
body {
  margin: 0;
  overflow: hidden;
}

canvas {
  transform-style: preserve-3d;
  transform: rotateX(45deg);
}

.container {
  width: 100%;
  height: 100%;
  perspective: 50vw;
  perspective-origin: 50% 0%;
}
<div class="container">
  <canvas></canvas>
</div>

How would I ensure the entire canvas stays within the page's bounds (bottom side of the trapezoid should have the exact same width as the page), while maintaining the perspective effect? Either CSS or JavaScript solutions are fine, as long as they work with any page size.

1 Answers1

0

translate it backwards using translateZ

look for a comment in CSS

window.onload = window.onresize = function() {
  // draw a gradient on the canvas
  var canvas = document.querySelector('canvas');
  canvas.width = window.innerWidth;
  canvas.height = window.innerHeight;
  var ctx = canvas.getContext('2d');
  var grad = ctx.createLinearGradient(0, 0, 0, canvas.height);
  grad.addColorStop(0, '#ff0000');
  grad.addColorStop(0.5, '#ffff00');
  grad.addColorStop(1, '#00ff00');
  ctx.fillStyle = grad;
  ctx.fillRect(0, 0, canvas.width, canvas.height);
};
body {
  margin: 0;
  overflow: hidden;
}

canvas {
  transform-style: preserve-3d;
  /* added translation here */
  transform: translateZ(-50vmax) rotateX(45deg);
}

.container {
  width: 100%;
  height: 100%;
  perspective: 50vw;
  perspective-origin: 50% 0%;
  
}
<div class="container">
  <canvas></canvas>
</div>
ashish singh
  • 6,526
  • 2
  • 15
  • 35
  • This solution is not adequate for all page sizes. Try clicking "full page" on the snippet, or running it on [Codepen](https://codepen.io/anon/pen/qygYEd). – RichardG867 Aug 11 '18 at 17:51
  • thats just a technique .. value can be in percentages or viewport units.. and can be altered with media query – ashish singh Aug 11 '18 at 17:57