How to make the matrix background render behind page content? - javascript

I wanted to use this cool matrix background for my web application but it covers all of my elements(div's, headers, paragraphs etc.).
I've tried to fix this with css but it doesn't work.
So now I'm stuck and asking you for help.
Here is my code from CodePen:
const canvas = document.getElementById('canv');
const ctx = canvas.getContext('2d');
const w = canvas.width = document.body.offsetWidth;
const h = canvas.height = document.body.offsetHeight;
const cols = Math.floor(w / 20) + 1;
const ypos = Array(cols).fill(0);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, w, h);
function matrix () {
ctx.fillStyle = '#0001';
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = '#0f0';
ctx.font = '15pt monospace';
ypos.forEach((y, ind) => {
const text = String.fromCharCode(Math.random() * 128);
const x = ind * 20;
ctx.fillText(text, x, y);
if (y > 100 + Math.random() * 10000) ypos[ind] = 0;
else ypos[ind] = y + 20;
});
}
setInterval(matrix, 50);
body {
margin: 0;
height: 100vh;
width: 100vw;
}
.container{
background-color: white;
}
<canvas id='canv'>
<div class='container'>
<p>Some div with login in</p>
</div>
</canvas>
Is there someway to fix it?
Thanks for your attention and help.

Here's a possible solution:
const canvas = document.getElementById('canv');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
const ctx = canvas.getContext('2d');
let cols = Math.floor(window.innerWidth / 20) + 1;
let ypos = Array(cols).fill(0);
ctx.fillStyle = '#000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
function matrix () {
const w = window.innerWidth;
const h = window.innerHeight;
if (canvas.width !== w) {
canvas.width = w;
cols = Math.floor(window.innerWidth / 20) + 1;
ypos = Array(cols).fill(0);
}
if (canvas.height !== h) {
canvas.height = h;
}
ctx.fillStyle = '#0001';
ctx.fillRect(0, 0, w, h);
ctx.fillStyle = '#0f0';
ctx.font = '15pt monospace';
ypos.forEach((y, ind) => {
const text = String.fromCharCode(Math.random() * 128);
const x = ind * 20;
ctx.fillText(text, x, y);
if (y > 100 + Math.random() * 10000) ypos[ind] = 0;
else ypos[ind] = y + 20;
});
}
setInterval(matrix, 50);
body {
margin: 0;
background-color: #000;
}
.container {
background-color: rgba(255, 255, 255, 0.85);
margin: 50px 10%;
padding: 3rem;
position: relative;
z-index: 1;
}
#canv {
position: fixed;
top: 0;
left: 0;
}
<canvas id='canv'></canvas>
<div class='container'>
<p>Some div with login in</p>
</div>
Play around with the CSS of .container to make it look like you want. Don't remove the position and z-index (they are needed to keep it on top of the <canvas>).
Note: The CSS required to place .container on top is rather simple and it's not the reason I added the answer for.
The reason is because your matrix script was not responsive. I made minor mods to it and it now resizes when viewport size changes.
Welcome to SO.

Related

Scrolling issue with Canvas style.left/top

I am making a magnifying glass for a canvas application but ive run into an issue with scrolling.
Essentially the goal is to take a canvas and when an image is added (in this case a cgm image) and make a snapshot of it, scale it up and draw it on to a second smaller canvas that overlays it and follow the mouse (preferably a drag/mousedown and up, but i am using mousemove for testing purposes). I believe the issue is in the zoom.style.top & zoom.style.left NOTE on my main aplication I have a top margin of 70px so keep that in mind.
here is a quick example I wrote up
<!-- language: lang-js -->
var canvas = document.getElementById("canvas1");
var ctx = canvas.getContext("2d");
var ox = canvas.width / 2;
var oy = canvas.height / 2;
ctx.font = "42px serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillStyle = "blue";
ctx.fillRect(ox / 2, oy / 2, ox, oy);
function magnify() {
var main = document.getElementById("canvas1");
var ctx = main.getContext('2d')
var base64 = main.toDataURL('image/png', 0);
drawing = new Image();
drawing.onload = () => {
var zoom = document.getElementById("tCanvas");
var zoomCtx = zoom.getContext('2d');
zoomCtx.drawImage(drawing, 0, 0);
}
main.addEventListener("mousemove", function(e) {
var zoom = document.getElementById("tCanvas");
var zoomCtx = zoom.getContext('2d');
zoomCtx.clearRect(0, 0, zoom.width, zoom.height);
zoomCtx.drawImage(main, e.x, e.y, 200, 200, 0, 0, 300, 300);
zoom.style.top = e.pageY - 70 + "px"
zoom.style.left = e.pageX - 10 + "px"
e.pageY = -150
e.pageX = -150
zoom.style.display = "block";
});
main.addEventListener("mouseleave", function() {
var zoom = document.getElementById("tCanvas");
zoom.style.display = "none";
});
drawing.src = base64;
};
<canvas id="tCanvas" class="cgm" height="100" width="100" style="background-color:white; position: absolute; display: none; z-
index:1;border:1px solid red;"> </canvas>
<canvas tabindex=1 class="cgm" id="canvas1" style="position:relative; background:white;
left:0;right:0;margin:auto;z-index:1;margin-top:70px; "></canvas>
<p></p>
<button id="zoom" onclick="magnify();">Zoom</button>
Here's a fiddle for reference (I fixed the height to display the scroll issue).
JSFiddle
I simplified a lot of the code on your JSFiddle.
See if this is the behavior you are looking for:
const canvas = document.getElementById("canvas1");
const ctx = canvas.getContext("2d");
const zoom = document.getElementById("tCanvas");
const zoomCtx = zoom.getContext('2d');
for (let i = 10; i < 20; i++)
for (let j = -60; j < 800; j += 60)
ctx.fillText(j + i, i * 20 - 180, i * 9 + j);
function getMousePos(evt) {
var rect = canvas.getBoundingClientRect()
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
}
}
canvas.addEventListener("mousemove", function(e) {
zoomCtx.clearRect(0, 0, zoom.width, zoom.height);
let pos = getMousePos(e)
zoomCtx.drawImage(canvas, pos.x, pos.y, 200, 200, 0, 0, 300, 300);
zoom.style.top = e.pageY - 10 + "px"
zoom.style.left = e.pageX - 10 + "px"
zoom.style.display = "block";
});
canvas.addEventListener("mouseleave", function() {
zoom.style.display = "none";
});
#tCanvas {
border: 1px solid red;
display: none;
position: absolute;
background-color: #808080;
pointer-events: none;
}
#canvas1 {
background-color: #808080;
}
<canvas id="tCanvas" width=100 height=100></canvas>
<canvas id="canvas1" width=240 height=800></canvas>
I think that your issue was with pointer-events: none; the top canvas was preventing the events from reaching the bottom canvas.
Also you don't have to declare your document.getElementById(".. on every function, those should be global constants
For the issue with a long canvas we need to use canvas.getBoundingClientRect in the calculation to get the real position of the mouse in the canvas

Aligning text inside rectangle of html5 canvas

I have resizable rectangle, and I wish to have right-aligned text (day numbers) next to it.
what I have now:
(also when resizing the text does not really align vertically)
what I wish to have:
Is there a way to fill the text and align it inside a drawn rectangle? Other suggestions are welcome too.
js.do code
function dayRect(day) {
const days = ["I","II","III","IV","V","VI","VII"];
context.beginPath();
//maybe align the text inside this rect somehow
context.rect(0, day*h/7, 3*w/27, h/7);
context.stroke();
context.font = "0.5rem Arial";
context.fillStyle = "#fff";
context.fillText(days[day], 0, (day+1)*h/7);
}
I've changed a few things in your code since I wasn't able to see anything. You need to use context.textAlign="right" for your text and move it to a different position. I hope it helps.
function getMousePos(canvas, evt) {
var rect = canvas.getBoundingClientRect();
return {
x: evt.clientX - rect.left,
y: evt.clientY - rect.top
};
}
var canvas = document.getElementById("posHourCanvas");
var context = canvas.getContext('2d');
canvas.width=600,canvas.height=300;
var boxes = [];
function init() {
context.clearRect(0, 0, canvas.width, canvas.height);
boxes.length = 0;
const strokeWidth = 0.6;
//canvas.width = $('#two')[0].clientWidth;
var cellSize = canvas.width/27;
canvas.height = 7/27 * canvas.width;
var x = y = 0;
draw(x,y,canvas.width,canvas.height,cellSize,strokeWidth);
}
function Box(x, y, day, hour) {
this.x = x;
this.y = y;
this.day = day;
this.hour = hour;
}
function draw(x, y, w, h, cellSize, strokeWidth) {
let onePixel = cellSize * strokeWidth;
cellSize = cellSize * (1 - strokeWidth);
context.beginPath();
context.lineWidth = 1;
context.strokeStyle = 'rgba(0, 0, 0, 1)';
const rectCoordinates = {
x: x+3*w/27,
y: y,
w: w-3*w/27,
h: h
}
context.rect(rectCoordinates.x, y, rectCoordinates.w, h);
context.fillStyle = 'white';
context.fill();
context.stroke();
let offX = rectCoordinates.w/24 + rectCoordinates.x;
let offY = h/7;
for (let i = 0; i < 7; i++) {
dayRect(i);
context.beginPath();
context.moveTo(0, offY);
context.lineTo(w, offY);
context.strokeStyle = "black";
context.stroke();
offY+=h/7;
}
for (let i = 0; i < 24; i++) {
context.beginPath();
context.moveTo(offX, 0);
context.lineTo(offX, h);
context.stroke();
offX+=rectCoordinates.w/24;
}
function dayRect(day) {
const days = ["I","II","III","IV","V","VI","VII"];
context.beginPath();
context.rect(0, day*h/7, 3*w/27, h/7);
context.stroke();
context.font = "0.5rem Arial";
context.fillStyle = "#fff";
context.textAlign="right";
context.fillText(days[day], 60, (day+1)*h/7);
}
}
init();
body {
margin: auto;
color: white;
background-color: black;
min-height: 100vh;
}
<div id="parent">
<div>text above</div>
<div id="two">
<canvas id="posHourCanvas" width="600" height="300"></canvas>
</div>
<div>text under</div>
</div>

How to change the color of the circle on canvas every n seconds?

How could the size of the shadow change, every n seconds? I guess you have to constantly create a new circle and eliminate the previous one? How would this be done? And also, is not there a more optimal way?
function main() {
var canvas = document.getElementsByTagName("CANVAS")[0],
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = document.documentElement.scrollHeight;
var cW = canvas.width,
cH = canvas.height;
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, cW, cH);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#FFF";
ctx.shadowBlur = 5;
ctx.shadowColor = "#FFF";
ctx.arc(cW/2, cH/2, 50, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
}
window.addEventListener("load", main);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>JS Bin</title>
</head>
<body>
<canvas></canvas>
</body>
</html>
Create a setInterval & an array of colors. Use Math.random to randomly select any color.
Modify the main function to accept colors as two parameters.
function main(bckColor, circleColor) {
var canvas = document.getElementsByTagName("CANVAS")[0],
ctx = canvas.getContext("2d");
if (canvas.height) {
canvas.height = 0;
}
canvas.width = window.innerWidth;
canvas.height = document.documentElement.scrollHeight;
var cW = canvas.width,
cH = canvas.height;
ctx.fillStyle = bckColor || "#000";
//ctx.fillStyle = "red" ;
ctx.fillRect(0, 0, cW, cH);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = circleColor || "#FFF";
ctx.shadowBlur = 5;
ctx.shadowColor = "#FFF";
ctx.arc(cW / 2, cH / 2, 50, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
}
var colorArray = ['red', 'green', 'yellow', 'blue', 'pink', 'brown', 'orange']
var changeColor = setInterval(function() {
let bckColor = colorArray[Math.floor(Math.random() * 7 + 1)];
let circleColor = colorArray[Math.floor(Math.random() * 7 + 1)];
main(bckColor, circleColor)
}, 2000)
window.addEventListener("load", main);
<canvas></canvas>
instead of animating the canvas itself with a redraw every x seconds, i would suggest using an overlay , create a circle div, position it over the canvas' circle and animate its shadow using css, you'll have all the controls you want like the shadow's color and distance, animation speed ..etc.
here's a fiddle ( the overlay is better positionned )
function main() {
var canvas = document.getElementsByTagName("CANVAS")[0],
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = document.documentElement.scrollHeight;
var cW = canvas.width,
cH = canvas.height;
ctx.fillStyle = "#000";
ctx.fillRect(0, 0, cW, cH);
ctx.fill();
ctx.beginPath();
ctx.fillStyle = "#FFF";
ctx.shadowBlur = 5;
ctx.shadowColor = "#FFF";
ctx.arc(cW / 2, cH / 2, 50, 0, 2 * Math.PI, false);
ctx.fill();
ctx.closePath();
// position the overlay over the circle
overlay.style.top = (cH / 2 - 99) + 'px'
overlay.style.left = (cW / 2 - 50) + 'px'
}
window.addEventListener("load", main);
main()
const animationDuration = 2;
function getRandomColor() {
var letters = '0123456789ABCDEF';
var color = '#';
for (var i = 0; i < 6; i++) {
color += letters[Math.floor(Math.random() * 16)];
}
return color;
}
overlay.style.animationDuration = animationDuration + 's';
setInterval(function() {
overlay.style.color = getRandomColor()
}, animationDuration * 1000)
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
canvas {
width: 100vw;
height: 100vh;
display: block;
}
#overlay {
border-radius: 50%;
background: none;
animation: shadow linear infinite;
margin: auto;
transform: translate(0, 50%);
color: green;
position: absolute;
z-index: 99;
width: 100px;
height: 93px;
}
#keyframes shadow {
0% 100% {
box-shadow: 0 0 0
}
50% {
box-shadow: 0 0 50px 20px
}
}
<canvas></canvas>
<div id="overlay">
</div>

Image not appearing in canvas - sometimes

This works great on all of my tests, but on the live system, I have a problem.
There are three separate but identical canvases. They are all initially painted with 640x480 jpg images. The third is then updated every second with a new 640x480 jpg image.
For some reason, the original static image for the third canvas - and that canvas only - doesn't load from the live server, only on the tests.
Here's the html:
<div style="padding: 1vw;">
<a href="/virtualscribe" class="camLink">
<div class="camDiv">
<div class="camBox" id="picBoxLeft">
<canvas id="canvasLeft" class="camBorder"></canvas>
</div>
</div>
</a>
<a href="/videos" class="camLink">
<div class="camDiv">
<div class="camBox" id="picBoxCenter">
<canvas id="canvasCenter" class="camBorder"></canvas>
</div>
</div>
</a>
<div class="camDiv">
<div class="camBox" id="picBoxRight">
<canvas id="canvasRight" class="camBorder"></canvas>
</div>
</div>
</div>
Here's the CSS:
<style>
.camBox {
max-width: 28vw;
width: 28vw;
height: 21vw;
max-height: 21vw;
display: inline-block;
}
.camDiv {
padding: 1.5vw;
display: inline-block;
}
.camBorder {
border: 0.6vw solid #fe890f;
border-top-left-radius: 3.3vw;
border-bottom-right-radius: 3.3vw;
}
.camLink {
color: transparent;
}
</style>
And here's the JavaScript:
var refreshTimer;
var imgLiveCam;
function drawPictureBox(img, canvas, text) {
var context = canvas.getContext("2d");
context.drawImage(img, 0, 0, canvas.width, canvas.height);
context.globalAlpha = 0.6;
context.fillStyle = "rgb(244,121,32)";
context.fillRect(0, canvas.height * 0.67, canvas.width, canvas.height * 0.33);
context.globalAlpha = 1;
var maxWidth = canvas.width;
var x = canvas.width / 2;
var y = canvas.height * 0.85;
context.font = canvas.width / 12 + 'px Oswald';
context.strokeStyle = 'black';
context.lineWidth = 2;
context.textAlign = "center";
context.strokeText(text, x, y, maxWidth);
context.fillStyle = 'white';
context.fillText(text, x, y, maxWidth);
};
function drawCamBox(img, logo, canvas) {
var context = canvas.getContext("2d");
context.drawImage(img, 0, 0, canvas.width, canvas.height);
context.globalAlpha = 0.6;
context.fillStyle = "rgb(244,121,32)";
context.fillRect(0, canvas.height * 0.67, canvas.width, canvas.height * 0.33);
var eSize = canvas.height / 10;
context.globalAlpha = 1;
context.drawImage(logo, 2, canvas.height * 0.67 - eSize, eSize, eSize);
var now = new Date();
var text = now.toLocaleDateString() + " " + now.toLocaleTimeString();
var maxWidth = canvas.width * 0.33;
var x = canvas.width - 10 - maxWidth;
var y = canvas.height * 0.67 - 10;
context.font = maxWidth / 10 + "px Arial";
context.strokeStyle = 'black';
context.lineWidth = 2;
context.strokeText(text, x, y, maxWidth);
context.fillStyle = 'white';
context.fillText(text, x, y, maxWidth);
text = 'View Our Production Floor';
context.textAlign = "center";
maxWidth = canvas.width;
x = canvas.width / 2;
y = canvas.height * 0.85;
context.font = canvas.width / 12 + 'px Oswald';
context.strokeText(text, x, y, maxWidth);
context.fillText(text, x, y, maxWidth);
}
function addResizeListener(fn) {
if (window.attachEvent) {
window.attachEvent('onresize', fn)
} else if (window.addEventListener) {
window.addEventListener('resize', fn, true);
};
}
function initCam() {
var imgLeft = new Image();
imgLeft.onload = function () {
var canvas = document.getElementById("canvasLeft");
var picBox = document.getElementById("picBoxLeft");
var drawFn = function () {
canvas.height = picBox.clientHeight;
canvas.width = picBox.clientWidth;
drawPictureBox(imgLeft, canvas, 'Looking for a Scribe?');
};
drawFn();
addResizeListener(drawFn);
}
var imgCenter = new Image();
imgCenter.onload = function () {
var canvas = document.getElementById("canvasCenter");
var picBox = document.getElementById("picBoxCenter");
var drawFn = function () {
canvas.height = picBox.clientHeight;
canvas.width = picBox.clientWidth;
drawPictureBox(imgCenter, canvas, 'Watch In-Depth Videos');
};
drawFn();
addResizeListener(drawFn);
}
imgLiveCam = new Image();
var logo = new Image();
logo.src = "e.png";
imgLiveCam.onload = function () {
var canvas = document.getElementById("canvasRight");
var picBox = document.getElementById("picBoxRight");
var drawFn = function () {
canvas.height = picBox.clientHeight;
canvas.width = picBox.clientWidth;
drawCamBox(imgLiveCam, logo, canvas);
};
drawFn();
imgLiveCam.onload = drawFn;
addResizeListener(drawFn);
}
imgLeft.src = "scribe.jpg";
imgCenter.src = "doc-with-spine.jpg";
imgLiveCam.src = "camloading.jpg";
refreshTimer = setTimeout(refresh, 499);
}
function refresh() {
clearTimeout(refreshTimer);
imgLiveCam.src = "http://cams.edataservices.com/17fcam.jpg?t=" + new Date().getTime();
refreshTimer = setTimeout(refresh, 1009);
}
Any idea why the third canvas starts out blank most of the time?
By adding a longer delay before starting the refresh cycle, the browsers had more time to load the initial, "default" image. I set it at 1500ms, and now it is pretty reliable.
(Thanks for the help...)

I want to create a parallax scrolling website of three pictures but only two scrolls work

i'm trying to create a parallex scrolling effect using javascript and html/css.
the scrolling have to apply to three picture so the 1st and 2nd picture scroll in parallex but i can't get the 2nd and the 3rd to do the same
i'm a novice to javascript and i'm learning through doing
CSS
#img1{
width: 100%;
height: 970px;
position: relative;
z-index: -1;
}
#img2{
width: 100%;
height: 970px;
position: relative;
z-index: 1;
}
#img3{
width: 100%;
height: 970px;
position: relative;
z-index: 1;
}
JS
var ypos,image,image2;
function parallex() {
ypos = pageYOffset;
image = document.getElementById('img1');
image.style.top= ypos* .8 +'px';
}
function parallex2() {
ypos = pageYOffset;
image = document.getElementById('img2');
image.style.zIndex=-1;
image.style.top= ypos* .8 +'px';
}
if(screenY<=970) window.addEventListener('scroll',parallex);
else window.addEventListener('scroll',parallex2);
HTML
<img src="ny.jpg" id="img1" >
<img src="5429c32b425f183f61bf7316_new-york-city-skyline.jpg" id="img2" >
<img src="9OEWK8nMTFmqQwAFpFyn7snIGP8.jpg" id="img3">
Here's a three image parallax in javascript/canvas. You might be able to adapt it to suit your needs.
var img1 = document.getElementById('img1');
var img2 = document.getElementById('img2');
var img3 = document.getElementById('img3');
var can = document.getElementById('can');
var w = can.width = img1.width = img2.width = img3.width = 200;
var h = can.height = img1.height = img2.height = img3.height = 100;
drawImages();
// SPEEDS
var s1 = .05;
var s2 = .25;
var s3 = 2;
// POSITIONS
var x1 = 0;
var x2 = 0;
var x3 = 0;
var ctx = can.getContext('2d');
function ani() {
ctx.fillStyle = "#6699CC";
ctx.fillRect(0, 0, w, h); // DRAW SKY
ctx.drawImage(img3, x1, 0); // SHOW ONLY ONE MOON
// OTHER IMAGES REPEAT
ctx.drawImage(img1, -w + x2, 0);
ctx.drawImage(img1, x2, 0);
ctx.drawImage(img2, x3, 0);
ctx.drawImage(img2, -w + x3, 0);
x1 += s1;
x2 += s2;
x3 += s3;
if (x1 > w) x1 = 0 - w; // SHOW ONLY ONE MOON
if (x2 > w) x2 = 0;
if (x3 > w) x3 = 0;
requestAnimationFrame(ani);
}
ani();
function drawImages() {
var ctx1 = img1.getContext('2d');
ctx1.beginPath();
ctx1.moveTo(0, h);
ctx1.lineTo(20, 20);
ctx1.lineTo(40, h - 10);
ctx1.lineTo(80, 10);
ctx1.lineTo(120, h);
ctx1.lineTo(160, 30);
ctx1.lineTo(200, h);
ctx1.fillStyle = "#996600";
ctx1.fill();
var ctx2 = img2.getContext('2d');
ctx2.fillStyle = "#666666";
ctx2.moveTo(30, h);
ctx2.lineTo(30, 0);
ctx2.lineTo(45, 0);
ctx2.lineTo(45, h);
ctx2.rect(100, 50, 25, 50);
ctx2.rect(w - 20, 0, 20, h);
ctx2.fill();
var ctx3 = img3.getContext('2d');
ctx3.moveTo(50, 50);
ctx3.arc(25, 25, 20, 0, 360 * Math.PI / 2);
ctx3.fillStyle = "#FFFF00";
ctx3.fill();
}
body {
background-color: #ACE;
}
<canvas id="img1"></canvas>
<canvas id="img2"></canvas>
<canvas id="img3"></canvas>
<canvas id="can"></canvas>

Categories

Resources