HTML5 canvas – Custom brush (BezierCurveBrush)

By | June 7, 2014
0
0



I hope that you still remember when we did our first Paint program with HTML5. Today I have decided to enhance it with adding new additional brush to it. This brush will use ‘bezierCurveTo’ function. In result we will have interesting effect, just check out it!

Step 1. HTML

Here are html code of our enhanced Paint:

index.html

<!DOCTYPE html>
<html lang="en" >
    <head>
        <meta charset="utf-8" />
        <title>HTML5 canvas - Custom brush (BezierCurveBrush) for your paing program | Script Tutorials</title>
        <link href="css/main.css" rel="stylesheet" type="text/css" />

        <script src="js/jquery-1.5.2.min.js"></script>
        <script src="js/script.js"></script>
    </head>
    <body>
        <header>
            <h2>HTML5 canvas - Custom brush (BezierCurveBrush) for your paing program</h2>
            <a href="http://www.script-tutorials.com/html5-canvas-custom-brush1/" class="stuts">Back to original tutorial on <span>Script Tutorials</span></a>
        </header>
        <div class="container">
            <div class="column1">
                <canvas id="color" width="500" height="128"></canvas>
            </div>
            <div class="column2">
                <div>Preview:</div>
                <div id="preview"></div>
                <div id="pick"></div>
            </div>
            <div></div>
        </div>
        <canvas id="panel" width="1000" height="600"></canvas>
    </body>
</html>

Step 2. CSS

Here are used CSS styles

css/main.css

/* page layout styles */
*{
    margin:0;
    padding:0;
}
body {
    background-color:#eee;
    color:#fff;
    font:14px/1.3 Arial,sans-serif;
}
header {
    background-color:#212121;
    box-shadow: 0 -1px 2px #111111;
    display:block;
    height:70px;
    position:relative;
    width:100%;
    z-index:100;
}
header h2{
    font-size:22px;
    font-weight:normal;
    left:50%;
    margin-left:-400px;
    padding:22px 0;
    position:absolute;
    width:540px;
}
header a.stuts,a.stuts:visited{
    border:none;
    text-decoration:none;
    color:#fcfcfc;
    font-size:14px;
    left:50%;
    line-height:31px;
    margin:23px 0 0 110px;
    position:absolute;
    top:0;
}
header .stuts span {
    font-size:22px;
    font-weight:bold;
    margin-left:5px;
}
.container {
    color: #000;
    margin: 20px auto;
    overflow: hidden;
    position: relative;
    width: 800px;
}

/* custom styles */
.column1 {
    float:left;
    width:500px;
}
.column2 {
    float:left;
    padding-left:20px;
    width:170px;
}
#panel {
    border:1px #000 solid;
    box-shadow:4px 6px 6px #444444;
    cursor:crosshair;
    display:block;
    margin:0 auto;
    height:600px;
    width:1000px;
}
#color {
    border:1px #000 solid;
    box-shadow:0px 4px 6px #444444;
    cursor:crosshair;
}
.column2 > div {
    margin-bottom:10px;
}
#preview, #pick {
    border:1px #000 solid;
    box-shadow:2px 3px 3px #444444;
    height:40px;
    width:80px;

    border-radius:3px;
    -moz-border-radius:3px;
    -webkit-border-radius:3px;
}

Step 3. JS

js/script.js

var canvas;
var canvasColor;
var ctx;
var ctxColor;
var bMouseDown = false;
var selColorR = 0;
var selColorG = 0;
var selColorB = 0;

var BezierCurveBrush = {
    // inner variables
    iPrevX : 0,
    iPrevY : 0,
    points : null,

    // initialization function
    init: function () { },

    startCurve: function (x, y) {
        this.iPrevX = x;
        this.iPrevY = y;
        this.points = new Array();
    },

    getPoint: function (iLength, a) {
        var index = a.length - iLength, i;
        for (i=index; i< a.length; i++) {
            if (a[i]) {
                return a[i];
            }
        }
    },

    draw: function (x, y) {
        if (Math.abs(this.iPrevX - x) > 5 || Math.abs(this.iPrevY - y) > 5) {
            this.points.push([x, y]);

            // draw main path stroke
            ctx.beginPath();
            ctx.moveTo(this.iPrevX, this.iPrevY);
            ctx.lineTo(x, y);

            ctx.lineWidth = 1;
            ctx.strokeStyle = 'rgba(' + selColorR + ', ' + selColorG + ', ' + selColorB + ', 0.9)';
            ctx.stroke();
            ctx.closePath();

            // draw extra strokes
            ctx.strokeStyle = 'rgba(' + selColorR + ', ' + selColorG + ', ' + selColorB + ', 0.2)';
            ctx.beginPath();
            var iStartPoint = this.getPoint(25, this.points);
            var iFirstPoint = this.getPoint(1, this.points);
            var iSecondPoint = this.getPoint(5, this.points);
            ctx.moveTo(iStartPoint[0],iStartPoint[1]);
            ctx.bezierCurveTo(iFirstPoint[0], iFirstPoint[1], iSecondPoint[0], iSecondPoint[1], x, y);
            ctx.stroke();
            ctx.closePath();

            this.iPrevX = x;
            this.iPrevY = y;
        }
    }
};

$(function(){
    // creating canvas objects
    canvas = document.getElementById('panel');
    ctx = canvas.getContext('2d');

    canvasColor = document.getElementById('color');
    ctxColor = canvasColor.getContext('2d');

    drawGradients(ctxColor);

    BezierCurveBrush.init();

    $('#color').mousemove(function(e) { // mouse move handler
        var canvasOffset = $(canvasColor).offset();
        var canvasX = Math.floor(e.pageX - canvasOffset.left);
        var canvasY = Math.floor(e.pageY - canvasOffset.top);

        var imageData = ctxColor.getImageData(canvasX, canvasY, 1, 1);
        var pixel = imageData.data;

        var pixelColor = 'rgba('+pixel[0]+', '+pixel[1]+', '+pixel[2]+', '+pixel[3]+')';
        $('#preview').css('backgroundColor', pixelColor);
    });

    $('#color').click(function(e) { // mouse click handler
        var canvasOffset = $(canvasColor).offset();
        var canvasX = Math.floor(e.pageX - canvasOffset.left);
        var canvasY = Math.floor(e.pageY - canvasOffset.top);

        var imageData = ctxColor.getImageData(canvasX, canvasY, 1, 1);
        var pixel = imageData.data;

        var pixelColor = 'rgba('+pixel[0]+', '+pixel[1]+', '+pixel[2]+', '+pixel[3]+')';
        $('#pick').css('backgroundColor', pixelColor);

        selColorR = pixel[0];
        selColorG = pixel[1];
        selColorB = pixel[2];
    }); 

    $('#panel').mousedown(function(e) { // mouse down handler
        bMouseDown = true;
        var canvasOffset = $(canvas).offset();
        var canvasX = Math.floor(e.pageX - canvasOffset.left);
        var canvasY = Math.floor(e.pageY - canvasOffset.top);

        BezierCurveBrush.startCurve(canvasX, canvasY, false, false, false, false, false, false, canvasX, canvasY, 0, 0);
    });
    $('#panel').mouseup(function(e) { // mouse up handler
        bMouseDown = false;
    });
    $('#panel').mousemove(function(e) { // mouse move handler
        if (bMouseDown) {
            var canvasOffset = $(canvas).offset();
            var canvasX = Math.floor(e.pageX - canvasOffset.left);
            var canvasY = Math.floor(e.pageY - canvasOffset.top);

            BezierCurveBrush.draw(canvasX, canvasY, false, false, false, false, false, false, canvasX, canvasY, 0, 0);
        }
    });
});

function drawGradients() {
    var grad = ctxColor.createLinearGradient(20, 0, canvasColor.width - 20, 0);
    grad.addColorStop(0, 'red');
    grad.addColorStop(1 / 6, 'orange');
    grad.addColorStop(2 / 6, 'yellow');
    grad.addColorStop(3 / 6, 'green')
    grad.addColorStop(4 / 6, 'aqua');
    grad.addColorStop(5 / 6, 'blue');
    grad.addColorStop(1, 'purple');
    ctxColor.fillStyle=grad;
    ctxColor.fillRect(0, 0, canvasColor.width, canvasColor.height);
}

What I have added – BezierCurveBrush object. This is pretty easy object with own Draw function where we use ‘bezierCurveTo’ function to draw curves between first point (in beginning of drawing) and all next stored points.

Conclusion

Hope that today’s lesson was interesting for you. We made another one nice html5 sample. I will be glad to see your thanks and comments. Good luck!

Leave a Reply

Your email address will not be published. Required fields are marked *