Auto-adjust canvas by itself in all possible sizes - javascript

I have one canvas-fx code ("stars" coming from deep to front, all centered, simulating space-navigation; it was not done by me) that I want to put in one website as a background.
I want it so that when a user resizes the window (dragging to right or left or resizing or whatever), the effect can auto-adjust itself so that the stars always come from the center in any size or even changing the desktop resolution (I refer the FX can auto-reset by itself the same it does when rendering the webcode).
Also I want it so that the code can adjust itself to the size of the content of the body (i.e. adding content from up to down, etc).
Finally, how can I quit the bottom bar, leaving only the scroll bar from the right?
Here is the complete code I am using:
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>FX TEST</title>
<STYLE type="text/css">
html, body {
width:100%;
height:100%;
}
#Canvas2D {
position:absolute;
top:0;
left:0;
}
#content {
z-index: 10;
position: relative;
}
</STYLE>
<script language="JavaScript">
function setup() {
var fov = 150;
var SCREEN_WIDTH = 1920;
var SCREEN_HEIGHT = 1080;
var HALF_WIDTH = SCREEN_WIDTH / 2;
var HALF_HEIGHT = SCREEN_HEIGHT / 2;
var numPoints = 300;
function draw3Din2D(point3d) {
x3d = point3d[0];
y3d = point3d[1];
z3d = point3d[2];
var scale = fov / (fov + z3d);
var x2d = (x3d * scale) + HALF_WIDTH;
var y2d = (y3d * scale) + HALF_HEIGHT;
c.lineWidth = scale;
c.strokeStyle = "rgb(255,255,255)";
c.beginPath();
c.moveTo(x2d, y2d);
c.lineTo(x2d + scale, y2d);
c.stroke();
}
var canvas = document.getElementById('Canvas2D');
var c = canvas.getContext('2d');
var points = [];
function initPoints() {
for(i = 0; i < numPoints; i++) {
point = [(Math.random() * 400) - 200, (Math.random() * 400) - 200, (Math.random() * 400) - 200];
points.push(point);
}
}
function render() {
c.fillStyle = "rgb(0,0,0)";
c.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
for(i = 0; i < numPoints; i++) {
point3d = points[i];
z3d = point3d[2];
z3d -= 4;
if(z3d < -fov) z3d += 400;
point3d[2] = z3d;
draw3Din2D(point3d);
}
}
initPoints();
var loop = setInterval(function () {
render();
}, 50);
}
</script>
</head>
<body onload="setup();">
<canvas id="Canvas2D" width="1920" height="1080">NOT USING HTML5 SUPPORT</canvas>
<div id="content">
<z-index: 0></z-index:>
</div>
</body>
</html>

Live Demo
Full screen demo
Below are the modifications I made to make it work. First remove the size in your canvas element. Change it to
<canvas id="Canvas2D"></canvas>
Next here is what I use for my CSS when Im doing anything full screen with canvas.
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
#Canvas2D {
position:absolute;
top:0;
left:0;
}
And here is the JS required to make it all work
// set the width and height to the full windows size
var SCREEN_WIDTH = window.innerWidth;
// Change to scroll height to make it the size of the document
var SCREEN_HEIGHT = document.documentElement.scrollHeight;
// Make sure to set the canvas to the screen height and width.
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
// everytime we resize change the height and width to the window size, and reset the
// center point
window.onresize = function () {
SCREEN_HEIGHT = canvas.height = document.documentElement.scrollHeight;
SCREEN_WIDTH = canvas.width = document.body.offsetWidth;
HALF_WIDTH = SCREEN_WIDTH / 2;
HALF_HEIGHT = SCREEN_HEIGHT / 2;
};

Well, first of all, thanks a lot to #Loktar for your inner support.
Now i had been working on the code that i will put in my own Official Website (relaunching it).
After the help of #Loktar, the problem was that the vertically autoadjust was not working, so i changed this :
var SCREEN_HEIGHT = document.documentElement.scrollHeight;
To this :
var SCREEN_HEIGHT = window.innerHeight;
And this :
SCREEN_HEIGHT = canvas.height = document.documentElement.scrollHeight;
Changed To this :
SCREEN_HEIGHT = canvas.height = document.body.offsetHeight;
Now it centers good vertically too.
The second problem was that when you doesn´t give to canvas command an exactly number of size it doesn´t show scrollbars, so i fund an style code that after i adadpt to this fx, the way now you can now have scrollbars horizontally and vertically. What you need to do is to add this to the style of your website :
div.scroll
{
width:100%;
height:100%;
overflow:scroll;
}
For after call it in the div of the content with a class, as you can see below :
<div id="content" class="scroll">
Now you will have scrollbars activated when needed. It was tested at Internet Explorer and Firefox and works. I hope it will help to apply to several other canvas codes.
Finally, here i left how the final code looks, and partially how it will look at my Official Website :
<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<title>FX TEST</title>
<STYLE type="text/css">
html, body {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
#Canvas2D {
position:absolute;
top:0;
left:0;
}
#content {
z-index: 10;
position: relative;
}
div.scroll
{
width:100%;
height:100%;
overflow:scroll;
}
</STYLE>
<script language="JavaScript">
function setup() {
var fov = 150;
var SCREEN_WIDTH = window.innerWidth;
var SCREEN_HEIGHT = window.innerHeight;
var HALF_WIDTH = SCREEN_WIDTH / 2;
var HALF_HEIGHT = SCREEN_HEIGHT / 2;
var numPoints = 300;
function draw3Din2D(point3d) {
x3d = point3d[0];
y3d = point3d[1];
z3d = point3d[2];
var scale = fov / (fov + z3d);
var x2d = (x3d * scale) + HALF_WIDTH;
var y2d = (y3d * scale) + HALF_HEIGHT;
c.lineWidth = scale;
c.strokeStyle = "rgb(255,255,255)";
c.beginPath();
c.moveTo(x2d, y2d);
c.lineTo(x2d + scale, y2d);
c.stroke();
}
var canvas = document.getElementById('Canvas2D');
var c = canvas.getContext('2d');
canvas.width = SCREEN_WIDTH;
canvas.height = SCREEN_HEIGHT;
var points = [];
function initPoints() {
for (i = 0; i < numPoints; i++) {
point = [(Math.random() * 400) - 200, (Math.random() * 400) - 200, (Math.random() * 400) - 200];
points.push(point);
}
}
function render() {
c.fillStyle = "rgb(0,0,0)";
c.fillRect(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
for (i = 0; i < numPoints; i++) {
point3d = points[i];
z3d = point3d[2];
z3d -= 4;
if (z3d < -fov) z3d += 400;
point3d[2] = z3d;
draw3Din2D(point3d);
}
}
initPoints();
var loop = setInterval(function () {
render();
}, 50);
window.onresize = function () {
SCREEN_HEIGHT = canvas.height = document.body.offsetHeight;
SCREEN_WIDTH = canvas.width = document.body.offsetWidth;
HALF_WIDTH = SCREEN_WIDTH / 2;
HALF_HEIGHT = SCREEN_HEIGHT / 2;
};
}
setup();
</script>
</head>
<body onload="setup();">
<canvas id="Canvas2D"></canvas>
<div id="content" class="scroll">
<z-index: 0>
</z-index:>
</div>
</body>
</html>

set the width and height of the canvas to 100%.

Related

Background size is not scaling with viewport size

I have an issue with background size. Basically if you will change the viewport size of this page https://attiliosantomo.com/sfera the background is not following the viewport dimension, but it conserve previous viewport dimension and only if I refresh the page background will update to viewport size. Can someone help me? How would like my background follow viewport size by scaling his dimension.
<!doctype html>
<html>
<head>
<style>
#font-face{
font-family: Roslindale;
src: url("pvcweb-banner-TRIAL.woff") format('woff');
font-weight: bold;
}
.workspace {
height: 100vh;
width: 100vw;
top: 0;
left: 0;
display: grid;
place-items: center;
font: 700 12px system-ui;
}
body, html {
height: 100vh;
width: 100vw;
background-size: cover;
}
body{
overflow: hidden;
cursor: url(images/cursor.png),auto;
}
canvas {
width:100%; height:100%;
background-size: cover;
}
.header-overlay {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgb(0, 0, 0);
opacity: 0.1;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/r122/three.min.js"></script>
<script src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/16327/gsap-latest-beta.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
</head>
<body>
<div class='header-overla' style="position: fixed; height: 100vh;">
<script>
var mousePos = {x:.5,y:.5, z:.5};
document.addEventListener('mousemove', function (event) { mousePos = {x:event.clientX/window.innerWidth, y:event.clientY/window.innerHeight, z:event.clientZ/window.innerWidth};});
var phase = 0;
var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(95, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 30;
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
var boxSize = 0.2;
var geometry = new THREE.BoxGeometry(boxSize, boxSize, boxSize);
var materialGreen = new THREE.MeshBasicMaterial({transparent: true, color: 0xffffff, opacity: 0.4, side: THREE.DoubleSide});
var pitchSegments = 60;
var elevationSegments = pitchSegments/2;
var particles = pitchSegments*elevationSegments
var side = Math.pow(particles, 1/3);
var radius = 30;
var parentContainer = new THREE.Object3D();
scene.add(parentContainer);
function posInBox(place) {
return ((place/side) - 0.5) * radius * 1.2;
}
//Plant the seeds, grow some trees in a grid!
for (var p = 0; p < pitchSegments; p++) {
var pitch = Math.PI * 2 * p / pitchSegments ;
for (var e = 0; e < elevationSegments; e++) {
var elevation = Math.PI * ((e / elevationSegments)-0.5)
var particle = new THREE.Mesh(geometry, materialGreen);
parentContainer.add(particle);
var dest = new THREE.Vector3();
dest.z = (Math.sin(pitch) * Math.cos(elevation)) * radius; //z pos in sphere
dest.x = (Math.cos(pitch) * Math.cos(elevation)) * radius; //x pos in sphere
dest.y = Math.sin(elevation) * radius; //y pos in sphere
particle.position.x = posInBox(parentContainer.children.length % side);
particle.position.y = posInBox(Math.floor(parentContainer.children.length/side) % side);
particle.position.z = posInBox(Math.floor(parentContainer.children.length/Math.pow(side,2)) % side);
console.log(side, parentContainer.children.length, particle.position.x, particle.position.y, particle.position.z)
particle.userData = {dests: [dest,particle.position.clone()], speed: new THREE.Vector3() };
}
}
function render() {
phase += 0.002;
for (var i = 0, l = parentContainer.children.length; i < l; i++) {
var particle = parentContainer.children[i];
var dest = particle.userData.dests[Math.floor(phase)%particle.userData.dests.length].clone();
var diff = dest.sub(particle.position);
particle.userData.speed.divideScalar(1.02); // Some drag on the speed
particle.userData.speed.add(diff.divideScalar(8000));// Modify speed by a fraction of the distance to the dest
particle.position.add(particle.userData.speed);
particle.lookAt(dest);
}
parentContainer.rotation.y = phase*3;
parentContainer.rotation.x = (mousePos.y-0.5) * Math.PI;
parentContainer.rotation.z = (mousePos.x-0.5) * Math.PI;
renderer.render(scene, camera);
requestAnimationFrame(render);
}
render();
</script>
</body>
</html>
Thank you so much
Your are using <canva> element with css (widht & height) inline, for your custom css you should use !important with size values
For <canva> element use object-fit instead of background-size
like this:
canvas {
width: 100% !important;
height: 100% !important;
object-fit: cover;
}
Sorry about my English, i dont know if i wrote correct
When you say "background" are you talking about the three.js scene?
If so, you need to add a resize event listener to resize the canvas/scene and update the camera.
window.addEventListener('resize', onWindowResize, false);
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}
You probaby also want to remove the default padding from the body with margin: '0px'

Dropped frame even on the simpliest examples

I'm creating a canvas game and using Chrome profiler to find rendering and performance issues. But it shows lots of red block "Dropped Frame".
let canvas = document.querySelector('canvas')
let c = canvas.getContext('2d')
let dpr = window.devicePixelRatio || 1
let {width, height} = canvas.getBoundingClientRect()
canvas.width = width * dpr
canvas.height = height * dpr
c.scale(dpr, dpr)
let x = 100
let y = 100
document.body.addEventListener('mousemove', (event) => {
x = event.clientX
y = event.clientY
})
function render() {
c.fillStyle = '#9be2fe'
c.fillRect(0, 0, width, height)
c.fillStyle = '#e23521'
c.beginPath()
c.arc(x, y, 40, 0, 2 * Math.PI)
c.fill()
}
function main() {
requestAnimationFrame(main)
render()
}
main()
* {
margin: 0;
padding: 0;
}
body {
height: 100vh;
}
canvas {
width: 100%;
height: 100%;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>DEMO</title>
</head>
<body>
<canvas></canvas>
</body>
</html>
Even for most basic examples! What is wrong? And why are frames not the same size?

Scale full screen canvas to fit content as window changes size

Basically, I have a canvas that draws a grid. When the window changes sizes, it refreshes the grid and scene to fill the entire screen with a grid.
When I resize my browser window to a smaller size, I would like the grid and everything inside the canvas to shrink with it, while keeping the grid boxes a square shape. Websites like Agar.io use this with their canvas.
var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function createMap() {
var gridOptions = {
majorLines: {
separation: 30,
color: '#e8e8e8'
}
};
drawGridLines(canvas, gridOptions.majorLines);
return;
}
function drawGridLines(canvas, lineOptions) {
var iWidth = canvas.width;
var iHeight = canvas.height;
ctx.strokeStyle = lineOptions.color;
ctx.strokeWidth = 1;
ctx.beginPath();
var iCount = null;
var i = null;
var x = null;
var y = null;
iCount = Math.floor(iWidth / lineOptions.separation);
for (i = 1; i <= iCount; i++) {
x = (i * lineOptions.separation);
ctx.moveTo(x, 0);
ctx.lineTo(x, iHeight);
ctx.stroke();
}
iCount = Math.floor(iHeight / lineOptions.separation);
for (i = 1; i <= iCount; i++) {
y = (i * lineOptions.separation);
ctx.moveTo(0, y);
ctx.lineTo(iWidth, y);
ctx.stroke();
}
ctx.closePath();
return;
}
function refresh() {
resize();
createMap();
}
window.onresize = function() {
refresh();
}
refresh();
body,
html {
align-content: center;
overflow: hidden;
border: 0;
margin: 0;
padding: 0;
}
#mainCanvas {
top: 0;
left: 0;
position: absolute;
overflow: hidden;
border: 0;
margin: 0;
padding: 0;
}
<canvas id="mainCanvas"></canvas>
In other words, the view of the canvas is like a bird's eye, and if there are 10 grid boxes from the center to the left side of the screen. When the window is enlarged completely, the screen would keep that same number or grid boxes from the center to the left side as it would when the browser window is resized to a smaller state. (Of course, depending on the screen ratio, it could be 10 grid boxes more or less, but roughly around there)
I tried setting the canvas size with CSS to 100% on the width and height, but that caused the grid squares to become blurry rectangles.
What can I add to cause the elements in the canvas to shrink and grow with the windows size?
Here is a sample where the elements in the canvas shrink and grow with the windows size:
<style>body{margin:0}</style>
<canvas id="mainCanvas"></canvas>
<script>
var canvas = document.getElementById("mainCanvas");
var ctx = canvas.getContext("2d");
function resize() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
var gridOptions = {
majorLines: {
separation: 20,
color: '#e8e8e8'
}
};
drawGridLines(canvas, gridOptions.majorLines);
}
function drawGridLines(canvas, lineOptions) {
ctx.strokeStyle = lineOptions.color;
ctx.strokeWidth = 1;
ctx.beginPath();
var size = Math.floor(canvas.width / lineOptions.separation);
for (var i = 1; i <= lineOptions.separation; i++) {
var x = (i * size);
ctx.moveTo(x, 0);
ctx.lineTo(x, canvas.height);
ctx.stroke();
}
for (var i = 1; i <= Math.floor(canvas.height / size); i++) {
var y = (i * size);
ctx.moveTo(0, y);
ctx.lineTo(canvas.width, y);
ctx.stroke();
}
ctx.closePath();
}
window.onresize = function() { resize(); }
resize();
</script>
Here is a live sample:
https://raw.githack.com/heldersepu/hs-scripts/master/HTML/canvasResize2.html

HTML5 context.drawImage() crop is not working after calling context.translate()

> What I want here are 10 canvases, 5 on the top and 5 on the bottom, each with width 17% and height 25.5%, and appropriate spacing between (see bottom image). Each image drawn on a canvas corresponds to the same area of the full image (see top image). This is kind of like a destination-in, but this is really just a crop of the full image onto smaller canvases using context.translate and context.drawImage(). Please see the two lines inside the innermost for loop with comments that deal wtih context.translate and context.drawImage for clue as to what might be going on.
Please see the attached image of what I am trying to achieve with html5 context.translate() and context.drawImage().
Any help greatly appreciated. Thank you.
//get parent's width and height
var parent = document.getElementById("parent");
var parentWidth = parent.offsetWidth;
var parentHeight = parent.offsetHeight;
//get below canvas
var belowCanvas = document.getElementById('belowCanvas');
var belowCtx = belowCanvas.getContext('2d');
//create temporary canvas
var tmpCanvas = document.createElement('canvas');
var tmpCtx = tmpCanvas.getContext('2d');
//initialize width and height of temporary canvas and below canvas to equal parent
tmpCanvas.width = belowCanvas.width = parentWidth;
tmpCanvas.height = belowCanvas.height = parentHeight;
//draw below canvas in black for visual aid of how things are cropped in above canvases
belowCtx.rect(0,0,parentWidth,parentHeight);
belowCtx.fillStyle = 'black';
belowCtx.fill();
//draw temporary canvas
var centerX = parentWidth/4;
var centerY = parentHeight/4;
var radius = parentHeight/4;
tmpCtx.rect(0,0,parentWidth,parentHeight);
tmpCtx.fillStyle = 'blue';
tmpCtx.fill();
tmpCtx.beginPath();
tmpCtx.arc(centerX, centerY, radius*1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'green';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(parentWidth - centerX, centerY, radius*1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'purple';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(parentWidth/2, parentHeight/2, radius*2, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'white';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(centerX, parentHeight - centerY, radius*1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'red';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(parentWidth - centerX, parentHeight - centerY, radius*1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'yellow';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
//set spacing between canvases
var horizontalSpacing = parentWidth*0.025
var verticalSpacing = parentWidth*0.03
//initialize canvases width and height
var widthCanvas = parentWidth*0.17;
var heightCanvas = parentWidth*0.255;
var xStart;
var yStart = verticalSpacing;
for(var i=0; i< 2; i++)
{
xStart = horizontalSpacing;
for(var j=0; j < 5; j++)
{
//get specific destinationInCanvas by id and its respective context
var canvas = document.getElementById("canvas" + ((i*5)+j));
var ctx = canvas.getContext('2d');
canvas.width = widthCanvas;
canvas.height = heightCanvas;
/***!!!
Problem next two lines
if the next line is commented out, each canvas is drawn, but of course not translated; so you only see last canvas, canvas9
if the next line is NOT commented out, only canvas0 is drawn and translated, the rest of the canvases 1-9 are not drawn*/
ctx.translate(xStart, yStart);//comment out this line to see effect
ctx.drawImage(tmpCanvas, xStart, yStart, widthCanvas, heightCanvas, 0, 0, widthCanvas, heightCanvas);
xStart += (horizontalSpacing + widthCanvas);
}
yStart += (verticalSpacing + heightCanvas);
}
#parent {
width: 1000px;
height: 600px;
}
#belowCanvas{
position: absolute;
z-index:-1;
}
#canvas0 {
position: absolute;
z-index:0;
}
#canvas1 {
position: absolute;
z-index:1;
}
#canvas2 {
position: absolute;
z-index:2;
}
#canvas3 {
position: absolute;
z-index:3;
}
#canvas4 {
position: absolute;
z-index:4;
}
#canvas5 {
position: absolute;
z-index:5;
}
#canvas6 {
position: absolute;
z-index:6;
}
#canvas7 {
position: absolute;
z-index:7;
}
#canvas8 {
position: absolute;
z-index:8;
}
#canvas9 {
position: absolute;
z-index:9;
}
<!DOCTYPE HTML>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style-test.css">
</head>
<body>
<div id="parent">
<canvas id="belowCanvas"></canvas>
<canvas id="canvas0"></canvas>
<canvas id="canvas1"></canvas>
<canvas id="canvas2"></canvas>
<canvas id="canvas3"></canvas>
<canvas id="canvas4"></canvas>
<canvas id="canvas5"></canvas>
<canvas id="canvas6"></canvas>
<canvas id="canvas7"></canvas>
<canvas id="canvas8"></canvas>
<canvas id="canvas9"></canvas>
</div>
<script type="text/javascript" src="script-test.js"></script>
</body>
</html>
You've got some problem while incrementing yStart and xStart:
You should do so by multiplying heightCanvas/widthCanvas by i/j state of your loop.
Also, in your CSS, if you do add position:absolute without setting marginsor left/top values, your canvases will get in stack and you'll only be able to see last one. Only add position:absolute to your #belowCanvas. Actually, if you only need a black background, you might consider wrapping all your canvases into a div with background:black;. It would be easier to align your elements then.
Finally, you won't need ctx.translate since ctx.drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight); already does the translation on source image (sx, sy).
Edit after I talked to OP on chat:
Actually, he wanted the canvases' holes to fit to a layout, created with a context.globalCompositeOperation='destination-out';.
I did remove the belowCanvas and replaced it with a divwhich background is set to black via CSS.
To prevent ghost margins with your small canvases, you'll need to set vertical-align:bottom; float: left since browsers display canvas element as a character.
I refactored the code to create the small canvases programmatically, this will allow you to change the grid format.
For the example, I added click listener to show/hide layers:
left click triggers destinationOutLayer and right click triggers small canvases layer.
//get parent's width and height
var parent = document.getElementById("parent");
var parentWidth = parent.offsetWidth;
var parentHeight = parent.offsetHeight;
var destinationOutCanvas = document.getElementById('destinationOutCanvas');
var destinationOutCtx = destinationOutCanvas.getContext('2d');
//create temporary canvas
var tmpCanvas = document.createElement('canvas');
var tmpCtx = tmpCanvas.getContext('2d');
//initialize width and height of temporary canvas and destOut canvas to equal parent
destinationOutCanvas.width = tmpCanvas.width = parentWidth;
destinationOutCanvas.height = tmpCanvas.height = parentHeight;
//draw temporary canvas
var centerX = parentWidth / 4;
var centerY = parentHeight / 4;
var radius = parentHeight / 4;
tmpCtx.rect(0, 0, parentWidth, parentHeight);
tmpCtx.fillStyle = 'blue';
tmpCtx.fill();
tmpCtx.beginPath();
tmpCtx.arc(centerX, centerY, radius * 1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'green';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(parentWidth - centerX, centerY, radius * 1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'purple';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(parentWidth / 2, parentHeight / 2, radius * 2, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'white';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(centerX, parentHeight - centerY, radius * 1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'red';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
tmpCtx.beginPath();
tmpCtx.arc(parentWidth - centerX, parentHeight - centerY, radius * 1.5, 0, 2 * Math.PI, false);
tmpCtx.fillStyle = 'yellow';
tmpCtx.fill();
tmpCtx.lineWidth = 2
tmpCtx.strokeStyle = '#003300';
tmpCtx.stroke();
//set the grid
//Strange bugs can occur with some fractions (e.g 18 rows);
var rows = 5;
var lines = 2;
//set spacing between canvases
//rounded to the nearest even number, since we divide this by 2 below
var horizontalSpacing = 2*Math.round((parentWidth*0.025)/2); // or whatever you want
var verticalSpacing = 2*Math.round((parentHeight*0.03)/2); // or whatever you want
//initialize canvases width and height
var widthCanvas = 2*(Math.round(parentWidth / rows)/2);
var heightCanvas = 2*(Math.round(parentHeight / lines)/2);
destinationOutCtx.drawImage(tmpCanvas, 0, 0);
destinationOutCtx.globalCompositeOperation = 'destination-out';
destinationOutCtx.fillStyle = 'orange';
for (var i = 0; i < lines; i++) {
for (var j = 0; j < rows; j++) {
//get specific destinationInCanvas by id and its respective context
//var canvas = document.getElementById("canvas" + ((i * rows) + j));
//create the canvases on the go
var canvas= document.createElement('canvas');
canvas.width = widthCanvas;
canvas.height = heightCanvas;
var ctx = canvas.getContext('2d');
//only needed for the demonstration toggler
canvas.className = "small";
//set the transform variables
var hS = horizontalSpacing/2,
vS = verticalSpacing/2,
xStart = (widthCanvas*j)+hS,
yStart = (heightCanvas*i)+vS,
cropedWidth = widthCanvas-hS*2,
cropedHeight = heightCanvas-hS*2;
ctx.drawImage(tmpCanvas, xStart, yStart, cropedWidth, cropedHeight, hS, vS, cropedWidth, cropedHeight);
destinationOutCtx.fillRect(xStart, yStart, cropedWidth, cropedHeight);
parent.appendChild(canvas);
}
}
//Toggle opacity with right and left click
destinationOutCanvas.addEventListener('click', function () {
if (this.style.opacity == 0) {
this.style.opacity = 1
} else {
this.style.opacity = 0
}
});
destinationOutCanvas.style.opacity = 1;
destinationOutCanvas.addEventListener('contextmenu', function (e) {
console.log('triggered');
e.preventDefault();
var smalls = document.querySelectorAll('.small');
console.log(smalls[0].style.opacity);
if (smalls[0].style.opacity == 0) {
for (i = 0; i < smalls.length; i++) {
smalls[i].style.opacity = 1
}
} else {
for (i = 0; i < smalls.length; i++) {
smalls[i].style.opacity = 0;
};
}
});
#parent {
width: 1000px !important;
height: 600px;
background:#000;
}
html, body {
margin:0
}
canvas {
vertical-align:bottom;
float: left
}
.destinationOutLayer, #tmp {
position: absolute;
z-index: 2;
top:0;
}
<div id="parent">
</div>
<canvas id="destinationOutCanvas" class="destinationOutLayer"></canvas>

Canvas Fill Page Width and Height

http://jsbin.com/oMUtePo/1/edit
I've been having a pain trying to get canvas to fill the whole page.
I tried using...
canvas.width = document.body.clientWidth;
canvas.height = document.body.clientHeight;
It filled the width, but not the height, and the drawing board was drawing 1px lines, which is not what I want.
When using 100% for width and height in CSS the width is scaled, and the height is cut, when drawing it looks as if a raster image was scaled significantly larger in ms paint and there's a large offset on onmousedown drawing which is obviously not what I want.
Any help would be greatly appreciated.
Full Code:
<!DOCTYPE html>
<head>
<meta charset="utf-8" />
<title>HTML5 Canvas Drawing Board</title>
<style>
* {
margin: 0;
padding: 0;
}
body, html {
height: 100%;
}
#myCanvas {
cursor: crosshair;
position: absolute;
width: 100%;
height: 100%;
}
</style>
<script type="text/JavaScript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js?ver=1.4.2"></script>
<script type="text/javascript">
window.onload = function() {
var myCanvas = document.getElementById("myCanvas");
var curColor = $('#selectColor option:selected').val();
var ctx = myCanvas.getContext("2d");
ctx.fillStyle="#000";
ctx.fillRect(0,0,500,500);
if(myCanvas){
var isDown = false;
var canvasX, canvasY;
ctx.lineWidth = 5;
$(myCanvas)
.mousedown(function(e){
isDown = true;
ctx.beginPath();
canvasX = e.pageX - myCanvas.offsetLeft;
canvasY = e.pageY - myCanvas.offsetTop;
ctx.moveTo(canvasX, canvasY);
})
.mousemove(function(e){
if(isDown !== false) {
canvasX = e.pageX - myCanvas.offsetLeft;
canvasY = e.pageY - myCanvas.offsetTop;
ctx.lineTo(canvasX, canvasY);
ctx.strokeStyle = "white";
ctx.stroke();
}
})
.mouseup(function(e){
isDown = false;
ctx.closePath();
});
}
};
</script>
</head>
<body>
<canvas id="myCanvas">
Sorry, your browser does not support HTML5 canvas technology.
</canvas>
</body>
</html>
You have to set the absolute size in pixels on the canvas element and not with CSS as you do in the demo, so first remove the following lines from the CSS rule:
#myCanvas {
cursor: crosshair;
position: absolute;
/*width: 100%; Remove these */
/*height: 100%;*/
}
Then add this to your code - you need to use clientWidth/Height of the window object.
myCanvas.width = window.innerWidth;
myCanvas.height = window.innerHeight;
var ctx = myCanvas.getContext("2d");
ctx.fillStyle="#000";
ctx.fillRect(0,0, myCanvas.width, myCanvas.height);
Your modified JSBIN.

Categories

Resources