I have the following code which generates some random images on an SVG canvas.
What I want to do is use the code under the //this bit// comment to append an animate node to all the elements with a specific class.
However, the code below does not work... and for the life of me I cant figure out why, could anyone point me in the right direction
function createBackground(){
var loopLimit = Math.floor((Math.random()*100)+1);
for(var i=0; i<100; i++)
{
var jpgSelecter = Math.floor((Math.random()*10)+1);
var thisItem = document.createElementNS( svgNS, "image" );
thisItem.setAttributeNS(null,"id","node_" + Math.round(new Date().getTime() / 1000));
thisItem.setAttributeNS(null,"class","node" + jpgSelecter);
thisItem.setAttributeNS(null,"x",(Math.random()*500)+1);
thisItem.setAttributeNS(null,"y",(Math.random()*500)+1);
thisItem.setAttributeNS(null,"width",(Math.random()*500)+1);
thisItem.setAttributeNS(null,"height",(Math.random()*500)+1);
thisItem.setAttributeNS(xlinkns,"xlink:href","images/blobs" + jpgselecter + ".png");
document.getElementById("SVGcanvas").appendChild(thisItem);
}
//This Bit//
var animate = document.createElementNS( svgNS, "animateTransform" );
ani.setAttributeNS(null,"name","transform");
ani.setAttributeNS(null,"begin","0");
ani.setAttributeNS(null,"type","rotate");
ani.setAttributeNS(null,"from", "0 180 50");
ani.setAttributeNS(null,"to","360 180 50");
ani.setAttributeNS(null,"dur","4");
ani.setAttributeNS(null,"repeatCount","indefinite");
var tenner = document.getElementsByClassName("node_10");
for(i=0; i<tenner.length; i++)
{
alert(tenner[i]);
tenner[i].appendChild(ani);
}
}
Update
I've edited my code, this doesn't throw up any errors however the animation node doesn't get appended.
I see two problems:
You create an animate element, but then attempt to set attributes on an ani object and append this object to all classed elements.
Even if you change animate to ani, you cannot append the same element to multiple children. Your loop will place the element on the first found class, and then move it to the second found class, and so on. Instead, you need to create a copy of it for each item. So, either do this:
for(var i=0; i<tenner.length; i++){
var ani = document.createElementNS(svgNS,'animateTransform');
// set all attributes
tenner[i].appendChild(ani);
}
…or do this:
var ani = document.createElementNS(svgNS,'animateTransform');
// set all attributes
for(i=0; i<tenner.length; i++){
tenner[i].appendChild(ani.cloneNode(true));
}
Related
I want to tween elements inside a container. The elements will be added in a for loop. Once they have been added I know that they are on the stage I then want to animate the elements in individually with a delay so that the first element animates in first then the second etc etc.
addElements();
function addElements(){
var total = arr.length;
var _cont = new createjs.Container();
stage.addChild(_cont)
for(var i=0;i<total;i++){
//add children to _cont
}
animateIn();
}
function animateIn(){
//I now want to tween each element in _cont individually
}
Thx.
I have updated the animateIn function below.
function animateIn(obj){
Debugger.log("Animate In");
for(i=0;i<obj.getNumChildren();i++){
obj.getChildAt(i).alpha = 0;
createjs.Tween.get(obj.getChildAt(i)).wait(i*100).to({alpha:1}, 1000)
}
}
Thx.
You can try something like this:
for (var i = 0; i < childElementCount; i++)
{
setTimeout (<animate function in context of current child>, i*<duration of your animation>);
}
I am trying to animate a dynamically created div with javascript, the id for the div is assigned when it is created, everything works fine until I attempt to animate one of the divs, I am trying this :
function start() // Called from a button click
{
var moveDiv= document.getElementById('Id0'); // Id0 is the Id of the div to move
animate(moveDiv); // Recursive animate
}
function animate(inDiv)
{
inDiv.style.left = parseInt(inDiv.style.left)+1+'px';
setTimeout(animate,20); // Recursive call
}
I know this is supposed to move the div infinitely to the left. However nothing happens at all and I cannot figure out why, I don't think its the fact that I dynamically create the divs as I have checked all the Id's and they all exist so I don't think its because it can't find Id0, but just incase here is a snippet of my div creation code :
for(var i=0; i<ca.length; i++)
{
var c = ca[i].trim();
var start = c.indexOf('"coursename":"') + 14;
var end = c.indexOf('","coursemark":"');
var CC = c.substring(start,end);
var start = c.indexOf('","coursemark":"') + 16;
var end = c.indexOf('%"')+1;
var CM = c.substring(start,end);
var idCount = i;
var div = document.createElement("div");
div.style.width = "180px";
div.style.height = "75px";
div.style.backgroundColor = "rgba(0,100,175,0.8)";
div.style.color = "white";
div.style.marginTop = "2%";
div.style.marginLeft = "50%";
div.id = "sortID"+idCount;
div.innerHTML = "Course Name : " + CC + " Course Mark : " + CM + " Id : " + div.id;
document.body.appendChild(div);
}
This code works fine however and creates the divs perfectly, I just can't get any div to move. Any help would be greatly appreciated.
Couple of problems...
function start() // Called from a button click
{
var moveDiv= document.getElementById('Id0'); // Id0 is the Id of the div to move
animate(moveDiv); // Recursive animate
}
There is no element with ID of Id0. All of your generated element IDs look like sortID...
And then...
function animate(inDiv)
{
inDiv.style.left = parseInt(inDiv.style.left)+1+'px';
setTimeout(animate,20); // Recursive call
}
inDiv.style.left has never been initiated
You're not passing inDiv through to your recursive animate call
So firstly check your element references. Then make sure you're setting the position of the div correctly, or handling scenarios where it isn't yet set. And finally make sure you pass inDiv through recursively.
for(var i=0; i<num_cols; i++)
{
//Wrapper for column
$('#cupcake-list').append('<div>');
//end wrapper
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$('#cupcake-list').append('<p>'+cupcakeData[d].name+'</p>');
}
//Wrapper for column
$('#cupcake-list').append('</div>');
//end wrapper
}
I just want to encapsulate my p tags within div tags to act as rows, however all I get are <div></div><p>ssdfsdf</p><p>sdfsdfdsf</p><div></div>etc....
What's the best way of doing it?
Start with a fragment so that you don't access the DOM more than once, and append it all at the end. You can skip the wrap by starting with your empty fragment, like so:
var $fragment;
for(var i=0; i<num_cols; i++)
{
$fragment = $('<div />');
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$fragment.append('<p>'+cupcakeData[d].name+'</p>');
}
//Wrapper for column
$('#cupcake-list').append($fragment);
//end wrapper
}
This is a much faster way to do it! Append parts of a string to an array and then you only have to update the DOM once.
var a = [];
for(var i=0; i<num_cols; i++)
{
a.push('<div>');
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
a.push('<p>'+cupcakeData[d].name+'</p>');
}
a.push('</div>');
}
$('#cupcake-list').append(a.join(''));
EDIT:
I'll explain why yours wasn't working. When you were calling $('#cupcake-list').append('<div>'); you thought it would only add the opening div tag, but that is not the case. jQuery won't let you do this is because they want to make sure the html is valid after every function call. If you were to just add the opening div and then do some other stuff, the next closing div (</div>) in the document would close the div you just opened, changing the structure of the document entirely.
In summation:
$('#cupcake-list').append('<div>'); and $('#cupcake-list').append('</div>'); will both append <div></div> to the document. Also, access and update the DOM as if it costs you a million dollars because it is among the slowest things you can do in javascript.
jQuery has a method called .wrap, and some similar ones (.wrapAll).
If you are having the output that you showed, your code is not reaching the inner for, so you have a logic problem. I think your way of doing this is correct. When i need to build some structure on the fly i usually do the same thing.
JQuery append adds DOM nodes, not HTML. So you can accomplish your task like this:
for(var i=0; i<num_cols; i++)
{
col_count++;
num_in_col = rowsInCol(total,num_perCol,col_count);
start = i*num_perCol;
end = start + num_in_col;
for(var d=start; d<end; d++)
{
$('#cupcake-list').append($('<div></div>').append('<p>'+cupcakeData[d].name+'</p>'));
}
}
First, $('<div></div>') creates a new empty div element not yet attached to the page (you can also do $('<div>') as a shorthand if you want). Then .append('<p>...</p>') adds a p element inside the div. Finally, $('#cupcake-list').append(...) adds the whole div to the end of #cupcake-list.
I am absolutely new to javascript, so please bear with me.
I have 50 elements on my page with ids. All are set to visibility:hidden and position:fixed. I have a button that corresponds to each element. When a button is clicked, a javascript function is initiated which makes the corresponding element visibile and position:relative. Code looks something like this:
document.getElementById("id1").style.position='relative';
document.getElementById("id1").style.visibility='visible';
To ensure that only one element is ever visible and relative, I also need to make the other 49 elements hidden and fixed. How can I accomplish this without having to resort to the following sort of code:
function makeid1visibile()
{
document.getElementById("id1").style.position='relative';
document.getElementById("id1").style.visibility='visible';
document.getElementById("id2").style.position='fixed';
document.getElementById("id2").style.visibility='hidden';
document.getElementById("id3").style.position='fixed';
document.getElementById("id3").style.visibility='hidden';
document.getElementById("id4").style.position='fixed';
document.getElementById("id4").style.visibility='hidden';
// etc...
}
Any help would be appreciated, because with 50 elements, the number of lines of coding would be outrageous.
Should be able to handle it with a single loop, just pass in the number of the item you wish to show:
function makeIdVisible(id) {
document.getElementById("id" + id).style.position='relative';
document.getElementById("id" + id).style.visibility='visible';
for (var i = 1; i <= 50; i++) {
if (i !== id) {
document.getElementById("id" + i).style.position='fixed';
document.getElementById("id" + i).style.visibility='hidden';
}
}
}
give yours checkboxes classname "someclass" and select all elements by function documet.getElementsByClassName
You can write a function like this:
function makeVisible( id ){
var idList = ['id1','id2','id3','id4'];
for( var i = 0, l = idList.length; i<l ; i++ ){
document.getElementById(idList[i]).style.position='fixed';
document.getElementById(idList[i]).style.visibility='hidden';
}
document.getElementById(id).style.position='relative';
document.getElementById(id).style.visibility='visible';
}
Then you can use
makeVisible('#id1');
to make the id1 element visible
I have the following function:
function slideDown() {
//get the element to slide
sliding = document.getElementById('slideDiv1');
//add 1px to the height each time
sliding.style.height = parseInt(sliding.style.height)+1+'px';
t = setTimeout(slideDown,30);
if (sliding.style.height == "401px") {
clearTimeout(t);
}
}
which is called within this function:
function addDiv(nextImageSlide) {
//finds the src attribute of the image nested in the Li
elemChild = nextImageSlide.firstChild;
imageSrc = elemChild.getAttribute('src');
//loops and creates six divs which will be the slices. adds background property etc
for (i = 0, j = 0, k = 1; i< = 19; i++, j++, k++) {
var newDiv = document.createElement('div');
newDiv.setAttribute('class', 'new-div');
newDiv.id='slideDiv' + k;
newDiv.style.height = '1px';
newDiv.style.background = 'url(' + imageSrc +') scroll no-repeat - '+39.5 * j + 'px 0';
var a = document.getElementById('content');
a.appendChild(newDiv);
}
slideDown();
}
Which is called within another function that defines nextImageSlide. It later removes all the divs that it just made.
The idea is for an image gallery. When the user hits the next button, I want slices of the next image to slide down to show the next image. Those slices are then taken away and the new image revealed.
I would like something like this: http://workshop.rs/projects/jqfancytransitions/.
It's for an assignment so we have to write all the code ourself and this is the best way I can think to replicate it. The only problem is that I keep getting an error:
'sliding is null. sliding.style.height = parseInt(sliding.style.height)+1+'px';'
No matter what I do I can't get rid of it. The thing is if I define sliding as a totally different id, (for example I made a random little div outside of everything), it working.
This error shows when I try to access the divs, it just made that it throws a hissy fit.
Anyone see any errors in my code?
Hopefully this is just a typo while pasting into the site here, but:
car a = document.getElementById('content');
^---syntax error, which'll kill your entire script - var?