HTML5 canvas – Custom brush #2 (Bubble brush) for your paing program
In our previous tutorial we made BezierCurveBrush. Today I have decided to create new brush for same script. This brush will use ‘arc’ function. In result we will have interesting effect, just check out it!
Here are our demo and downloadable package:
Live Demo
download in package
Ok, download the source files and lets start coding !
Step 1. HTML
This is markup of our result page. Here it is.
index.html
<!DOCTYPE html> <html lang="en" > <head> <meta charset="utf-8" /> <title>HTML5 canvas - Custom brush #2 (Bubble brush) for your paing program | Script Tutorials</title> <link href="css/main.css" rel="stylesheet" type="text/css" /> <script src="http://code.jquery.com/jquery-latest.min.js"></script> <script src="js/script.js"></script> </head> <body> <header> <h2>HTML5 canvas - Custom brush #2</h2> <a href="https://www.script-tutorials.com/html5-canvas-custom-brush2/" 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 style="clear:both;"></div> </div> <canvas id="panel" width="1000" height="600"></canvas> </body> </html>
Step 2. CSS
Here are all stylesheets
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 { background-color:rgb(0, 195, 135); 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 = 195; var selColorB = 135; var BubbleBrush = { // inner variables iPrevX : 0, iPrevY : 0, // initialization function init: function () { ctx.globalCompositeOperation = 'source-over'; //'lighter' is nice too ctx.lineWidth = 1; ctx.strokeStyle = 'rgba(0, 0, 0, 0.2)'; ctx.lineWidth = 2; }, startCurve: function (x, y) { this.iPrevX = x; this.iPrevY = y; ctx.fillStyle = 'rgba(' + selColorR + ', ' + selColorG + ', ' + selColorB + ', 0.9)'; }, draw: function (x, y) { var iXAbs = Math.abs(x - this.iPrevX); var iYAbs = Math.abs(y - this.iPrevY); iXAbs = (iXAbs > 30) ? 30 : iXAbs; iYAbs = (iYAbs > 30) ? 30 : iYAbs; if (iXAbs > 10 || iYAbs > 10) { ctx.beginPath(); ctx.arc(this.iPrevX, this.iPrevY, (iXAbs + iYAbs) * 0.5, 0, Math.PI*2, false); ctx.fill(); ctx.stroke(); 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); BubbleBrush.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); BubbleBrush.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); BubbleBrush.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); }
This is combination of two main elements – color picker and drawing board. Today – new brush – with bubble effect.
Live Demo
download in package
Conclusion
Hope that today’s lesson was interesting for you as usual. We made another one nice html5 sample. I will be glad to see your thanks and comments. Good luck!
Could You explain why are You calling
BubbleBrush.draw(canvasX, canvasY, false, false, false, false, false, false, canvasX, canvasY, 0, 0);
instead of
BubbleBrush.draw(canvasX, canvasY); ?
Hi Paul,
Yes, you are right,
Before, I tested with different variables, and, in final version I removed all unnecessary variables and, seems forgot to remove them here. Thanks for your notice.
Hi!
This is really nice! There is any way to let the user choose between different brushes?
Thanks a lot!
Hi Francesc,
This tutorial only demonstrates the brush #2.