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

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/

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>

Get center coordinates of circle sector

I need to set up <text> element in the center of pie chart segments in an svg <circle>. Right now I use this formula for coordinates:
x(t) = r cos(t) + j
y(t) = r sin(t) + j
where t must be radians. Actually, it works good the first point. But next points are wrong (see code snippet). The question is do I use the wrong formula?
It's my calculations for <text> coordinates
var textAngle = ((data[c].value/100) *360)/2 + textAngleOffset;
var radians = degrees_to_radians(textAngle);
text.setAttribute("x", radius * Math.cos(radians) + 188.5 );
text.setAttribute("y", radius * Math.sin(radians) + 188.5);
//Pie chart plugin
function initPieChart(segmentsData) {
var data = [];
for (var i = 0; i < segmentsData.length; i++) {
var percent = segmentsData[i].getAttribute('data-percent');
var bgcolor = segmentsData[i].getAttribute('data-bg-color');
var textcolor = segmentsData[i].getAttribute('data-text-color');
data.push({"bgcolor": bgcolor, "textcolor": textcolor, "value" : Number(percent)});
}
var angle = -90;
var textAngleOffset = -90;
// Setup global variables
var svg = document.getElementById('pie-chart'),
list = document.getElementById('pie-values'),
totalValue = 0,
radius = 94,
circleLength = Math.PI * (radius * 2), // Circumference = PI * Diameter
spaceLeft = circleLength;
// Get total value of all data.
for (var i = 0; i < data.length; i++) {
totalValue += data[i].value;
}
function degrees_to_radians(degrees){
var pi = Math.PI;
return degrees * (pi/180);
}
function animate(circle, segmentLength, circleLength) {
// circle.setAttribute("stroke-dasharray", spaceLeft + " " + circleLength);
circle.setAttribute("stroke-dasharray", circleLength *segmentLength + " " + circleLength);
}
var segmentOffset = 0;
var animationDelay = 0;
// Loop trough data to create pie
for (var c = 0; c < data.length; c++) {
var segmentLength = data[c].value/100;
var angleOffset = (data[c].value) *360 + angle;
animationDelay = animationDelay + 800;
if(c>0) {
segmentOffset = segmentOffset -data[c-1].value/100*circleLength;
textAngleOffset = (data[c].value/100) *360 + textAngleOffset;
}
// Create circle
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
// Create group for each segment
var group = document.createElementNS("http://www.w3.org/2000/svg", "g");
group.classList.add("segment-group");
//Create text
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
var textAngle = ((data[c].value/100) *360)/2 + textAngleOffset;
var radians = degrees_to_radians(textAngle);
text.setAttribute("x", radius * Math.cos(radians) + 188.5 );
text.setAttribute("y", radius * Math.sin(radians) + 188.5);
text.setAttribute("text-anchor", "middle");
text.setAttribute("fill", data[c].textcolor);
text.innerHTML = data[c].value + '%';
// Set attributes (self explanatory)
circle.setAttribute("class", "pie-chart-value");
circle.setAttribute("cx", 188.5);
circle.setAttribute("cy", 188.5);
circle.setAttribute("r", radius);
circle.setAttribute("transform", "rotate(" + angleOffset + ", 188.5, 188.5)");
// Set dash on circle
circle.setAttribute("stroke-dasharray", "0" + " " + circleLength);
setTimeout(animate, animationDelay, circle, segmentLength, circleLength);
if(c>0) {
circle.setAttribute("stroke-dashoffset", segmentOffset);
}
// Set Stroke color
circle.style.stroke = data[c].bgcolor;
//Append circle and text to group
group.appendChild(circle);
group.appendChild(text);
// Append group to svg.
svg.appendChild(group);
}
}
//Pie chart call
var chartSegments = document.getElementsByClassName('pie-segment');
initPieChart(chartSegments);
/* Pie chart styles */
.pie-chart-value {
fill: none;
stroke-width: 188.5;
transition: stroke-dasharray 800ms linear;
}
/* */
.time-statistics {
padding-top: 30px;
}
.chart-value {
position: relative;
margin-bottom: 5px;
}
.chart-value:before {
display: none;
}
.chart-value .dot {
width: 8px;
height: 8px;
border-radius: 100%;
margin-right: 10px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.pie-chart-container {
position: relative;
}
.pie-chart-bg {
position: absolute;
top: 0px;
left: 0;
z-index: -1;
}
.pie-chart-content {
position: absolute;
top: 0px;
left: 0px;
}
<div class="pie-chart-container">
<span class="pie-segment" data-percent="20" data-bg-color="#d8d8d8" data-text-color="#123431"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#345a57" data-text-color="white"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#133532" data-text-color="white"></span>
<div class="pie-chart-content">
<svg id="pie-chart" width="377" height="377"></svg>
</div>
</div>
You need to adjust the textoffset for the previous value, not the current one. I.e.:
textAngleOffset = (data[c-1].value/100) *360 + textAngleOffset;
Here is working code:
//Pie chart plugin
function initPieChart(segmentsData) {
var data = [];
for (var i = 0; i < segmentsData.length; i++) {
var percent = segmentsData[i].getAttribute('data-percent');
var bgcolor = segmentsData[i].getAttribute('data-bg-color');
var textcolor = segmentsData[i].getAttribute('data-text-color');
data.push({"bgcolor": bgcolor, "textcolor": textcolor, "value" : Number(percent)});
}
var angle = -90;
var textAngleOffset = -90;
// Setup global variables
var svg = document.getElementById('pie-chart'),
list = document.getElementById('pie-values'),
totalValue = 0,
radius = 94,
circleLength = Math.PI * (radius * 2), // Circumference = PI * Diameter
spaceLeft = circleLength;
// Get total value of all data.
for (var i = 0; i < data.length; i++) {
totalValue += data[i].value;
}
function degrees_to_radians(degrees){
var pi = Math.PI;
return degrees * (pi/180);
}
function animate(circle, segmentLength, circleLength) {
// circle.setAttribute("stroke-dasharray", spaceLeft + " " + circleLength);
circle.setAttribute("stroke-dasharray", circleLength *segmentLength + " " + circleLength);
}
var segmentOffset = 0;
var animationDelay = 0;
// Loop trough data to create pie
for (var c = 0; c < data.length; c++) {
var segmentLength = data[c].value/100;
var angleOffset = (data[c].value) *360 + angle;
animationDelay = animationDelay + 800;
if(c>0) {
segmentOffset = segmentOffset -data[c-1].value/100*circleLength;
textAngleOffset = (data[c-1].value/100) *360 + textAngleOffset;
}
// Create circle
var circle = document.createElementNS("http://www.w3.org/2000/svg", "circle");
// Create group for each segment
var group = document.createElementNS("http://www.w3.org/2000/svg", "g");
group.classList.add("segment-group");
//Create text
var text = document.createElementNS("http://www.w3.org/2000/svg", "text");
var textAngle = ((data[c].value/100) *360)/2 + textAngleOffset;
var radians = degrees_to_radians(textAngle);
text.setAttribute("x", radius * Math.cos(radians) + 188.5 );
text.setAttribute("y", radius * Math.sin(radians) + 188.5);
text.setAttribute("text-anchor", "middle");
text.setAttribute("fill", data[c].textcolor);
text.innerHTML = data[c].value + '%';
// Set attributes (self explanatory)
circle.setAttribute("class", "pie-chart-value");
circle.setAttribute("cx", 188.5);
circle.setAttribute("cy", 188.5);
circle.setAttribute("r", radius);
circle.setAttribute("transform", "rotate(" + angleOffset + ", 188.5, 188.5)");
// Set dash on circle
circle.setAttribute("stroke-dasharray", "0" + " " + circleLength);
setTimeout(animate, animationDelay, circle, segmentLength, circleLength);
if(c>0) {
circle.setAttribute("stroke-dashoffset", segmentOffset);
}
// Set Stroke color
circle.style.stroke = data[c].bgcolor;
//Append circle and text to group
group.appendChild(circle);
group.appendChild(text);
// Append group to svg.
svg.appendChild(group);
}
}
//Pie chart call
var chartSegments = document.getElementsByClassName('pie-segment');
initPieChart(chartSegments);
/* Pie chart styles */
.pie-chart-value {
fill: none;
stroke-width: 188.5;
transition: stroke-dasharray 800ms linear;
}
/* */
.time-statistics {
padding-top: 30px;
}
.chart-value {
position: relative;
margin-bottom: 5px;
}
.chart-value:before {
display: none;
}
.chart-value .dot {
width: 8px;
height: 8px;
border-radius: 100%;
margin-right: 10px;
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
}
.pie-chart-container {
position: relative;
}
.pie-chart-bg {
position: absolute;
top: 0px;
left: 0;
z-index: -1;
}
.pie-chart-content {
position: absolute;
top: 0px;
left: 0px;
}
<div class="pie-chart-container">
<span class="pie-segment" data-percent="20" data-bg-color="#d8d8d8" data-text-color="#123431"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#345a57" data-text-color="white"></span>
<span class="pie-segment" data-percent="40" data-bg-color="#133532" data-text-color="white"></span>
<div class="pie-chart-content">
<svg id="pie-chart" width="377" height="377"></svg>
</div>
</div>

Dynamically adding a transform - reverts back to original value at the end

I am trying to dynamically add a transform: translate3d to move a div, but at the end of the transform, the div reverts back to the original position. I am adding a new stylesheet and using insertRule(). Any ideas what could be causing this?
Here is a fiddle:
slideshow = (function() {
function slideshow() {
var _this = this;
this.divMiddle;
this.divLarge = []; // holds full sized image
this.largeSize = [];
this.slide = -1;
this.oldSlide = -1;
this.img = [];
this.divMiddle = document.createElement("div");
this.divMiddle.id = "divMiddle";
this.divMiddle.style.position = "relative"
this.divMiddle.style.width = "500px";
this.divMiddle.style.height = "400px";
this.divMiddle.style.border = "1px solid black";
document.body.appendChild(this.divMiddle);
document.getElementById("next").addEventListener("click", function() {
_this.transitionSlides(1)
});
document.getElementById("prev").addEventListener("click", function() {
_this.transitionSlides(-1)
});
this.oldSlide = -1;
this.slide = -1;
this.transitionSlides(1);
}
// transition between slides - fading new one in and old one out
slideshow.prototype.transitionSlides = function(direction) {
// if not the first one loaded, will do transition
var begin, end;
this.oldSlide = this.slide;
this.slide += direction;
if (this.slide > this.oldSlide) {
this.createImage();
}
if (CSSRule.KEYFRAMES_RULE) {
var prefix = ""
} else if (CSSRule.WEBKIT_KEYFRAMES_RULE) {
var prefix = "-webkit-"
}
var style = document.createElement("style");
document.head.appendChild(style);
// fade out the old slide
if (this.oldSlide >= 0) {
// fade(this.divLarge[this.oldSlide], 1, .1, 20);
this.divLarge[this.oldSlide].style.opacity = ".3";
var oldMargin = (parseInt(this.divMiddle.style.width) - parseInt(this.largeSize[this.oldSlide].displayWidth)) / 2;
begin = 0;
if (direction == 1) {
// next
// move existing slide from left to right
end = (parseInt(this.largeSize[this.oldSlide].displayWidth) + oldMargin);
} else {
// prev
// move existing slide from right to left
end = -(parseInt(this.largeSize[this.oldSlide].displayWidth) + oldMargin + 1);
}
var rule = "#" + prefix + "keyframes moveOld {" +
"0% {" + prefix + "transform: translate3d(" + begin + "px, 0, 0); }" +
"100% {" + prefix + "transform: translate3d(" + end + "px, 0, 0); }" +
"}";
style.sheet.insertRule(rule, 0);
var rule2 = "#" + this.divLarge[this.oldSlide].id + "{" + prefix + "animation: moveOld 3s linear" + "}";
style.sheet.insertRule(rule2, 0);
}
// fade in the new slide
//fade(this.divLarge[this.slide], .1, 1, 20);
this.divLarge[this.slide].style.opacity = "1";
this.divLarge[this.slide].style.display = "block";
var margin = (parseInt(this.divMiddle.style.width) - parseInt(this.largeSize[this.slide].displayWidth)) / 2;
begin = 0;
if (this.oldSlide == -1) {
// first slide - don't move
this.divLarge[this.slide].style.left = margin + "px";
end = 0;
} else if (direction == 1) {
// next
// move new slide from left to right
// move to starting position
this.divLarge[this.slide].style.left = (oldMargin - parseInt(this.largeSize[this.slide].displayWidth)) + "px";
end = (-oldMargin + parseInt(this.largeSize[this.slide].displayWidth) + margin);
} else {
// prev
// move new slide from right to left
// move to starting position
this.divLarge[this.slide].style.left = (oldMargin + parseInt(this.largeSize[this.oldSlide].displayWidth)) + "px";
end = +oldMargin - (parseInt(this.largeSize[this.slide].displayWidth) + margin);
}
var rule = "#" + prefix + "keyframes moveNew {" +
"0% {" + prefix + "transform: translate3d(" + begin + "px, 0, 0); }" +
"100% {" + prefix + "transform: translate3d(" + end + "px, 0, 0); }" +
"}";
style.sheet.insertRule(rule, 0);
var rule2 = "#" + this.divLarge[this.slide].id + "{" + prefix + "animation: moveNew 2s linear" + "}";
style.sheet.insertRule(rule2, 0);
}
slideshow.prototype.createImage = function() {
var img = document.createElement("img");
var from = 100;
var to = 300;
var width = Math.floor(Math.random() * (to - from + 1) + from);
var height = Math.floor(Math.random() * (to - from + 1) + from);
img.src = "http://placehold.it/" + width + "x" + height;
img.style.height = height;
img.style.width = width;
this.img.push(img);
var div = document.createElement("div");
div.id = "slideshow-large-" + (this.img.length - 1)
div.style.display = "none";
div.style.top = ((parseInt(this.divMiddle.style.height) - height) / 2) + "px";
div.style.position = "absolute";
div.style.width = width + "px";
div.className = "slideshow-large";
div.appendChild(img);
this.divLarge.push(div);
this.largeSize.push({
displayWidth: width,
displayHeight: height
});
this.divMiddle.appendChild(div);
}
return slideshow;
})();
var ss = new slideshow();
The styles and HTML
<div id="next">Next Slide</div>
<div id="prev">Prev Slide</div>
#divMiddle {
width: 600px;
height: 600px;
display: flex;
position: relative;
top: 0px;
left: 0px;
overflow: hidden;
}
div.slideshow-large {
overflow: hidden;
top: 0;
position: absolute;
}
div.slideshow-large img {
display: block;
}
div.slideshow-large span {
position: absolute;
top: 0;
left: 0;
z-index: 1070;
}
You should add animation-fill-mode: forwards to your code, it'll keep the animation at the ending value. For your code example, it'd be something like this:
...
var rule2 = "#" + this.divLarge[this.slide].id + "{" + prefix + "animation: moveNew 2s linear forwards" + "}";
...

Place elements to canvas using 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; }

Categories

Resources