Place elements to canvas using JavaScript - javascript

I'm making a little game. I will place some div-tags into a canvas-tag by JavaScript. This is my code:
document.addEventListener("DOMContentLoaded", function () {
init();
});
function init(){
draw();
}
function draw(){
var number = Math.round((Math.random() * 31) + 20);
var cnv = document.getElementsByTagName("canvas")[0];
for (i = 0; i <= number ; i++){
var div = document.createElement('div');
//breedte
var length = Math.round((Math.random() * 31) + 20);
div.style.height = length + "px";
div.style.width = length + "px";
//locattie
div.style.top = Math.floor(Math.random() * (cnv.height - 100))+ "px";
div.style.left = Math.floor(Math.random() * (cnv.width - 100))+ "px";
//toevoegen
div.style.backgroundColor = "rgb(" + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ")";
cnv.appendChild(div);
}
}
canvas{
width: 100%;
height: 500px;
background-color: #898989;
}
div {
position: absolute;
}
<canvas id="playarea">
</canvas>
So you can see, it displays only a empty canvas. Only if I implement the element, I can see the generated div-tags. I have also try it replace some properties in the CSS code of my div. But it don't work...
Can anyone help me? Thanks

canvas isn't intended to encapsulate div-s like this. You should try to use native canvas methods like fillRect() for example, see this MDN tutorial
With a quick example:
document.addEventListener("DOMContentLoaded", function () {
init();
});
function init(){
draw();
}
function draw(){
var number = Math.round((Math.random() * 31) + 20);
var cnv = document.getElementsByTagName("canvas")[0];
var ctx = cnv.getContext("2d");
var top = 0;
var left = 0;
var size = 0;
for (i = 0; i <= number ; i++){
ctx.fillStyle = "rgb(" + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ", " + Math.floor(Math.random() * 255) + ")";
top = Math.floor(Math.random() * (cnv.height - 100));
left = Math.floor(Math.random() * (cnv.width - 100));
size = Math.round((Math.random() * 31) + 20);
ctx.fillRect(left, top, size, size);
}
}

Nodes inside a canvas object will only be shown in browsers that doesn't support the canvas element:
<canvas>Your browser <em>doesn't</em> support the canvas element!</canvas>
If you want to add elements on top of your canvas you could consider adding a wrapper and add the elements to it:
<div class="canvas_wrapper">
<canvas></canvas>
<div class="canvas_child">My added element</div>
</div>
And some css like this:
.canvas_wrapper { position: relative; }
.canvas_child { position: absolute; top: 100px; left: 100px; }

Related

Different scroll speeds for elements in array

I have different randomly-styled stars in an array and I would like them to each have different scroll speeds between -.2 and -.8. The idea is to have them do a parallax effect, and it'd be cool to have everything a little random.
This was the original scroll speed code using images:
var starsOne = document.querySelector("#starsOne");
function setTranslate(xPos, yPos, el) {
el.style.transform = "translate3d(" + xPos + ", " + yPos + "px, 0)";
}
var xScrollPosition;
var yScrollPosition;
function scrollLoop() {
xScrollPosition = window.scrollX;
yScrollPosition = window.scrollY;
setTranslate(0, yScrollPosition * -0.6, starsOne);
requestAnimationFrame(scrollLoop);
}
window.addEventListener("load", scrollLoop, false);
I've been trying to integrate the above code somehow for the array:
let starScrollMin = 2;
let starScrollMax = 8;
var starScrollSpeed = -Math.abs((Math.floor(Math.random() * (starScrollMax - starScrollMin + 1)) + starScrollMin) / 10);
function starScroll() {
for (i = 0; i < starDivvyArr.length; i++) {
yScrollPos = window.scrollY;
starDivvyArr[i].style.transform = "translate3d(" + 0 + "px, " + yScrollPos * starScrollSpeed + "px, 0)";
}
requestAnimationFrame(starScroll);
}
window.addEventListener("load", starScroll, false);
If starScrollSpeed is global, then all the stars move in a big chunk. If it's within the starScroll() function, the values are at least different per star, but it gets crazy as it keeps randomizing and multiplying.
Any ideas on how to randomize the scroll speed for each star so it looks like a parallax effect, without them moving in one single chunk or going crazy? Or is it a safer bet to make a bunch of css lines and then randomly assign classes?
jsfiddle
It's a bit unclear what exactly you're after.
If you're trying to set a random scroll speed for each star, and not change it every time the startScroll triggers.
you could set a speed for each start separately inside the loop and use that in the startScroll function instead:
...
starDivvyArr[i].starScrollSpeed = -Math.abs((Math.floor(Math.random() * (starScrollMax - starScrollMin + 1)) + starScrollMin) / 10);
...
starDivvyArr[i].style.transform = "translate3d(" + 0 + "px, " + yScrollPos * starDivvyArr[i].starScrollSpeed + "px, 0)";
var starCount = 25;
let starContain = document.getElementById('starContain');
/*Create star divs*/
for (var i = 0; i < starCount; i++) {
var starDiv = document.createElement("div");
starDiv.className = 'star';
starContain.append(starDiv);
}
/*Make an array from the star divs*/
var starDivvy = document.querySelectorAll(".star");
var starDivvyArr = Array.from(starDivvy);
/*Create some possible styles*/
var starColor = ['yellow', 'blue', 'white'];
var starSizeMin = 5;
var starSizeMax = 25;
let starContainWidth = starContain.offsetWidth;
let starContainHeight = starContain.offsetHeight;
let starScrollMin = 2;
let starScrollMax = 8;
/*Give the star array some different styles*/
for (i = 0; i < starDivvyArr.length; i++) {
/*Change star color*/
starDivvyArr[i].style.backgroundColor = starColor[Math.floor(Math.random() * starColor.length)];
/*Change star position within container*/
starDivvyArr[i].style.left = Math.floor((Math.random() * starContainWidth) + 1) + "px";
starDivvyArr[i].style.top = Math.floor((Math.random() * starContainHeight) + 1) + "px";
/*Change star size*/
starDivvyArr[i].style.width = Math.floor(Math.random() * (starSizeMax - starSizeMin + 1)) + starSizeMin + "px";
starDivvyArr[i].style.height = starDivvyArr[i].style.width;
starDivvyArr[i].starScrollSpeed = -Math.abs((Math.floor(Math.random() * (starScrollMax - starScrollMin + 1)) + starScrollMin) / 10);
}
/*>>>>>>>POINT OF CONFUSION<<<<<<<*/
/*Randomize scroll speed between -0.2 and -0.8*/
/*Give the stars a scrolling function*/
function starScroll() {
for (i = 0; i < starDivvyArr.length; i++) {
yScrollPos = window.scrollY;
starDivvyArr[i].style.transform = "translate3d(" + 0 + "px, " + yScrollPos * starDivvyArr[i].starScrollSpeed + "px, 0)";
}
requestAnimationFrame(starScroll);
}
window.addEventListener("load", starScroll, false);
*{
margin:0 auto;
}
section{
width:100vw;
height:150vh;
}
.section1{
background-color:#000;
}
.section2{
background-color:#202;
}
h2{
text-align:center;
color:#ccc;
}
#starContain{
width:100vw;
height:500px;
position:absolute;
top:50vh;
z-index:2;
background-color:rgba(255,255,255,0.2);
}
.star{
background-color:green;
position:absolute;
z-index:100;
border-radius:50%;
}
<main>
<section class="section1">
<h2>
Section 1
</h2>
</section>
<div id="starContain">
</div>
<section class="section2">
<h2>
Section 2
</h2>
</section>
</main>
You could create an array for the randomly created numbers and push a value from a function that returns the randomly created speed into that array with in the loop and then use that array to get a random value for each element.
var starCount = 25;
let starContain = document.getElementById('starContain');
/*Create star divs*/
for (var i = 0; i < starCount; i++) {
var starDiv = document.createElement("div");
starDiv.className = 'star';
starContain.append(starDiv);
}
/*Make an array from the star divs*/
var starDivvy = document.querySelectorAll(".star");
var starDivvyArr = Array.from(starDivvy);
/*Create some possible styles*/
var starColor = ['yellow', 'blue', 'white'];
var starSizeMin = 5;
var starSizeMax = 25;
let starContainWidth = starContain.offsetWidth;
let starContainHeight = starContain.offsetHeight;
/*Give the star array some different styles*/
for (i = 0; i < starDivvyArr.length; i++) {
/*Change star color*/
starDivvyArr[i].style.backgroundColor = starColor[Math.floor(Math.random() * starColor.length)];
/*Change star position within container*/
starDivvyArr[i].style.left = Math.floor((Math.random() * starContainWidth) + 1) + "px";
starDivvyArr[i].style.top = Math.floor((Math.random() * starContainHeight) + 1) + "px";
/*Change star size*/
starDivvyArr[i].style.width = Math.floor(Math.random() * (starSizeMax - starSizeMin + 1)) + starSizeMin + "px";
starDivvyArr[i].style.height = starDivvyArr[i].style.width;
}
/*>>>>>>>POINT OF CONFUSION<<<<<<<*/
/*Randomize scroll speed between -0.2 and -0.8*/
let starScrollMin = 2;
let starScrollMax = 8;
//function for creating random scroll speed
const starScrollSpeed = (min,max) => {
return -Math.abs((Math.floor(Math.random() * (min - max + 1)) + min) / 10);
}
//==> added array
const starArray = [];
/*Give the stars a scrolling function*/
function starScroll() {
for (i = 0; i < starDivvyArr.length; i++) {
// array to hold randomly created scroll speeds
starArray.push(starScrollSpeed(starScrollMin,starScrollMax))
yScrollPos = window.scrollY;
starDivvyArr[i].style.transform = "translate3d(" + 0 + "px, " + yScrollPos * starArray[i] + "px, 0)";
}
requestAnimationFrame(starScroll);
}
window.addEventListener("load", starScroll, false);
* {
margin: 0 auto;
}
section {
width: 100vw;
height: 150vh;
}
.section1 {
background-color: #000;
}
.section2 {
background-color: #202;
}
h2 {
text-align: center;
color: #ccc;
}
#starContain {
width: 100vw;
height: 500px;
position: absolute;
top: 50vh;
z-index: 2;
background-color: rgba(255, 255, 255, 0.2);
}
.star {
background-color: green;
position: absolute;
z-index: 100;
border-radius: 50%;
}
<main>
<section class="section1">
<h2>
Section 1
</h2>
</section>
<div id="starContain">
</div>
<section class="section2">
<h2>
Section 2
</h2>
</section>
</main>

How to rotate point and place in the center?

I have tried to rotate point in case when parent container was rotated:
https://stackblitz.com/edit/js-qzfdbb?file=index.js
Code is:
var elParent = document.getElementById('parent');
var elCircle = document.getElementById('circle');
elCircle.addEventListener('click', function(e) {
const circleSvg = document.getElementById('circle');
const circleSvgRect = circleSvg.getBoundingClientRect();
const parentRect = document.getElementById('parent').getBoundingClientRect();
let leftTopX = circleSvgRect.left - parentRect.left;
let leftTopY = circleSvgRect.top - parentRect.top;
leftTopX = leftTopX + 15 - 5;
leftTopY = leftTopY + 15 - 5;
var degree = (20 * Math.PI) / 180;
var xc = 250;
var yc = 250;
leftTopX =
(leftTopX - xc) * Math.cos(degree) -
(leftTopY - yc) * Math.sin(degree) +
xc;
leftTopY =
(leftTopX - xc) * Math.sin(degree) +
(leftTopY - yc) * Math.cos(degree) +
yc;
let c = document.getElementById('c');
if (c) c.remove();
c = document.createElement('div');
c.setAttribute('id', 'c');
c.style.setProperty('left', leftTopX + 'px');
c.style.setProperty('top', leftTopY + 'px');
elParent.appendChild(c);
});
To see result make click inside red circle. Withour rotation a green circle is placed in the center of red circle. Otherwise has offset.
the maths should be something like this, but the solution needs some additional calculations for the rotation of the red circle itself within the outer rectangle.
Note 1: The margin of the body is removed for simplicity...
Note 2: Scrolls effect the script a lot. Therefore the solution also may not be very useful without taking it into consideration...
var elParent = document.getElementById('parent');
var elCircle = document.getElementById('circle');
elCircle.addEventListener('click', function(e) {
const circleSvg = document.getElementById('circle');
const circleSvgRect = circleSvg.getBoundingClientRect();
const parentRect = document.getElementById('parent').getBoundingClientRect();
const degree = getCurrentRotation(document.getElementById('parent'));
const xcenter = parentRect.width / 2 + parentRect.left;
const ycenter = parentRect.height / 2 + parentRect.top;
const dx = (circleSvgRect.left + 10) - xcenter;
const dy = ycenter - (circleSvgRect.top + 10);
console.log(dx + ' - ' + dy + '-' + Math.atan(dy / dx));
const r = Math.sqrt(dx * dx + dy * dy);
const curDegree = Math.atan(dy / dx) + degree;
xnew = xcenter + Math.sign(-dx) * Math.sin(curDegree) * r;
ynew = ycenter - Math.sign(-dx) * Math.cos(curDegree) * r;
let c = document.getElementById('c');
if (c) c.remove();
c = document.createElement('div');
c.setAttribute('id', 'c');
c.style.setProperty('left', xnew + 'px');
c.style.setProperty('top', ynew + 'px');
elParent.appendChild(c);
});
//https://stackoverflow.com/questions/19574171/how-to-get-css-transform-rotation-value-in-degrees-with-javascript
function getCurrentRotation(el) {
var st = window.getComputedStyle(el, null);
var tm =
st.getPropertyValue('-webkit-transform') ||
st.getPropertyValue('-moz-transform') ||
st.getPropertyValue('-ms-transform') ||
st.getPropertyValue('-o-transform') ||
st.getPropertyValue('transform') ||
'none';
if (tm != 'none') {
var values = tm
.split('(')[1]
.split(')')[0]
.split(',');
return (angle = Math.atan2(values[1], values[0]));
}
return 0;
}
<div id="parent">
<div id="circle" style="left: 100px; top: 100px"></div>
</div>
<style>
body {
margin:0px;
padding:0px;
}
#circle {
width: 30px;
height: 30px;
border-radius: 50%;
background: red;
position: relative;
}
#c {
position: absolute;
width: 10px;
height: 10px;
background: green;
border-radius: 50%;
}
#parent {
width: 500px;
position: relative;
height: 500px;
border: 1px solid #ccc;
transform: rotate(180deg);
}
</style>

how to add interval clock to a random square generator

i'm trying to make a random square generator that makes one square show up on the screen every 5 seconds (not an additional square but i'm trying to move the original square to a random location every 5 seconds)
i experimented with interval but nothing worked.
this is what i done so far. it gives me a random square every time i refresh the page.
var h = window.innerHeight;
var w = window.innerWidth;
var randomTop = Math.random() * h;
var randomLeft = Math.random() * w;
var boxPosition = {
left: randomLeft,
top: randomTop
};
document.write('<div style="width: 64px; height:64px;background-color:blue; left: ' + boxPosition.left + 'px; top: ' + boxPosition.top + 'px;position: absolute"></div>');
https://codepen.io/danielle-23523/pen/LYRpPNp
If you wrap your code in a function and call that function on load as well as in setInterval it works.
I also updated your code to delete any previously added boxes.
var h = window.innerHeight;
var w = window.innerWidth;
function create() {
var boxPosition = {
left: Math.random() * w,
top: Math.random() * h
};
box = document.querySelector("#box")
if(box)box.remove();
document.write(
'<div id="box" style="width: 64px; height:64px;background-color:blue; left: ' +
boxPosition.left +
"px; top: " +
boxPosition.top +
'px;position: absolute"></div>'
);
}
create();
setInterval(create, 5000);
Try this:-
<html>
<head>
</head>
<body>
<script>
function generateAndAddSquare() {
var h = window.innerHeight;
var w = window.innerWidth;
var randomTop = Math.random() * h;
var randomLeft = Math.random() * w;
var boxPosition = {
left: randomLeft,
top: randomTop
};
var node = document.createElement('div')
node.style.width = '64px';
node.style.height = '64px';
node.style.backgroundColor = 'blue';
node.style.left = boxPosition.left + 'px';
node.style.top = boxPosition.top + 'px';
node.style.position = 'absolute';
document.body.appendChild(node);
}
setInterval(generateAndAddSquare, 1000);
</script>
</body>
</html>

How to set css width or left attributes to get pixel perfect result?

I just started experimenting with JS/CSS a bit and I came across this problem I couldn't find an answer for on the forum.
I wonder how I could get rid off the white line in the middle of the window (picture attached). It doesn't appear all the time but at certain scalings.
Many thanks
<html>
<head>
<style>
body {
margin: 0;
padding: 0;
}
.d {
position: fixed;
margin: 0;
padding: 0;
border: 0px;
background-color: #A1F1F1;
text-align: center;
}
</style>
</head>
<body>
<script>
var numOfDivsHor = 10;
var numOfDivsVer = 10;
function setCubeSize() {
document.body.innerHTML = '';
var w = document.body.clientWidth;
var h = document.body.clientHeight;
var fs = h/numOfDivsVer/3;
for (i=0; i < numOfDivsHor; i++) {
for (j=0; j < numOfDivsVer; j++) {
var d = document.createElement('div');
document.getElementsByTagName('body')[0].appendChild(d);
d.id = i + '' + j;
d.className = 'd';
d.innerHTML = i + '' + j;
setLayout(i + '' + j, w, h, fs);
d.style.left = j * w/numOfDivsHor + 'px';
d.style.top = i * h/numOfDivsVer + 'px';
d.style.backgroundColor = 'rgb(120, ' + Math.round(i * 25.5) + ', ' + Math.round(j * 25.5) + ')';
}
}
}
function setLayout(divId, w, h, fs) {
var d = document.getElementById(divId);
d.style.width = 100/numOfDivsHor + '%';
d.style.height = 100/numOfDivsVer + '%';
d.style.fontSize = fs + 'px';
d.style.paddingTop = (h/numOfDivsVer - fs)/2 + 'px';
}
document.addEventListener('DOMContentLoaded', function() {;
setCubeSize();
});
window.addEventListener('resize', function() {
setCubeSize();
});
</script>
</body>
</html>
white line in the middle
This a rounding issue that is common when dealing with graphics and floating point numbers. You more or less just need to floor values when you divide.
Specifically, this change fixes the problem in the code that you posted. Change:
d.style.left = j * w/numOfDivsHor + 'px';
d.style.top = i * h/numOfDivsVer + 'px';
to:
d.style.left = j * Math.floor(w/numOfDivsHor) + 'px';
d.style.top = i * Math.floor(h/numOfDivsVer) + 'px';
Note that you will be left with whitespace on one edge of the grid. This is because the size of the window is not a perfect multiple of the size of a cell. You have to choose either between keeping the sizes of the cells the same, as above, or having varying sizes of cell, which would take a bit more work.

Random Keyframe Positions Every Iteration to Create Falling "Matrix Code"

I'm attempting to make an HTML web page with animated CSS classes on many independent DIVs moving to their own randomly generated positions. I have 20 elements with randomly generated characters falling from the top of the page and dissipating as they move along their y-axis (like the Matrix code).
EDIT: JsFiddle Demo Remember the range is wide, so sometimes the group of characters generate far off to the right (outside the small viewing window)
Generating random char in top JavaScript
<script type="text/javascript">
$(document).ready(function() {
});
function generateChar()
{
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789«‘¥~‹÷´`≠¡ˆ()][¶##…•–!£$%&/?^*駰ç_:è+òàù,.-";
text = possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
</script>
HTML of 20 divs
<div id="m1 " class="timeSpan movement"></div>
...
<div id="m20" class="timeSpan movement"></div>
JavaScript: Here I've randomly generated characters (successfully) but only 1 random position. All the elements start in the same position instead of starting from their own spots.
<script type="text/javascript">
document.getElementById("m1 ").innerHTML = generateChar();
...
document.getElementById("m20").innerHTML = generateChar();
var divs = document.getElementsByTagName("div");
for(var i = 0; i < divs.length; i++){
var xRandom = Math.round(Math.random() * 2000);
var yBegRan = Math.round(Math.random() * 150);
var yEndRan = Math.round(Math.random() * (2000 - 650) + 650);
var secRan = Math.round(Math.random() * (20));
var style = document.documentElement.appendChild(document.createElement("style")),
rule = " moveMinus {\
0% {\
opacity: 1;\
}\
100% {\
opacity: 0; \
}\
from {\
top: " + yBegRan + "px; left: " + xRandom + "px;\
}\
to {\
top: " + yEndRan + "px; left: " + xRandom + "px;\
}\
}";
if (CSSRule.KEYFRAMES_RULE) {
style.sheet.insertRule("#keyframes" + rule, 0);
} else if (CSSRule.WEBKIT_KEYFRAMES_RULE) {
style.sheet.insertRule("#-webkit-keyframes" + rule, 0);
}
divs[i].innerHTML = makeid();
}
</script>
CSS
.body-m{
background-color: black;
overflow: hidden;
}
.movement{
position: absolute;
font-size: 20px;
color: limegreen;
background-color: transparent;
overflow: hidden;
}
#keyframes moveMinus {
from { top: 0px; left: 21px; }
to { top: 600px; left: 21px; }
0% { opacity: 1; }
100% { opacity: 0; }
}
.timeSpan{
animation: moveMinus 7s infinite;
}
How do I properly iterate through the DIVs' styles?
Hi I just made this fiddle, Fiddle, I'm not sure that's what you wanted but I get a result that you can easily edit =)
Here is the main function :
function setDiv(_div){
var xRandom = Math.round(Math.random() * 2000);
var yBegRan = Math.round(Math.random() * 600);
var yEndRan = Math.round(Math.random() * (2000 - 650) + 650);
var secRan = Math.round(Math.random() * (20)) + 10;
_div.style.opacity = 1;
_div.style.top = yBegRan +"px";
_div.style.animationDuration = secRan +"s";
_div.style.left = xRandom + "px";
_div.innerHTML = generateChar();
}
function generateChar() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789«‘¥~‹÷´`≠¡ˆ()][¶##…•–!£$%&/?^*駰ç_:è+òàù,.-";
text = possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
var len = 500;
var style = document.createElement("style");
document.body.appendChild(style);
for (var i = 0; i < len; i++) {
var xRandom = Math.round(Math.random() * 2000);
var yBegRan = Math.round(Math.random() * 150);
var yEndRan = Math.round(Math.random() * (2000 - 650) + 650);
var secRan = Math.round(Math.random() * (20));
var rule = " moveMinus" + i +" {"
+ "0%{opacity: 1;top:"
+ yBegRan + "px; left:"
+ xRandom + "px;"
+ "}"
+ "100% {"
+ "opacity: 0;top:"
+ yEndRan + "px; left:"
+ xRandom + "px;"
+ "}}";
var div = document.createElement("div");
div.style.position = "absolute";
div.style.left = (Math.random() * window.innerWidth) + "px";
div.className = "timeSpan" + i;
div.innerHTML = generateChar();
if (!("webkitAnimation" in document.body.style)) {
style.textContent += "." + div.className
+"{animation:moveMinus"+i+" "+Math.random() * 7
+"s infinite;}\n" +"#keyframes" + rule;
} else {
style.textContent += "." + div.className
+"{-webkit-animation:moveMinus"+i+" "+Math.random() * 7
+"s infinite;}\n"
+"#-webkit-keyframes" + rule;
};
document.body.appendChild(div)
}
.body-m {
background-color: black;
overflow: hidden;
}
/*Base Class*/
.movement {
position: absolute;
font-size: 20px;
color: limegreen;
background-color: transparent;
overflow: hidden;
}
div {
color:lime;
}
<body class="body-m"></body>
jsfiddle http://jsfiddle.net/yLzkvb9e/2/

Categories

Resources