угловой градиент ручки jquery


Есть ли способ добавить угловой градиент к плагину jQuery knob, чтобы он начинался с одного цвета и по дуге переходил в другой?

2 6

2 ответа:

Я искал решение в интернете, но никто никогда не пробовал это или не публиковал решение. Наконец, я публикую вопрос и ответ. Если у кого-то есть лучшее решение, Пожалуйста, поделитесь с нами.

Во время инициализации я переопределил метод draw и проверил атрибут shaded= "true". Если он есть, то образуется градиент, начиная с белого и двигаясь в направлении fgColor. Чтобы выбрать начальный цвет, отличный от белого, задайте атрибут shadeColor="#(color hex code)".

<input class="knob" value="95" autocomplete="off" data-readOnly=true data-fgColor="#FF0000" data-bgColor="transparent" shaded="1" shadeColor="#00FF00"/>
<script>
    $(function(){
        $('.knob').knob({
            draw : function () {
                var a = this.angle(this.cv)  // Angle
                , sa = this.startAngle          // Previous start angle
                , sat = this.startAngle         // Start angle
                , ea                            // Previous end angle
                , eat = sat + a                 // End angle
                , r = 1;

                this.g.lineWidth = this.lineWidth;

                if(this.$.attr('shaded')){
                    var color1 = r ? this.o.fgColor : this.fgColor;
                    var color2 = this.$.attr('shadeColor') ? this.$.attr('shadeColor') : '#ffffff';
                    var grad = getGradient(color2, color1);

                    var saDeg = parseInt((sa * 180 / Math.PI) % 360);
                    var eatDeg = parseInt((eat * 180 / Math.PI) % 360);

                    for(var angle = saDeg;(angle % 360) != eatDeg;angle++){
                        sat = angle * (Math.PI / 180);
                        eat = (angle + 2) * (Math.PI / 180);

                        if(grad.color2[0] != grad.color1[0] && (angle + 1) % grad.steps[0] == 0){
                            grad.color1[0] += grad.adder[0];
                        }
                        if(grad.color2[1] != grad.color1[1] && (angle + 1) % grad.steps[1] == 0){
                            grad.color1[1] += grad.adder[1];
                        }
                        if(grad.color2[2] != grad.color1[2] && (angle + 1) % grad.steps[2] == 0){
                            grad.color1[2] += grad.adder[2];
                        }

                        color = '#' + toHex(grad.color1[0]) + toHex(grad.color1[1]) + toHex(grad.color1[2]);

                        this.g.beginPath();
                        this.g.strokeStyle = color;
                        this.g.arc(this.xy, this.xy, this.radius, sat, eat, false);
                        this.g.stroke();
                    }
                } else {
                    this.g.beginPath();
                    this.g.strokeStyle = r ? this.o.fgColor : this.fgColor ;
                    this.g.arc(this.xy, this.xy, this.radius, sat, eat, false);
                    this.g.stroke();
                }

                return false;
            }
        });
    });

    function getGradient(color1, color2){
        var ret = new Object();

        ret.color1 = new Array();
        ret.color2 = new Array();
        ret.steps = new Array();
        ret.adder = new Array();

        color1 = color1.replace('#','');
        ret.color1[0] = parseInt(color1.slice(0,2), 16),
        ret.color1[1] = parseInt(color1.slice(2,4), 16),
        ret.color1[2] = parseInt(color1.slice(4,6), 16);

        color2 = color2.replace('#','');
        ret.color2[0] = parseInt(color2.slice(0,2), 16),
        ret.color2[1] = parseInt(color2.slice(2,4), 16),
        ret.color2[2] = parseInt(color2.slice(4,6), 16);

        ret.steps[0] = (ret.color1[0] == ret.color2[0])? 0 : parseInt(360 / Math.abs(ret.color1[0] - ret.color2[0])),
        ret.steps[1] = (ret.color1[1] == ret.color2[1])? 0 : parseInt(360 / Math.abs(ret.color1[1] - ret.color2[1])),
        ret.steps[2] = (ret.color1[2] == ret.color2[2])? 0 : parseInt(360 / Math.abs(ret.color1[2] - ret.color2[2])),

        ret.adder[0] = (ret.color1[0] > ret.color2[0])? -1 : 1;
        ret.adder[1] = (ret.color1[1] > ret.color2[1])? -1 : 1;
        ret.adder[2] = (ret.color1[2] > ret.color2[2])? -1 : 1;

        return ret;
    }

    function toHex(number){
        number = number.toString(16);
        if(number.length < 2){
            number = '0' + number;
        }
        return number;
    }
</script>

Это рисует отдельную дугу для каждого градуса (с углом дуги 2 градуса вместо одного ради плавности). Цвета дуг проходят через переход от fgColor к shadeColor.

Эффект смешивания цветов похож на смешивание красок, а не на смешивание света, поэтому, если вы начнете с зеленого и перейдете к красному, вы не получите желтый оттенок в центре. Это будет выглядеть круто с эффектом смешивания света, но не знаю, как это сделать точно. Кроме того, это не хорошо оптимизированный код, это просто решение. Огромный простор для совершенствования..

Отлично, именно то, что мне было нужно! Я также добавил опцию "курсор", потому что это была единственная вещь, которая еще не работала.

var drawGradient = function () {

    var a = this.angle(this.cv)  // Angle
        , sa = this.startAngle          // Previous start angle
        , sat = this.startAngle         // Start angle
        , eat = sat + a                 // End angle
        , r = 1;

    this.g.lineCap = this.lineCap;
    this.g.lineWidth = this.lineWidth;

    if (this.o.bgColor !== "none") {
        this.g.beginPath();
        this.g.strokeStyle = this.o.bgColor;
        this.g.arc(this.xy, this.xy, this.radius, this.endAngle - 0.00001, this.startAngle + 0.00001, true);
        this.g.stroke();
    }

    if (this.$.attr('shaded')) {
        var color1 = r ? this.o.fgColor : this.fgColor;
        var color2 = this.$.attr('shadeColor') ? this.$.attr('shadeColor') : '#ffffff';
        var grad = getGradient(color2, color1);

        var saDeg = parseInt((sa * 180 / Math.PI) % 360);
        var eatDeg = parseInt((eat * 180 / Math.PI));

        var normalizedAngle = 0
        var normalizedEatAngle = eatDeg - saDeg;

        if(this.o.cursor == true) {
            var size = 40;
        } else if(this.o.cursor != false) {
            var size = this.o.cursor;
            this.o.cursor = true;
        }

        if(this.o.cursor) {
            if(normalizedEatAngle <= size) {
                normalizedEatAngle = size;
            }
        }
        for (var angle = saDeg; normalizedAngle < normalizedEatAngle; angle++, normalizedAngle++) {

            sat = angle * (Math.PI / 180);
            eat = (angle + 2) * (Math.PI / 180);

            if (grad.color2[0] != grad.color1[0] && (angle + 1) % grad.steps[0] == 0) {
                grad.color1[0] += grad.adder[0];
            }
            if (grad.color2[1] != grad.color1[1] && (angle + 1) % grad.steps[1] == 0) {
                grad.color1[1] += grad.adder[1];
            }
            if (grad.color2[2] != grad.color1[2] && (angle + 1) % grad.steps[2] == 0) {
                grad.color1[2] += grad.adder[2];
            }


            if(!this.o.cursor || (normalizedAngle + size) > normalizedEatAngle) {
                color = '#' + toHex(grad.color1[0]) + toHex(grad.color1[1]) + toHex(grad.color1[2]);
                this.g.beginPath();
                this.g.strokeStyle = color;
                this.g.arc(this.xy, this.xy, this.radius, sat, eat, false);
                this.g.stroke();
            }
        }
    } else {
        this.g.beginPath();
        this.g.strokeStyle = r ? this.o.fgColor : this.fgColor;
        this.g.arc(this.xy, this.xy, this.radius, sat, eat, false);
        this.g.stroke();
    }

    return false;
};