JS function - optimize math, in some cases - by 1

I'm still peeing as a web designer, not the best in math, and I'm in trouble when something else is broken. Hope you guys can help.

Quick: I'm using JQuery to make some (dynamic numbers) divs in my header overlap by 30%, filling the full width of the container. My current iteration is being rounded too many times, so my last item is below the rest.

I have X elements filling the full width of my header container. Each element overlaps 30% on each side. In an equation, I can't solve the math without problems. Ensuring pixel accuracy with these numbers turned out to be more difficult. This is what I use to determine the width of each element.

width of element = [container width] / ((.7 * ([# of elements] - 1)) + 1)
left margin of element = [width of element] * .3

      

I make variables that I call extraWidth and extraMargin which are% 1 width and margin respectively. The default element width I'm using is width- (width% 1). For each element, I add extraWidth and extraMargin to trigger the full variables. Whenever the total value of any of these variables exceeds 0.5, that particular element has its width or margin set 1 higher than the default.

So I don't run anymore, here's a JSFiddle with everything you need to see what I mean. It works fine most of the time, but at certain widths I'm 1 pixel too big.

ps

Ran JSFiddle, doesn't work the same as my live sandbox site, so check it out here . I feel like I've included all the necessary bits, but I can't say for sure. On my Chrome, when the window size is 575px (among many others), it messes up.

EDIT

It should be noted that I am making changes to my site without updating this post. I am not removing any features yet, but just creating new / minor changes for the existing ones.

+3


source to share


2 answers


Recursion! Recursion was the most elegant answer (which seems to work in all cases) I could come up with.

Iterating through my jQuery object one element at a time and calculating the width and margin based on the remaining width of the container rather than the entire width of the container makes this much easier to compute.



function circleWidth(circles, containerWidth) {
    var width = containerWidth / ((.7 * (circles.length - 1)) + 1);
    var pxWidth = Math.round(width);
    var margin = width * .3;
    var pxMargin = Math.round(margin);

    $(circles[0]).css({
        'width': pxWidth + "px",
        'margin-left': "-" + pxMargin + "px"
    });

    containerWidth -= (pxWidth - pxMargin);

    if (circles.length > 1) {
        circleWidth(circles.slice(1), containerWidth);
    }
}

function circleSize(circles, containerWidth) {
    var height = Math.ceil(containerWidth / ((.7 * (circles.length - 1)) + 1));

    circles.each(function() {
        $(this).css({
            'height': height + "px"
        });
    });

    circleWidth(circles, containerWidth);

    $(circles[circles.length]).css({
        'margin-left': $(circles[0]).css('margin-left')
    });

    $(circles[0]).css({
        'margin-left': 0
    });
}

      

Here's a fiddle with my final result . I'm sure I still have the optimization, but at least it works for now.

+1


source


You have 2 options:

Calculate pixelMargin

as the next integer. as:

var pixelMargin = Math.ceil(circleMargin);

      



or you can use pixelMargin

%.

The first one worked for me.

0


source







All Articles