Crear Paint con Canvas, HTML5 y jQuery

Crear Paint con Canvas, HTML5 y jQuery

Bueno, esta es mi primera entrada de mi nueva página.
La voy a dedicar a explicar cómo podemos crear un lienzo con CANVAS, HTML5 y jQuery.
Puedes descargarte el archivo completo al final de la entrada.

Demo

Antes que nada, decir que éste era mi proyecto final de jQuery pero mucho más ámplio. Si tengo tiempo subiré el resto del proyecto, pero creo que para empezar, es suficiente.
Cabe destacar que el diseño de este proyecto lo vi por internet hace un tiempo, pero no explicaba la forma de crearlo. Eso si, era un proyecto bastante completo.
Lo que haremos será crear un lienzo en el que podremos pintar con distintos colores y tamaños, escribir con distintas tipografías y la posibilidad de guardar el archivo.
Para que entiendas todo el proceso, sería conveniente que tengas conceptos básicos de HTML, CSS y jQuery.

¡¡Empecemos!!

Primero de todo creamos un nuevo documento HTML5 con sus respectivos links de jQuery y CSS y una etiqueta Canvas:

<!doctype html>
<html lang="es">
<head>
<meta charset="UTF-8">
<title>Paint Canvas</title>
<link href="css/reset.css" rel="stylesheet" style="text/css" />
<link href="css/main3.css" rel="stylesheet" style="text/css" media="screen" />
<script src="http://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
</head>
<body>
    <div id="container">
	<canvas id="canvas"></canvas><!-- /canvas -->
    </div>
</body>
</html>

Ahora crearemos un div con un id llamado config debajo de la etiqueta canvas con las herramientas que vamos a utilizar:

<!doctype html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Paint Canvas</title>
<link href="css/reset.css" rel="stylesheet" style="text/css" />
<link href="css/main3.css" rel="stylesheet" style="text/css" media="screen" />
<script src="http://code.jquery.com/jquery-1.11.1.min.js" type="text/javascript"></script>
<script src="http://code.jquery.com/ui/1.10.4/jquery-ui.js"></script>
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.4/themes/smoothness/jquery-ui.css">
</head>
<body>
	<div id="container">
		<canvas id="canvas"></canvas><!-- /canvas -->
		<div id="config">
			<span class="top">PaintCanvas</span>
			<ul id="config_in">
				<li>
					Herramientas:
					<p>
						<select id="herramientas">
							<option selected="selected">Pincel</option>
							<option>Texto</option>
						</select>
					</p>
				</li>
				<li id="txt">
					Texto:
					<p>
						<input type="text" id="valor_t" placeholder="escribe aqu&iacute; tu texto">
						<select id="texto">
							<option selected="selected">Arial</option>
							<option>Verdana</option>
							<option>Impact</option>
							<option>Comic Sans</option>
						</select>
					</p>
				</li>
				<li>
					tama&ntilde;o: <span id="n_range">5</span>
					<p>
						<input type="range" id="rr" min="1" max="100" value="5"><!-- #rr es el valor -->
					</p>
				</li><!-- tamaño -->
				<li>
					Color: <input id="color" name="color" type="color" value='#000'>
				</li>
				<li>
					Color de fondo: <input id="bg_color" name="bg_color" type="color" value='#fff'>
				</li>
				<li>
					<button id="jpeg">Descargar</button>
				</li>
			</ul>
		</div><!-- /config -->
		<div id="c"></div>
		<div id="bg_c"></div>
	</div>
</body>
</html>

Los dos últimos div són para los colores -> id=»c» (color del pincel y el texto), id=»bg_c» (color del fondo).
Y añadimos los estils css al a etiqueta canvas y al resto del div config en el archivo main3.css que hemos linkado anteriormente:

body {
	font-family: Arial, Verdana, sans-serif;
}
canvas {
	/*background: url(../img/bgcanvas.png) repeat;*/
	position: relative;
	cursor: crosshair;
}
#config {
	background-color: #fff;
	position: absolute;
	width: 200px;
	height: auto;
	top: 0;
	margin-top: 5%;
	margin-left: 3%;
	border-radius: 5px 5px 5px 5px;
	box-shadow: 0px 0px 9px #7a7a7a;
	font-size: 14px;
}
.top {
	background-color: #cecece;
	display: block;
	height: 20px;
	color: #000;
	font-weight: bold;
	padding: 7px;
	border-radius: 5px 5px 0 0;
	cursor: move;
}
#config_in li {
	padding: 10px;
}
#config_in li p {
	text-align: center;
	margin-top: 10px;
}
#config_in li p select {
	width: 100%;
}
#texto {
	width: 100%;
}
#valor_t {
	width: 100%;
	margin-top: -10px;
}

El resultado del div, devería de quedar así:

config

Los estilos css no los vamos a utilizar más.
Ahora toca la parte de jQuery.
Creamos un script antes de la etiqueta de cierre del html o entre la etiqueta head e iniciamos jQuery:

$(document).ready(function(){
//ocultamos txt
		$('#txt').hide();
		//barra draggalge
		$('#config').draggable();
		//creamos el CANVAS
	   var clic=false;
	   var x = "";
	   var y = "";
	   var canvas=document.getElementById("canvas");
	   //ancho y alto de la ventana 100%
	   canvas.width = window.innerWidth;
	   canvas.height = window.innerHeight;
	   var cntx = canvas.getContext("2d");
	   //border de la linea -> redondeado
	   cntx.lineCap = 'round';
	   //barra de tamaños
		$(":input").change(function(){
			$("#n_range").html($("#rr").val());
			var a = $('#n_range').text();
	  		cntx.lineWidth = a;
		});
});

Voy a explicar un poco el código:
Primero de todo ocultamos el li de texto, para no mostrarlo hasta que no seleccionemos la opción de texto en el selector. Lo hacemos así -> $(‘#txt’).hide();.
Para que la barra de herramientas pueda desplazarse por todo el documento, lo que hacemos es seleccionar todo el div y hacerlo draggalbe -> $(‘#config’).draggable();. Es por ello que en el head del documento hemos lincado a jQuery-ui, que es el que nos da esa opción.
Ahora creamos el canvas. Porque aún que hayamos puesto la etiqueta, hay que configurarlo desde aquí.
Creamos 3 variables -> clic con un valor false y X e Y que són las coordenadas del lienzo.
Para el ancho y el alto del canvas debaríamos hacerlo desde aquí, porque en css el resultado no es el mismo.
Ancho -> window.innerWidth.
Alto -> window.innerHeight.
Lo que hemos hecho aquí, es darle el ancho y el alto completos de toda la pantalla. Si quisiéramos definirle unas medidas ajustadas, es tan fácil como cambiar window.innerHeight por un número -> canvas.width = 400; para el ancho y canvas.height = 200; para el alto.
La variable cntx es lo que será nuestro puntero dentro del lienzo.
Para redondear el puntero lo hacemos así -> cntx.lineCap = ‘round’;. Si no lo creamos, por defecto el puntero se crea en forma cuadrada, pero en este caso no nos interesa.
Para el ancho del puntero o cntx lo que hacemos es coger el valor de la barra de tamaños.
Una vez que lo tenemos, se lo aplicamos al puntero de la siguiente manera -> cntx.lineWidth = a;, que a es la variable que guarda el resultado del tamaño. Si queremos darle un tamaño fijo es tan fácil cómo -> cntx.lineWidth = 20;.
¡Sigamos!
Ahora creamos las funciones para el click:

//si hacemos click
	   $("#canvas").mousedown(function(canvas){
		   clic=true;
		   cntx.save();
		   x = canvas.pageX-this.offsetLeft;
		   y = canvas.pageY-this.offsetTop;
		});

		$(document).mouseup(function(){
		   clic=false;
		});

		$(document).click(function(){
		   clic=false;
		});

Lo que hacemos aquí es decirle que haga una función cuando hagamos click y movamos, otra cuando levantemos el ratón y otra cuando hagamos click en el documento.
Ahora lo que haremos, será decirle que depende de lo que seleccionemos en la etiqueta select con id #herramientas haga una cosa u otra.
Vamos a crear una variable que será el resultado seleccionado:

$( "#herramientas" ).change(function() {
		    var str = "";
		    $( "#herramientas option:selected" ).each(function() {
		      str += $( this ).text();
		    });
			//pincel
		    if (str == 'Pincel') {
				$("#canvas").mousemove(function(canvas){
				   if(clic==true){
				       cntx.beginPath();
				       cntx.moveTo(canvas.pageX-this.offsetLeft,canvas.pageY-this.offsetTop);
				       cntx.lineTo(x, y);
				       cntx.stroke();
				       x = canvas.pageX-this.offsetLeft;
				       y = canvas.pageY-this.offsetTop;
				   }
				});
				$('#txt').hide();
			}
                        //texto que mostrar y tipografías
                        if (str == 'Texto') {
				$('#txt').show();
				//escribimos
				var texto = document.getElementById('valor_t');
				////////////
				$("#canvas").mousedown(function(canvas){
				 var fnt = "";
					$( "#texto option:selected" ).each(function() {
					  fnt += $( this ).text();
					});
				   cntx.font = 'bold ' + $('#n_range').text()+'px' + ' ' + fnt;
				   clic=true;
				   cntx.save();
				   x = canvas.pageX-this.offsetLeft;
				   y = canvas.pageY-this.offsetTop;
				   var a = cntx.fillText($(texto).val(),x,y);
				   var s = $(texto).val("");
				});
			}
}).trigger( "change" );

Bueno, vamos a explicar por partes:
Primero le pedimos que si la variable str es Pincel, que ejecute la función, donde cntx.moveTo(canvas.pageX-this.offsetLeft,canvas.pageY-this.offsetTop); le dice que se mueva donde esté el punto del cursor y cntx.lineTo(x, y); que cree una línea.
En el caso de que str sea «Texto», le pedimos que haga 2 cosas, primero que escriba donde pongamos el puntero del mouse, y con la tipografía seleccionada.
La fuente se crea de esta forma -> cntx.font = ‘bold ‘ + $(‘#n_range’).text()+’px’ + ‘ ‘ + fnt;, donde $(‘#n_range’).text() es el tamaño del texto y fnt es la variable de la tipografía seleccionada.

El siguiente paso es añadir color al asunto.
Primero pondremos color al pincel y al texto de esta forma:

//Añadimos color
		  	var content = $('#color').val(); 
		  	var c = $('#c');
		  	c.html($(content));
		  	$('#color').on('change', function() {
			    cntx.strokeStyle =  (this.value);
			    cntx.fillStyle = (this.value);
			});

La variable content, es el valor del id=»color» y c es el resultado de ese valor. Lo que hacemos, es decirle que si cambia el color seleccionado, que añada ése valor. Por defecto el color es #000 -> negro.
Ahora toca el color de fondo:

//color de fondo del canvas
			$('#canvas').css('background-image','url("img/bgcanvas.png")');
			var content = $('#bg_color').val(); 
		  	var bgc = $('#bg_c');
		  	bgc.html($(content));
		  	$('#bg_color').on('change', function() {
				$('#canvas').css('background-image','none');
				$('#canvas').css('background-color',(this.value));
			});

Primero de todo le ponemos una imágen de fondo al canvas, en este caso un patrón que saqué directamente de photoshop. Después le pedimos el valor del color seleccionado con -> var content = $(‘#bg_color’).val(); y -> var bgc = $(‘#bg_c’); y a bgc que es el div de abajo, le añadimos el resultado de ese valor así -> bgc.html($(content));. Lo último, es como las 2 últimas funciones, le pedimos que si cambia de color, que elimine la imágen -> $(‘#canvas’).css(‘background-image’,’none’); y le añada color al canvas -> $(‘#canvas’).css(‘background-color’,(this.value));.

Por último, no falta la opción de poder descargar el documento:

//creamos la imágen del canvas
			var jpeg = document.getElementById("jpeg");
			jpeg.addEventListener("click",function(){	
			  var dato = canvas.toDataURL("image/jpeg");
			  dato = dato.replace("image/jpeg", "image/octet-stream");
			  document.location.href = dato;	
			},false);

jpeg es el id del botón de descarga. La variable dato crea el lienzo en imagen jpg y le decimos que descargue el documento con -> document.location.href = dato;.

El resultado de todo el archivo jQuery sería este:

$(document).ready(function(){
		//ocultamos txt
		$('#txt').hide();
		//barra draggalge
		$('#config').draggable();
		//creamos el CANVAS
	   var clic=false;
	   var x = "";
	   var y = "";
	   var canvas=document.getElementById("canvas");
	   //ancho y alto de la ventana 100%
	   canvas.width = window.innerWidth;
	   canvas.height = window.innerHeight;
	   var cntx = canvas.getContext("2d");
	   //border de la linea -> redondeado
	   cntx.lineCap = 'round';
	   //barra de tamaños
		$(":input").change(function(){
			$("#n_range").html($("#rr").val());
			var a = $('#n_range').text();
	  		cntx.lineWidth = a;
		});

	   //si hacemos click
	   $("#canvas").mousedown(function(canvas){
		   clic=true;
		   cntx.save();
		   x = canvas.pageX-this.offsetLeft;
		   y = canvas.pageY-this.offsetTop;
		});

		$(document).mouseup(function(){
		   clic=false;
		});

		$(document).click(function(){
		   clic=false;
		});
		//pincel
		//var valor = document.getElementById('herramientas option[value=""]');
		$( "#herramientas" ).change(function() {
		    var str = "";
		    $( "#herramientas option:selected" ).each(function() {
		      str += $( this ).text();
		    });
			//pincel
		    if (str == 'Pincel') {
				$("#canvas").mousemove(function(canvas){
				   if(clic==true){
				       cntx.beginPath();
				       cntx.moveTo(canvas.pageX-this.offsetLeft,canvas.pageY-this.offsetTop);
				       cntx.lineTo(x, y);
				       cntx.stroke();
				       x = canvas.pageX-this.offsetLeft;
				       y = canvas.pageY-this.offsetTop;
				   }
				});
				$('#txt').hide();
			}
			//texto que mostrar y tipografías
			if (str == 'Texto') {
				$('#txt').show();
				//escribimos
				var texto = document.getElementById('valor_t');
				////////////
				$("#canvas").mousedown(function(canvas){
				 var fnt = "";
					$( "#texto option:selected" ).each(function() {
					  fnt += $( this ).text();
					});
				   cntx.font = 'bold ' + $('#n_range').text()+'px' + ' ' + fnt;
				   clic=true;
				   cntx.save();
				   x = canvas.pageX-this.offsetLeft;
				   y = canvas.pageY-this.offsetTop;
				   var a = cntx.fillText($(texto).val(),x,y);
				   var s = $(texto).val("");
				});
			}
		    }).trigger( "change" );

		  	//Añadimos color
		  	var content = $('#color').val(); 
		  	var c = $('#c');
		  	c.html($(content));
		  	$('#color').on('change', function() {
			    cntx.strokeStyle =  (this.value);
			    cntx.fillStyle = (this.value);
			});
			//color de fondo del canvas
			$('#canvas').css('background-image','url("img/bgcanvas.png")');
			var content = $('#bg_color').val(); 
		  	var bgc = $('#bg_c');
		  	bgc.html($(content));
		  	$('#bg_color').on('change', function() {
				$('#canvas').css('background-image','none');
				$('#canvas').css('background-color',(this.value));
			});
			
			//creamos la imágen del canvas
			var jpeg = document.getElementById("jpeg");
			jpeg.addEventListener("click",function(){	
			  var dato = canvas.toDataURL("image/jpeg");
			  dato = dato.replace("image/jpeg", "image/octet-stream");
			  document.location.href = dato;	
			},false);

	});

Bueno, espero que te hayas enterado de todo o como mínimo de lo importante!
De todas formas tienes la posibilidad de descargarte el archivo completo haciendo click en el siguiente botón:

Para cualquier duda deja un comentario o ponte en contacto conmigo 🙂

4 Comentarios
  • dallas cowboys jerseys for women
    Publicado el 03:26h, 16 noviembre Responder

    If only it was as easy to implement some of the solutions as it was to read and nod my head at each of your points.it will be more energetic for me to read your next post also. it will really enhance my knowledge database.our write up is a fine example of your ability in writing .

    • Santi Camp
      Publicado el 13:30h, 16 noviembre Responder

      Thank you very much for your comment. I especially motivated to teach each tutorial step by step.
      If you have any questions about any post please contact me.
      My next post is not a tutorial but you can download a free HTML5 template to do with it whatever you like.

  • Feryhal
    Publicado el 04:17h, 09 mayo Responder

    Iam unable to copy and paste and implent only the code for the input type range plz only give the code for that I have a project and and I only want range and its script onlyyy plz

    • webcamp
      Publicado el 11:56h, 09 mayo Responder

      If I don’t understand bad, you can’t select the color?

      In some browsers don’t work this label and the color needs to be added manually…
      You can use tools like https://color.adobe.com to select the color code.

      Also You can download the entire file and look for the error you need.

      please tell me if this is what you need,

      Thank you 😉

Añadir Comentario