Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a bent gradient?

I'm programming snake with Javascript. For the background of the different body parts I'm using the following gradient generation:

gibGradient: function() {
    var string = "background: linear-gradient(to right, rgba(243,226,199,1) 15%,rgba(193,158,103,1) "+ snake.data.gradientLinks +"%,rgba(182,141,76,1) "+ snake.data.gradientRechts +"%,rgba(233,212,179,1) 90%);";
    if ((snake.data.gradientLinks < 85) && (snake.data.modus == "hochzaehlen")) {
        snake.data.gradientLinks = snake.data.gradientLinks + 5;
        snake.data.gradientRechts = snake.data.gradientRechts + 5;
        if (snake.data.gradientLinks >= 85) {
            snake.data.modus = "runterZaehlen";
        }
    }

    if ((snake.data.gradientLinks > 20) && (snake.data.modus == "runterZaehlen")) {
        snake.data.gradientLinks = snake.data.gradientLinks - 5;
        snake.data.gradientRechts = snake.data.gradientRechts - 5;
        if (snake.data.gradientLinks <= 20) {
            snake.data.modus = "hochzaehlen";
        }
    }
    return string;
},

My problem is that when the snake moves and it changes directions, the gradient needs to be bent to fit in the last body part before the corner ends and the last that follows the straight of the snake.

For Example:

Im using 10x10 px div elements

Example

Now i need the transition when it moves a corner

Anybody got an idea?

like image 909
Snackaholic Avatar asked Dec 03 '14 16:12

Snackaholic


1 Answers

I took the time to write a few utility javascript functions you may find useful. They require the use of the jQuery library however. The best way to create bent gradients is to use offset radial gradients. This combined with border radius makes for a really nice effect.

Now it is up to you to

  • use the right function at the right times (the naming convention of the functions is sideA_To_sideB so rightToUp means going right will eventually find sideA and going up will eventually find sideB - sides being the head or the tail)
  • make it cross browser (if you are into that sort of thing)
  • rounding the head and tail would be a nice touch (ideally this rounding would only occur on vertical and horizontal parts)

Feel free to change the size variable to suit your needs.

EDIT - based on the image you just added I created this : jsfiddle http://jsfiddle.net/Lbydhhkh/. This was done using rotated linear gradients. I still think using my original approach looks better and makes more sense. This should be enough to send you in the right direction though. The pseudocode can still be used for this new code.

var size = 40;

function aToB(gradient) {
    return $("<div>").css({
        width: size,
        height: size,
        background: gradient,
        position: "absolute"
    });
}

function radialOut(x, y, corner) {
    var css = {};
    css["border-" + corner + "-radius"] = size / 2;
    return aToB([
        "radial-gradient(",
    size,
        "px at ",
    x,
        "px ",
    y,
        "px, red, blue)"].join("")).css(css);
}

function radialIn(x, y, corner) {
    var css = {};
    css["border-" + corner + "-radius"] = size / 2;
    return aToB([
        "radial-gradient(",
    size,
        "px at ",
    x,
        "px ",
    y,
        "px, blue, red)"].join("")).css(css);
}

function downToUp() {
    return aToB("linear-gradient(to left, red, blue)");
}

function rightToLeft() {
    return aToB("linear-gradient(to bottom, red, blue)");
}

function upToDown() {
    return aToB("linear-gradient(to right, red, blue)");
}

function leftToRight() {
    return aToB("linear-gradient(to top, red, blue)");
}

function upToRight() {
    return radialIn(size, 0, "bottom-left");
}

function leftToUp() {
    return radialIn(0, 0, "bottom-right");
}

function downToLeft() {
    return radialIn(0, size, "top-right");
}

function rightToDown() {
    return radialIn(size, size, "top-left");
}

function rightToUp() {
    return radialOut(size, 0, "bottom-left");
}

function upToLeft() {
    return radialOut(0, 0, "bottom-right");
}

function leftToDown() {
    return radialOut(0, size, "top-right");
}

function downToRight() {
    return radialOut(size, size, "top-left");
}

$(function () {
    //inner
    $("body").append(upToDown().css({
        top: size,
        left: 0
    })).append(upToRight().css({
        top: size * 2,
        left: 0
    })).append(leftToRight().css({
        top: size * 2,
        left: size
    })).append(leftToUp().css({
        top: size * 2,
        left: size * 2
    })).append(downToUp().css({
        top: size,
        left: size * 2
    })).append(downToLeft().css({
        top: 0,
        left: size * 2
    })).append(rightToLeft().css({
        top: 0,
        left: size
    })).append(rightToDown().css({
        top: 0,
        left: 0
    }));

    //outer
    $("body").append(leftToDown().css({
        top: 0,
        left: size * 5
    })).append(upToDown().css({
        top: size,
        left: size * 5
    })).append(upToLeft().css({
        top: size * 2,
        left: size * 5
    })).append(rightToLeft().css({
        top: size * 2,
        left: size * 4
    })).append(rightToUp().css({
        top: size * 2,
        left: size * 3
    })).append(downToUp().css({
        top: size * 1,
        left: size * 3
    })).append(downToRight().css({
        top: 0,
        left: size * 3
    })).append(leftToRight().css({
        top: 0,
        left: size * 4
    }));
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Also here is some pseudocode to help you call the appropriate functions

while(nextPart()) { //while there are more parts to process
    var prev = getPrev(), //returns null or previous part
        curr = getCurrent(), //returns current part
        next = getNext(), //returns null or next part
        a, b, part = [];

    //get the direction towards the tail
    if(prev) a = curr.getDirectionTo(prev); //returns "up", "right", "down", or "left"
    else a = tail.getOppositeDirection(); //returns "up", "right", "down", or "left"

    //get the direction towards the head
    if(next) b = curr.getDirectionTo(next);
    else b = head.getDirection(); //returns "up", "right", "down", or "left"

    b = upperCaseFirstLetter(b);

    if(!prev) part.push("tail"); //is this a tail?
    if(!next) part.push("head"); //is this a head?

    //the following line of code calls a function with the form "aToB"
    //the variable part does not do anything yet but it can help the called  
    //function determine if this part is a head, tail, or both for rounding
    var domElement = window[a + "To" + b](part); 
    domElement.css(curr.position()); //properly position the element
    $("#container").append(domElement); //add the element to the container
}
like image 73
Logan Murphy Avatar answered Oct 23 '22 19:10

Logan Murphy