HTML5 Canvas圆形调色板需要自定义尺寸

时间:2015-06-10 14:25:20

标签: javascript html5 canvas palette color-palette

我有静态大小的调色板我需要它变得更小或更大,anybode可以帮助我,我试图找到我可以改变值,坏结果是坏的。这是较短版本,完整版本为:https://github.com/nilium/harmony



/* PALETTE.JS */
function Palette()
{
    var canvas, context, offsetx, offsety, radius = 90,
    count = 1080, oneDivCount = 1 / count, countDiv360 = count / 360, degreesToRadians = Math.PI / 180,
    i, angle, angle_cos, angle_sin, gradient;

    canvas = document.createElement("canvas");
    canvas.width = 250;
    canvas.height = 250;

    offsetx = canvas.width / 2;
    offsety = canvas.height / 2;

    context = canvas.getContext("2d");
    context.lineWidth = 1;

    // http://www.boostworthy.com/blog/?p=226

    for(i = 0; i < count; i++)
    {
        angle = i / countDiv360 * degreesToRadians;
        angle_cos = Math.cos(angle);
        angle_sin = Math.sin(angle);

        context.strokeStyle = "hsl(" + Math.floor( (i * oneDivCount) * 360 ) + ", 100%, 50%)";
        context.beginPath();
        context.moveTo(angle_cos + offsetx, angle_sin + offsety);
        context.lineTo(angle_cos * radius + offsetx, angle_sin * radius + offsety);
        context.stroke();
    }

    gradient = context.createRadialGradient(offsetx, offsetx, 0, offsetx, offsetx, radius);
    gradient.addColorStop(0, 'rgba(255, 255, 255, 1)');
    gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');

    context.fillStyle = gradient;
    context.fillRect(0, 0, canvas.width, canvas.height);

    return canvas;
}



/* COLORSELECTOR.JS */
function ColorSelector( gradient )
{
    this.init( gradient );
}

ColorSelector.prototype =
{
    container: null,

    gradientContainer: null,
    color: [0, 0, 0],

    hueInput: null,
    saturationInput: null,
    luminosityInput: null,

    hue: null,
    hueSelector: null,

    luminosity: null,
    luminositySelector: null,
    luminosityData: null,

    luminosityPosition: null,

    dispatcher: null,
    changeEvent: null,

    areaDelta: 0,

    init: function(gradient)
    {
        /* DEFINES */
        var scope = this, context, hue, hueData;

        this.container =  document.getElementById('container');
        this.gradientContainer =  document.getElementById('gradient-container');
        this.luminosity = document.getElementById('luminosity');
        this.hue = document.getElementById('hue');
        this.hueSelector = document.getElementById('hue-selector');
        this.luminositySelector =  document.getElementById('luminosity-selector');

        /* OTHER ASSIGNS */
        this.hue.width = gradient.width;
        this.hue.height = gradient.height;

        this.hueSelector.style.left = ((this.hue.width - 15) / 2 ) + 'px';
        this.hueSelector.style.top = ((this.hue.height - 15) / 2 ) + 'px';

        this.luminosityPosition = [ (gradient.width - 15), (gradient.height - 15) / 2 ];
        this.luminositySelector.style.left = (this.luminosityPosition[0] - 7) + 'px';
        this.luminositySelector.style.top = (this.luminosityPosition[1] - 7) + 'px';
        

        /* INITS */
        drawSelectorCircles(this.hueSelector.getContext("2d"));

        contextHue = this.hue.getContext("2d");
        contextHue.drawImage(gradient, 0, 0, this.hue.width, this.hue.height);
        hueData = contextHue.getImageData(0, 0, this.hue.width, this.hue.height).data;

        contextLum = this.luminositySelector.getContext("2d");
        contextLum.drawImage(this.hueSelector, 0, 0, this.luminositySelector.width, this.luminositySelector.height);


        /* OTHER */
        this.dispatcher = document.createElement('div'); // this could be better handled...
        this.changeEvent = document.createEvent('Events');
        this.changeEvent.initEvent('change', true, true);

        this.gradientContainer.addEventListener('mousedown', onMouseDown, false);
        
        function drawSelectorCircles(ctx) {
            ctx.lineWidth = 2;
            ctx.strokeStyle = "rgba(0, 0, 0, 0.5)";
            ctx.beginPath();
            ctx.arc(8, 8, 6, 0, Math.PI * 2, true);
            ctx.stroke();
            ctx.strokeStyle = "rgba(256, 256, 256, 0.8)";
            ctx.beginPath();
            ctx.arc(7, 7, 6, 0, Math.PI * 2, true);
            ctx.stroke();   
        }

        function onMouseDown( event )
        {
            window.addEventListener('mousemove', onMouseMove, false);
            window.addEventListener('mouseup', onMouseUp, false);

            update( event.clientX - scope.container.offsetLeft, event.clientY - scope.container.offsetTop, true );
        }

        function onMouseMove( event )
        {
            update( event.clientX - scope.container.offsetLeft, event.clientY - scope.container.offsetTop, false );
        }

        function onMouseUp( event )
        {
            window.removeEventListener('mousemove', onMouseMove, false);
            window.removeEventListener('mouseup', onMouseUp, false);

            update( event.clientX - scope.container.offsetLeft, event.clientY - scope.container.offsetTop, false );
        }
        //

        function updateColorInputs()
        {
            var hsv = [0,0,0];
            var r=scope.color[0], g=scope.color[1], b=scope.color[2];
            var mn, mx, dif, ad, dv, md;
            mn = Math.min(r, g, b);
            mx = Math.max(r, g, b);
            if (r > g && r > b) {
                dif = g - b;
                ad = 0;
            } else if (g > b) {
                dif = b - r;
                ad = 120;
            } else {
                dif = r - g;
                ad = 240;
            }

            md = mx - mn;
            var mdt = 0;
            if (md != 0) {
                mdt = 1.0 / md;
            }

            var mxt = 0;
            if (mx != 0) {
                mxt = 1.0 / mx;
            }


            hsv[0] = 60 * (dif * mdt) + ad;
            if (hsv[0] < 0) {
                hsv[0] = 360 + hsv[0];
            }
            hsv[1] = md * mxt;
            hsv[2] = mx;

            scope.hueInput = Math.floor(hsv[0]);
            scope.saturationInput = Math.floor(hsv[1] * 100);
            scope.luminosityInput = Math.floor(hsv[2] / 2.56);
        }

        function update(x, y, began)
        {
            var dx, dy, d, nx, ny;

            dx = x - 125;
            dy = y - 125;
            d = Math.sqrt( dx * dx + dy * dy );

            if (began) {
                scope.areaDelta = d;
            }

            var pickHue = 0;
            if (scope.areaDelta < 90) {
                pickHue = 1;
            } else if (scope.areaDelta > 100) {
                pickHue = 2;
            }

            if (pickHue == 1)
            {
                if (d > 89.5) {
                    var scale = d / 89.5;
                    dx = Math.floor(dx / scale);
                    dy = Math.floor(dy / scale);

                    x = dx + 125;
                    y = dy + 125;
                    d = 89.5;
                }

                scope.hueSelector.style.left = (x - 7) + 'px';
                scope.hueSelector.style.top = (y - 7) + 'px';
                var index = (x + (y * 250)) * 4;
                scope.updateLuminosity( [ hueData[index], hueData[index + 1], hueData[index + 2] ] );
            }
            else if (pickHue == 2)
            {
                nx = dx / d;
                ny = dy / d;

                scope.luminosityPosition[0] = (nx * 110) + 125;
                scope.luminosityPosition[1] = (ny * 110) + 125;

                scope.luminositySelector.style.left = ( scope.luminosityPosition[0] - 7) + 'px';
                scope.luminositySelector.style.top = ( scope.luminosityPosition[1] - 7) + 'px';
            }

            x = Math.floor(scope.luminosityPosition[0]);
            y = Math.floor(scope.luminosityPosition[1]);

            scope.color[0] = scope.luminosityData[(x + (y * 250)) * 4];
            scope.color[1] = scope.luminosityData[(x + (y * 250)) * 4 + 1];
            scope.color[2] = scope.luminosityData[(x + (y * 250)) * 4 + 2];

            updateColorInputs();

            scope.dispatchEvent( scope.changeEvent );
        }
    },


    //

    show: function()
    {
        this.container.style.visibility = 'visible';
    },

    getColor: function()
    {
        return this.color;
    },

    setColor: function( color )
    {
        // Ok, this is super dirty. The whole class needs some refactoring, again! :/

        var hsb, angle, distance, rgb, degreesToRadians = Math.PI / 180

        this.color = color;

        hsb = RGB2HSB(color[0] / 255, color[1] / 255, color[2] / 255);

        angle = hsb[0] * degreesToRadians;
        distance = (hsb[1] / 100) * 90;

        this.hueSelector.style.left = ( ( Math.cos(angle) * distance + 125 ) - 7 ) + 'px';
        this.hueSelector.style.top = ( ( Math.sin(angle) * distance + 125 ) - 7 ) + 'px';

        rgb = HSB2RGB(hsb[0], hsb[1], 100);
        rgb[0] *= 255; rgb[1] *= 255; rgb[2] *= 255;

        this.updateLuminosity( rgb );

        angle = (hsb[2] / 100) * 360 * degreesToRadians;

        this.luminosityPosition[0] = ( Math.cos(angle) * 110 ) + 125;
        this.luminosityPosition[1] = ( Math.sin(angle) * 110 ) + 125;

        this.luminositySelector.style.left = ( this.luminosityPosition[0] - 7 ) + 'px';
        this.luminositySelector.style.top = ( this.luminosityPosition[1] - 7 ) + 'px';

        this.dispatchEvent( this.changeEvent );
    },

    //

    updateLuminosity: function( color )
    {
        var context, angle, angle_cos, angle_sin, shade, offsetx, offsety,
        inner_radius = 100, outter_radius = 120, i, count = 1080 / 2, oneDivCount = 1 / count, degreesToRadians = Math.PI / 180,
        countDiv360 = (count / 360);

        offsetx = this.luminosity.width / 2;
        offsety = this.luminosity.height / 2;

        context = this.luminosity.getContext("2d");
        context.lineWidth = 3;
        context.clearRect(0, 0, this.luminosity.width, this.luminosity.height);

        for(i = 0; i < count; i++)
        {
            angle = i / countDiv360 * degreesToRadians;
            angle_cos = Math.cos(angle);
            angle_sin = Math.sin(angle);

            shade = 255 - (i * oneDivCount /* / count */) * 255;

            context.strokeStyle = "rgb(" + Math.floor( color[0] - shade ) + "," + Math.floor( color[1] - shade ) + "," + Math.floor( color[2] - shade ) + ")";
            context.beginPath();
            context.moveTo(angle_cos * inner_radius + offsetx, angle_sin * inner_radius + offsety);
            context.lineTo(angle_cos * outter_radius + offsetx, angle_sin * outter_radius + offsety);
            context.stroke();
        }

        this.luminosityData = context.getImageData(0, 0, this.luminosity.width, this.luminosity.height).data;
    },

    //

    addEventListener: function( type, listener, useCapture )
    {
        this.dispatcher.addEventListener(type, listener, useCapture);
    },

    dispatchEvent: function( event )
    {
        this.dispatcher.dispatchEvent(event);
    },

    removeEventListener: function( type, listener, useCapture )
    {
        this.dispatcher.removeEventListener(type, listener, useCapture);
    }
}



/* MAIN.JS */
var BACKGROUND_COLOR = [250, 250, 250];

var container = document.createElement('div');
document.body.appendChild(container);


var canvas = document.getElementById('canvas');
var context = canvas.getContext("2d");
container.appendChild(canvas);


palette = new Palette();
backgroundColorSelector = new ColorSelector(palette);
container.appendChild(backgroundColorSelector.container);


backgroundColorSelector.setColor( BACKGROUND_COLOR );

backgroundColorSelector.addEventListener('change', onBackgroundColorSelectorChange, false);

function onBackgroundColorSelectorChange( event )
{
    BACKGROUND_COLOR = backgroundColorSelector.getColor();
    document.body.style.backgroundColor = 'rgb(' + BACKGROUND_COLOR[0] + ', ' + BACKGROUND_COLOR[1] + ', ' + BACKGROUND_COLOR[2] + ')';
}




/* COLORUTILS.JS */
function HSB2RGB(hue, sat, val)
{
    var red, green, blue,
    i, f, p, q, t;

    if (val == 0)
        return [ 0, 0, 0 ];

    hue *= 0.016666667; // /= 60;
    sat *= 0.01; // /= 100;
    val *= 0.01; // /= 100;

    i = Math.floor(hue);
    f = hue - i;
    p = val * (1 - sat);
    q = val * (1 - (sat * f));
    t = val * (1 - (sat * (1 - f)));

    switch(i)
    {
        case 0: red = val; green = t; blue = p; break;
        case 1: red = q; green = val; blue = p; break;
        case 2: red = p; green = val; blue = t; break;
        case 3: red = p; green = q; blue = val; break;
        case 4: red = t; green = p; blue = val; break;
        case 5: red = val; green = p; blue = q; break;
    }

    return [red, green, blue];
}

function RGB2HSB(red, green, blue)
{
    var x, f, i, hue, sat, val;

    x = Math.min( Math.min( red, green ), blue );
    val = Math.max( Math.max( red, green ), blue );

    if (x==val)
        return [0, 0, val*100];

    f = (red == x) ? green - blue : ((green == x) ? blue - red : red - green);
    i = (red == x) ? 3 : ((green == x) ? 5 : 1);

    hue = Math.floor((i - f / (val - x)) * 60) % 360;
    sat = Math.floor(((val - x) / val) * 100);
    val = Math.floor(val * 100);

    return [hue, sat, val];
}
&#13;
        #container {
            position: absolute;
            left: 0px;
            top: 0px;
            width: 400px;
            height: 250px;
        }

        #gradient-container {
            position: absolute;
            left: 0px;
            top: 0px;
            width: 250px;
            height: 250px;
            cursor: pointer;
        }

        #luminosity {
            position: absolute;
            left: 0px;
            top: 0px;
        }

        #luminosity-selector {
            position: absolute;
        }

        #hue-selector {
            position: absolute;
        }

        #canvas {
            cursror: crosshair;
        }
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id='container'> 
            <div id='gradient-container'>
                <canvas id='hue' width='' height=''></canvas>
                <canvas id='luminosity' width='250' height='250'></canvas> 

                <canvas id='luminosity-selector' width='15' height='15'></canvas>
                <canvas id='hue-selector' width='15' height='15'></canvas>  
            </div>
        </div>

        <canvas id='canvas'></canvas>
&#13;
&#13;
&#13;

0 个答案:

没有答案