javascript (making collage from images) - javascript

javascript code for making collage through images working in mozilla but chrome
$(document).ready(function() {
var canvaswidth = $('.rc-contentholder').width();
var canvasheight = $('.rc-contentholder').height();
function setleftandtop(noofdivision) {
var elements = document.getElementsByClassName('rc-singlecontentholder');
var noofelements = elements.length;
//place the first row
currentelementid = elements[0].id;
$("#" + currentelementid).css('left', '0px');
$("#" + currentelementid).css('top', '0px');
for (j = 1; j < noofdivision; j++) {
previousleft = parseFloat(elements[j - 1].style.left);
top = 0;
previouswidth = parseFloat(elements[j - 1].style.width);
elements[j].style.left = (previousleft + previouswidth) + "px";
elements[j].style.top = 0;
}
//place the remaining rows
for (i = noofdivision; i < noofelements; i++) {
currentid = elements[i - noofdivision].id;
left = parseFloat(elements[i - noofdivision].style.left);
uppertop = parseFloat(elements[i - noofdivision].style.top);
console.log(uppertop)
height = $("#" + currentid).height();
console.log("id" + "=" + currentid + " " + "height" + "=" + ($("#" + currentid).height()));
elements[i].style.left = left + "px";
elements[i].style.top = (uppertop + height) + "px";
}
}
if (canvaswidth >= 1200) {
noofdivision = 5;
singlecontentholderwidth = canvaswidth / noofdivision;
$('.rc-singlecontentholder').css('width', singlecontentholderwidth);
setleftandtop(noofdivision);
} else if (canvaswidth >= 900) {
noofdivision = 4;
singlecontentholderwidth = canvaswidth / noofdivision;
$('.rc-singlecontentholder').css('width', singlecontentholderwidth);
setleftandtop(noofdivision);
} else if (canvaswidth >= 550) {
noofdivision = 3;
singlecontentholderwidth = canvaswidth / noofdivision;
$('.rc-singlecontentholder').css('width', singlecontentholderwidth);
setleftandtop(noofdivision);
} else if (canvaswidth >= 480) {
noofdivision = 2
singlecontentholderwidth = canvaswidth / noofdivision;
$('.rc-singlecontentholder').css('width', singlecontentholderwidth);
setleftandtop(noofdivision);
} else if (canvaswidth < 480) {
noofdivision = 1;
singlecontentholderwidth = canvaswidth / noofdivision;
$('.rc-singlecontentholder').css('width', singlecontentholderwidth);
setleftandtop(noofdivision);
}
});
in chrome the height of the division rc-singlecontentholder keeps changing dont know what is happening please help me. Help would be appreciated.

As a rule of thumb you should always provide a standalone example/snippet/jsfiddle, so it is easy for others to figure out exactly what your problem is. In your code the markup(HTML) is missing and several of your variables are not defined. However I will try to give you a push in the right direction from the information you have provided.
I deduced that you want to determine the amount of images your canvas can fit from an element with class 'rc-containerwidth'. The first thing I want to address is that if you iterate from
var j = 0
you can just use
elements[j]
but this is just a minor esthetic.
I am assuming that you have classes called 'rc-singlecontentholder' with actual content, that would make the divs have a width and a height. With this in mind the real problem I see with your code is that the first for loop sets the first n=(noofdivision-1) elements with class 'rc-singlecontentholder' to have top=0.
The second for loop starts at element number n=i-noofdivison. Since it starts at
var i = noofdivison;
this effectively starts at n=0, which means you are looping over the same elements as in the first loop. You then calculate the variable upperTop as the elements top position which will be 0.
upperTop = top = 0;
and finally sets the top of this element as top + height
elements[i].style.top = (upperTop + height) + 'px';
Which will cause the different elements to be positioned at the height of their container. This will happen to the first n=(noofdivison-1) elements and the rest will be placed depending on what your original css for these elements are, which are hard to guess from your question. These factors coupled together is likely what is causing the height in chrome to be different from the height of the divs in firefox. Hope this can point you in the right direction to bandage your code.
There are several improvements that can be done to the code apart from this, but this could be a good task to solve if you are in the stages of learning JavaScript.
If learning JavaScript is not of the essence then I suggest trying to reuse some of the libraries that already exists for image collages, which should be more robust and time-saving than creating your own.
You can check out one alternative called H5P Collage or check out how we used JavaScript to make it at github. Disclosure: I am one of the developers on the H5P team.

Related

Changing Z-index Problems

I am making an old-RPG game on HTML, and I want to make a Function on Javascript
that makes the div of the player get lower than the obstacle, and when the top get higher than the obstacle, the z-index of the player go higher than the obstacle:
var top = parseInt($("#player").css("top"));
var hei = $("#player").height();
var total = top + hei;
var obTop = parseInt($("#obstacle").css("top"));
var obHei = $("#obstacle").height();
var obTotal = obHei + obTop;
if (total < obTotal) {
player.style.zIndex = 1;
$("#obstacle").css('z-index', 2);
} else {
player.style.zIndex = 2;
$("#obstacle").css('z-index', 1);
}
When top's player is higher than the obstacle (Fire)
When top is Lower
You need to compare the Y positions of the objects in question. In this case, When the fire y is lower then the player y, You want to have the player have a higher Z-index than the fire. And Vice Versa, Where when the fire y is higher than the player y, you want the fire to have a higher Z-index than the fire. You could do something like this like this:
//Define player y and fire y
player.style.zIndex = 1;
$("obstacle").css("z-index", 1);
if (playery > firey){
player.style.zIndex = 2;
} else {
$("obstacle").css("z-index", 2);
}
This hasnt been tested as there Is not a runnable example given.

CSS/JS Randomly Position Elements [duplicate]

I want to display random numbers inside a div at random positions without overlapping.
I am able to display random number at random position but its going outside the box and overlapping each other.
Here is my code:
JS Fiddle
var width = $('.container').innerWidth();
var height = $('.container').innerHeight();
(function generate() { // vary size for fun
for (i = 0; i < 15; i++) {
var divsize = 12;
var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
$newdiv = $('<div/>').css({
'width': divsize + 'px',
'height': divsize + 'px'
});
// make position sensitive to size and document's width
var posx = (Math.random() * (width - divsize)).toFixed();
var posy = (Math.random() * (height - divsize)).toFixed();
$newdiv.css({
'position': 'absolute',
'left': posx + 'px',
'top': posy + 'px',
'float': 'left'
}).appendTo('.container').html(Math.floor(Math.random() * 9));
}
})();
How can I do this?
You've got most of it figured out. You just need to think of the .container div as a grid to avoid any overlap or outlying items.
Just check out this fiddle.
Here's what the code looks like:
var tilesize = 18, tilecount = 15;
var gRows = Math.floor($(".container").innerWidth()/tilesize);
var gCols = Math.floor($('.container').innerHeight()/tilesize);
var vals = _.shuffle(_.range(tilecount));
var xpos = _.shuffle(_.range(gRows));
var ypos = _.shuffle(_.range(gCols));
_.each(vals, function(d,i){
var $newdiv = $('<div/>').addClass("tile");
$newdiv.css({
'position':'absolute',
'left':(xpos[i] * tilesize)+'px',
'top':(ypos[i] * tilesize)+'px'
}).appendTo( '.container' ).html(d);
});
PS:I have used underscore in my fiddle to make things easier for me and because I personally hate writing for loops.
If the number of divs you need to create is small enough (i.e. you're not risking that they won't fit) then a simple algorithm is:
pick a random position (x0, y0)-(x1, y1)
check if any previously selected rect overlaps
if none overlaps then add the rect, otherwise loop back and choose another random position
in code
var selected = [];
for (var i=0; i<num_divs; i++) {
while (true) {
var x0 = Math.floor(Math.random() * (width - sz));
var y0 = Math.floor(Math.random() * (height - sz));
var x1 = x0 + sz;
var y1 = y0 + sz;
var i = 0;
while (i < selected.length &&
(x0 >= selected[i].x1 ||
y0 >= selected[i].y1 ||
x1 <= selected[i].x0 ||
y1 <= selected[i].y0)) {
i++;
}
if (i == selected.length) {
// Spot is safe, add it to the selection
selected.push({x0:x0, y0:y0, x1:x1, y1:y1});
break;
}
// The choice collided with a previously added div
// just remain in the loop so a new attempt is done
}
}
In case the elements are many and it's possible to place n-1 of them so that there's no position where to put n-th element then things are a lot more complex.
For the solution of the 1-dimensional version of this problem see this answer.
You can add to array position of each number. And then when ou generate new position for digit you should check if posx posy in array, if false place number there, if true generate new posx and posy

Image slider is choppy

I have put together a plain javascript/css image slider, started out as just a learning exercise but am now looking to apply it in the real world. The problem is that the animation is choppy on my desktop (which is a v. high spec gaming rig) - and even worse on a mobile (to the degree it's not really an animation anymore)
You can see it in action here:
www.chrishowie.co.uk/sands/
jsfiddle isolates much of the pertinent code - it's not a "this doesn't work" issue, so hopefully the fiddle gives enough to help optimize it.
http://jsfiddle.net/9aozrxy8/5/
In summary: I have a DIV with 4 images in a row, each image is 100% the width of the page. I use javascript to translateX (I have tried translate3d as heard this uses GPU, but didnt make much diff) and I set CSS transitions to ease-in the transform.
I also thought that potentially I am just trying to do too much on this site - but then I look at some other sites doing a heck of a lot more and it's smooth as silk. So I guess I'm missing something.
function slideRight() {
if (sliding) {
return false
};
window.sliding = true;
el = document.getElementById("slider");
cst = getComputedStyle(el);
transformst = cst.transform || cst.webkitTransform || cst.mozTransform;
widthst = cst.width;
widthst = widthst.replace("px", ""); // computed width of slider (7680px)
slidewidth = widthst / 4;
transformst = transformst.replace("matrix(", "");
transformst = transformst.replace(")", "");
transformst = transformst.split(",");
transformst = transformst[4]; // returns current transform in px without unit (px)
if (!transformst) {
transformst = 0;
}
var activebtn = "sldr" + Math.round((Number(transformst) / (-1 * slidewidth)));
document.getElementById(activebtn).classList.remove("sliderbuttonactive");
if (activebtn != "sldr3") {
document.getElementById("slider" + Math.round((2 + Number(transformst) / (-1 * slidewidth)))).style.visibility = "visible";
document.getElementById("slider" + Math.round((2 + Number(transformst) / (-1 * slidewidth)))).style.display = "initial";
document.getElementById("slider").style.transform = "translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("slider").style.transform = "-webkit-translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("slider").style.transform = "-moz-translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("slider").style.transform = "-ms-translate3d(" + 25 * ((Number(transformst) / (slidewidth)) - 1) + "%, 0, 0)";
document.getElementById("leftslidebtn").style.visibility = "visible";
document.getElementById("leftslidebtn").style.display = "block";
}
activebtn = activebtn.replace("sldr", "");
activebtn = "sldr" + (1 + Number(activebtn));
document.getElementById(activebtn).classList.add("sliderbuttonactive");
if (Number(activebtn.replace("sldr", "")) == 3) {
document.getElementById("rightslidebtn").style.visibility = "hidden";
document.getElementById("rightslidebtn").style.display = "none";
}
setTimeout(function () {
window.sliding = false
}, 2000);
}
update: still not resolved but on mobile I have made it usable by reducing the image size for small screens and also not displaying images that are off-screen. Not perfectly smooth but getting there.
Thanks a lot,
C
Like Jeremy mentioned, that the "transition" in your JSFiddle caused the problem, it's also causing it on your website.
In your "Main.css" in line 221. Remove the "transition: top ease 2s;" from class .slide
Everything works fine then on Win8.1/Google Chrome/i7

Generate numbers in side div at random position without overlapping

I want to display random numbers inside a div at random positions without overlapping.
I am able to display random number at random position but its going outside the box and overlapping each other.
Here is my code:
JS Fiddle
var width = $('.container').innerWidth();
var height = $('.container').innerHeight();
(function generate() { // vary size for fun
for (i = 0; i < 15; i++) {
var divsize = 12;
var color = '#' + Math.round(0xffffff * Math.random()).toString(16);
$newdiv = $('<div/>').css({
'width': divsize + 'px',
'height': divsize + 'px'
});
// make position sensitive to size and document's width
var posx = (Math.random() * (width - divsize)).toFixed();
var posy = (Math.random() * (height - divsize)).toFixed();
$newdiv.css({
'position': 'absolute',
'left': posx + 'px',
'top': posy + 'px',
'float': 'left'
}).appendTo('.container').html(Math.floor(Math.random() * 9));
}
})();
How can I do this?
You've got most of it figured out. You just need to think of the .container div as a grid to avoid any overlap or outlying items.
Just check out this fiddle.
Here's what the code looks like:
var tilesize = 18, tilecount = 15;
var gRows = Math.floor($(".container").innerWidth()/tilesize);
var gCols = Math.floor($('.container').innerHeight()/tilesize);
var vals = _.shuffle(_.range(tilecount));
var xpos = _.shuffle(_.range(gRows));
var ypos = _.shuffle(_.range(gCols));
_.each(vals, function(d,i){
var $newdiv = $('<div/>').addClass("tile");
$newdiv.css({
'position':'absolute',
'left':(xpos[i] * tilesize)+'px',
'top':(ypos[i] * tilesize)+'px'
}).appendTo( '.container' ).html(d);
});
PS:I have used underscore in my fiddle to make things easier for me and because I personally hate writing for loops.
If the number of divs you need to create is small enough (i.e. you're not risking that they won't fit) then a simple algorithm is:
pick a random position (x0, y0)-(x1, y1)
check if any previously selected rect overlaps
if none overlaps then add the rect, otherwise loop back and choose another random position
in code
var selected = [];
for (var i=0; i<num_divs; i++) {
while (true) {
var x0 = Math.floor(Math.random() * (width - sz));
var y0 = Math.floor(Math.random() * (height - sz));
var x1 = x0 + sz;
var y1 = y0 + sz;
var i = 0;
while (i < selected.length &&
(x0 >= selected[i].x1 ||
y0 >= selected[i].y1 ||
x1 <= selected[i].x0 ||
y1 <= selected[i].y0)) {
i++;
}
if (i == selected.length) {
// Spot is safe, add it to the selection
selected.push({x0:x0, y0:y0, x1:x1, y1:y1});
break;
}
// The choice collided with a previously added div
// just remain in the loop so a new attempt is done
}
}
In case the elements are many and it's possible to place n-1 of them so that there's no position where to put n-th element then things are a lot more complex.
For the solution of the 1-dimensional version of this problem see this answer.
You can add to array position of each number. And then when ou generate new position for digit you should check if posx posy in array, if false place number there, if true generate new posx and posy

Adjust position of a group of adjacent divs in non-linear fashion

This isn't so much a jQuery question as it is an overall conceptual question.
In my example I can populate a container with divs that have a top value set in a nonlinear fashion.
The top value of each one is calculated based on a formula that takes into account the top position of the one to its left as well as the height of the container (line 33 of fiddle).
//this formula sets the top value for each new child added to the container
//height is 100% of its parent which is 20% of the body
//newOne:last is the most recently added child and will have an initial top value of 10%
parseInt($(this).next().css('top'), 10) / $('#queue').height()) * 75 + (parseInt($('.newOne:last').css('top'), 10) * 2) + '%'
I more of less stumbled upon this by chance and it seems to work 'ok', but if an optimization is obvious to you, please point it out :)
What I'm having trouble coming up with is an elegant formula for how to adjust the children smoothly during a drag event. I'm thinking the top value needs to be adjusted based on some manipulation of the left offset, but after hours of experimenting, I haven't found anything that keeps the original position intact when I start dragging and continues adjusting the values smoothly during my drag. The children should gradually approach a minimum top value of 10% as I drag left (child with left offset of 0 will have a top value of 10%), and gradually move away from that top value back toward their initial position as I drag right.
$('#queue').draggable({
axis: "x",
scroll: false,
drag: function(){
//adjust values of each child
$('.newOne').each(function(){
var percentLeft = $(this).offset().left / $('footer').width() * 100
var thisLeft = parseInt($(this).css('left'), 10) / $(window).width() * 100;
var thisTop = parseInt($(this).css('top'), 10) / $('#queue').height() * 100;
if (percentLeft >= 0){
//top value of each one gradually decreases...
//as it gets closer to an offset value of 0 and minimum top value of 10%
//non-linear attempt but not even close
//$(this).css('top', $(this).css('top', 10 + (thisTop - 10 / thisLeft) + '%'));
//linear step
$(this).css({'top': 8 + (percentLeft/2) + '%'});
}
});
}
});
http://jsfiddle.net/5RRCS/17/
P.S. I know I'm asking a lot here, but hopefully someone is up to the challenge :)
Update:
Stumbled onto exp method and did something like this:
adjustTop = function(offset){
return 100 * (1.0-Math.min(0.98,(0.83 + ( 0.17/ (Math.exp(0.007*offset))) )) ) + '%';
};
$(this).css('top', adjustTop($(this).offset().left) );
Here's a version that I believe does what you are looking for.
The first thing I did was to refactor the top calculation so that both the initialization and the drag handlers would get the same results.
Rather than calculate the positions of the child divs based on their offset to the document, I changed the logic to use position relative to their container.
I also remove z-index as the child divs already being added the parent with the correct stacking order - the left most child is the last element in the container.
Calculating the height of each child depended on whether #queue's current position was to the left or right of its origin.
I also change the iteration logic to behave the same to simplify calculating the current elements starting offset:
$($('.newOne').get().reverse()).each(function (index) {
$(this).css({
'background': 'rgba(255,255,255,.80)',
'top': calcTop($(this), index)
});
});
Code for positioning the child elements:
function calcTop($ele, index) {
var elePositionLeft = $ele.position().left;
var queuePositionLeft = $('#queue').position().left;
var footerWidth = $('footer').width();
var queueHeight = $('#queue').height();
var distanceToTravel = queuePositionLeft < 0 ? elePositionLeft : footerWidth - elePositionLeft;
var percentTraveled = Math.abs(queuePositionLeft) / distanceToTravel;
var thisPercentLeft = (elePositionLeft + queuePositionLeft) / footerWidth;
var queuePercentLeft = queuePositionLeft / footerWidth;
var newTop;
var myStartOffset = (index + 1) * startOffset;
var topTravel = queuePositionLeft < 0 ? -myStartOffset + startOffset : (queueHeight - startOffset);
var linear = false;
if (linear) {
newTop = myStartOffset + (topTravel * percentTraveled);
newTop = newTop > startOffset ? Math.round(newTop) : startOffset;
return newTop;
} else {
if (queuePositionLeft >= 0) {
newTop = myStartOffset + (topTravel * thisPercentLeft * percentTraveled);
newTop = newTop > startOffset ? Math.round(newTop) : startOffset;
} else {
newTop = myStartOffset + (topTravel * (1+thisPercentLeft) * percentTraveled);
newTop = newTop < startOffset ? startOffset : Math.round(newTop);
}
return newTop;
}
}
There was also a minor bug in the reset function - it wasn't setting childCount back to zero:
$('#reset').click(function () {
$('#queue').empty().css('left', 0);
childCount = 0;
});
Demo Fiddle

Categories

Resources