martes, 3 de septiembre de 2013

Canvas desde cero: primeros pasos

El elemento canvas es una gran herramienta para crear juego, animaciones y manipular imágenes, aun así no todos los navegadores soportan esta etiqueta, por tanto, es necesario contar con alternativas para no dejar de lado a los usuarios de dichos navegadores.

En esta primera parte veremos dos de estas alternativas así como algunas particularidades de la etiqueta canvas.

Compatibilidad

En la actualidad los únicos navegador que no cuentan con soporte para el elemento canvas son Internet Explorer 6, 7 y 8; no obstante existen soluciones (polyfills) que emulan su funcionalidad, entre los que se destacan:
  • excanvas: utiliza VML, una tecnología propietaria de Microsoft similar al svg y no necesita de plugins, pero carece de algunos métodos (getImageData, toDataURL...).
  • flashcanvas: utiliza flash (duh), es mas rápido que excanvas (a mi parecer) y soporta mas características, pero hay que comprar una licencia para poder desarrollar aplicaciones de comerciales.

La etiqueta canvas

El elemento canvas cuenta con una etiqueta de apertura y una de cierre, pero a diferencia de otras etiquetas, su contenido solo es visible en navegadores antiguos (ya que estos ignoran las etiquetas desconocidas) lo cual nos permite mostrar un contenido alternativo a los usuarios de dichos navegadores.
<canvas height="150" id="canvas" width="300">
    <!-- contenido a mostrar si el navegador no soporta canvas -->
    <img src="/images/imagen-estatica.jpg" />
</canvas>
Otro hecho a destacar es que sus medidas se declaran mediante los atributos width/height y no a través css. al usar css se escala el elemento, así, si el canvas mide 300x150 y cambiamos sus medidas por 600x300 los pixeles "medirán el doble" y la imagen se verá borrosa.

Por ejemplo, los siguientes cuadros se dibujaron en la mismas posición (10, 10) y tienen las mismas medidas (30x30) pero el canvas de la derecha fue escalado 6x usando css.
Note el borde borroso el la segunda imagen 

Detectar soporte

Antes de empezar a usar el canvas necesitamos saber si el navegador siquiera soporta dicho elemento, para esto:
  1. Creamos un elemento canvas y comprobamos si cuenta con el método getContext
  2. De lo contrario verificamos que exista un Polyfill
if (! document.createElement("canvas").getContext || ! window.G_vmlCanvasManager )
    alert("Actualize su navegador");

Accediendo desde javascript

Para poder acceder al elemento desde javascript hay esperar que el DOM este listo, para esto puedes utilizar la función ready de jQuery o colocar el script justo antes de </body>.

A continuación obtenemos una referencia al contexto de dibujo del canvas utilizando el método getContext:
var canvas = document.getElementById("canvas"),
    ctx    = canvas.getContext("2d");
Ahora si podemos empezar a dibujar:
ctx.fillStyle = "red";
ctx.fillRect(50, 50, 30, 20);
Utiliza un navegador moderno para poder ver el ejemplo

TIPS

Antes de poder acceder al contexto del canvas en IE<9 (usando excanvas/FlashCanvas) debemos inicializarlo, para esto, en lugar de usar el método getContext podemos usar la siguiente función:
function getContext(canvas) {
    if (! canvas.getContext && window.GV_ContextCanvas) {
        G_vmlCanvasManager.init(canvas);
    } else {
        throw new Error("El navegador no soporta el elemento canvas");
    }

    return canvas.getContext("2d");
}

Conclusión

Finalizando esta primera parte tenemos todo listo para empezar a trabajar con el canvas. con suerte ahora podrás mostrar contenido alternativo para usuarios con navegadores antiguos, detectar el soporte del elemento canvas ya sea de forma nativa o mediante un polyfill y obtener el contexto de dibujo.

No te pierdas la siguiente parte en la que veremos el sistema de coordenadas y como dibujar formas básicas.

Si te gusto el tutorias compartelo en twitter o subscribete y te avisare cuando esté disponible la siguiente parte.




viernes, 23 de agosto de 2013

Canvas desde cero


Si llevas tiempo con ganas de aprender a usar el canvas o quieres refrescar tus conocimientos,
no puedes perderte esta serie de tutoriales que arranca el día de hoy, donde no solo se explicara
como usar x función sino que desarrollaremos programas reales donde podrás aplicar lo aprendido.

y quien es usted para decirme que hacer

Soy un tipo al que le gusta la programación, en especial todo lo relacionado con la web (javascript *¬*)
y desde que conocí el elemento canvas quede fascinado con la idea de poder dibujar en navegador.
si bien no soy un experto y aun sigo aprendiendo, ya llevo tiempo trabajando con este elemento
y he aprendido mucho gracias a la comunidad y esta es mi forma de contribuir en algo.
algunos de los trabajos que he hecho:

P.D.: Si ven que me estoy colgando en la actualización del blog no duden en jalarme las orejas en twitter XD.




jueves, 26 de abril de 2012

Creando un blog con django - parte 4

Después de una eternidad sin escribir y casi abandonar el tema de django, hoy por fin retomo el asunto. Hasta el momento tenemos los post clasificado por tags, pero un blog sin comentarios no es nada, así que hoy veremos como crear el formulario de comentarios.

En django existen dos formas de crear un formulario, una es crear cada campo manualmente y la otra es crearlos automáticamente basados en el modelo de datos.

Ya que casi siempre los formulario se usan para agregar/editar una tabla en una BD, y los campos del formulario reflejan los campos de la tabla, seria un desperdicio de tiempo crearlos manualmente.

Dejemos de hablar y empecemos a escribir código, editemos el archivo forms.py en el directorio de nuestra aplicación:
from django.forms import ModelForm #1
from blog.models import Comment #2

class CommentForm(ModelForm): #3
    """Formulario de comentarios"""
    class Meta: #4
        model = Comment #5
        exclude = ("post","deleted") #6

Hora de explicar lo que hemos hecho:
  1. Importamos ModelForm, la base para los formularios basados en modelos de datos.
  2. Importamos el modelo para el que se creará el formulario
  3. Creamos una subclase de ModelForm.
  4. En la clase Meta especificamos como crear el formulario
  5. model: modelo en el que se basa el formulario.
  6. exclude: campos a excluir, en este ejemplo post lo asignamos según el articulo desde el que se envió el comentario y deleted lo decidimos en la pagina de administración si es un comentario insultante. Si son muchos los campos a excluir podemos hacer lo contrario y especificar los que se deben incluir.
    Ahora podemos incluir el formulario en la vista single:
    # Archivo views.py
    from blog.models import Post, Tag, Comment
    from blog.forms import CommentForm
    ...
    # la función recibe el numero capturado
    def single(request, id=0):
        # recuperar post según id
        post = Post.objects.get(id=int(id))
        # Crear formulario
        form = CommentForm()
    
        return render_to_response("single.html", locals())
    
    Para crear el formulario se instancia el objeto adecuado y en la vista se usa esta instancia para mostrar el formulario:
    {# plantilla single.html #}
    {% extends 'base.html' %}
    
    {% block main_content %}
        {% include 'include/article.html' %}
        {# necesitamos crear el tag form #}
        &lt;form action="" method="form"&gt;
            {{ form }}
        &lt;/form&gt;
    {% endblock %}
    
    Con esto veremos el formulario en nuestro blog, lo llenamos y enviamos...
    Wow un error. Django requiere que incluyamos protección contra ataques csrf, este tipo de ataque permite que alguien engañe a un usuario registrado para enviar datos a nuestro sitio usando un formulario en otra pagina web. Afortunadamente django tiene todo lo necesario para protegernos con unas cuantas lineas de código.
    # Archivo views.py
    from blog.models import Post, Tag, Comment
    from blog.forms import CommentForm
    # importamos el decorador
    from django.views.decorators.csrf import csrf_protect
    # importamos render
    from django.shortcuts import render
    
    ...
    # aplicamos el decorador función que recibe datos de formulario
    @csrf_protect
    def single(request, id=0):
        # recuperar post según id
        post = Post.objects.get(id=int(id))
        form = CommentForm()
        
        # usamos render en lugar de render_to_response
        return render(request, "single.html", locals())
    
    Ahora incluimos el tag {% csrf_token %} dentro del formulario en la plantilla single.html. Esto crea un elemento input oculto con un token único que se verifica al enviar datos al servidor, si este no coincide, se produce un error 403 (prohibido) y tenemos una app algo mas segura.

    Ok, ya podemos enviar datos del formulario al servidor, hora debemos validarlos y guardarlos en la BD.
    # Archivo views.py
    @csrf_protect
    def single(request, id=0):
        # recuperar post según id
        post = Post.objects.get(id=int(id))
        # recuperar comentarios de este post
        comments = Comment.objects.filter(post=post)
    
        # Si la petición es POST es porque enviaron el formulario
        if request.method == "POST":
            # Creamos una instancia del modelo Comment asignado el post actual
            comment = Comment(post=post)
            # Creamos una instancia del formulario con los datos recibidos
            form = CommentForm(request.POST, instance=comment)
            
            # Validamos los datos
            if form.is_valid():
                # Guardamos el comentario en la BD
                form.save()
                # Enviamos al usuario de nuevo al post
                return HttpResponseRedirect("/post/{0}".format(slug))
        
        # De lo contrario creamos un formulario vacío
        else:
            form = CommentForm()
        
        return render(request, "single.html", locals())
    
    Podemos notar algunas cosas:
    1. Validamos el formulario con el método is_valid que no definimos. ¿como es esto posible?; Al crear el modelo Comment especificamos el tipo de datos admitidos, el formulario "sabe" que si esto datos no corresponden, el formulario contiene errores.
    2. Para guardar los datos usamos form.save y no comment.save. Esto se debe a que hay datos que no están incluidos en el formulario (post) pero si en la instancia comment y viceversa, por esto pasamos comment al formulario en el momento de crearlo.
    Solo resta mostrar los comentarios, editamos la plantilla single.html:
    {# plantilla single.html #}
    {% extends 'base.html' %}
    
    {% block main_content %}
        {% include 'include/article.html' %}
        {% for comment in comments %}
          &lt;div class="comment"&gt;
              &lt;div class="user"&gt;{{ comment.name }} dijo:&lt;/div&gt;
              &lt;div class="body"&gt;{{ comment.body }}&lt;/div&gt;
              &lt;small&gt;{{ comment.date|date:"d-m-Y" }}&lt;/small&gt;
          &lt;/div&gt;
        {% endfor %}
        {# necesitamos crear el tag form #}
        &lt;form action="" method="form"&gt;
            {{ form }}
        &lt;/form&gt;
    {% endblock %}
    
    Con esto solo falta crear el sitio de administración para agregar post y moderar los comentarios y tendremos un blog terminado. Estén pendientes por la ultima parte de esta serie que seguro saldrá antes que se acabe el mundo este 21 de diciembre XD.

    miércoles, 28 de marzo de 2012

    while (fracaso) { try{do_something} catch(e){ continue; } }


    Después de varios "fracasos" puedo decir con seguridad que la parte difícil de programar no es tener una idea y desarrollarla, no porque sea fácil, sino porque entre entre mas dificultad presente el problema mas nos entusiasmamos y a pesar de todo lo disfrutamos (al menos yo).

    Pero a la hora de "vender" el producto y lo pongo entre comillas ya que no lo digo en el sentido de intercambiarlo por dinero sino hacer que las personas lo usen, recomienden... todo va mal. Por poner ejemplos:

    ConceptMap: una aplicación para crear mapas conceptuales que desde su lanzamiento ha tenido la increíble estadística de 2 personas afiliadas y 1 mapa conceptual creado.

    jsaw5: un juego que permite crear rompecabezas de hasta 100 fichas usando cualquier imagen y compartirlos con amigos usando una url corta, que empezó muy bien pero a medida que pasan los días veo como las estadísticas en analytics van cayendo.

    Y eso que estas aplicaciones son GRATIS, ahora no me imagino lo difícil que debe de ser atraer usuarios que paguen por usar tu programa.

    No es solo la falta de experiencia en marketing y esas cosas, sino que la tarea en sí resulta molesta a diferencia de programar que disfruto aun cuando me saca canas verdes.

    Tal vez no tengo talento para esto, tal vez nunca pueda llegar a crear una aplicación "popular", pero por el momento seguiré intentando.

    Alguien mas se siente de esta forma, algún consejo.

    jueves, 8 de marzo de 2012

    jsaw5: Crea rompecabezas personalizados


    Ya llevo tiempo sin escribir, y es que en estos días han pasado muchas. Ahora que tengo tiempo libre (ya que estoy desempleado) me puse en la tarea de crear un juego en javascript y HTML5: jsaw5.

    Actualización: el demo fue movido a dropbox

    En jsaw5 podrán crear, resolver y compartir rompecabezas personalizados con amigos en twitter y facebook. Espero que lo visiten y den sus opiniones, aun debe tener varios errores pero si esperaba a que fuera "perfecto" 

    En el proceso de creación agregue algunas mejoras a canvas-event-js las cuales espero hacer disponibles en cuanto pueda.

    miércoles, 28 de diciembre de 2011

    Visor de imágenes para xkcd

    Una de mis tiras cómicas favoritas es xkcd, y desde ya hace tiempo quería descargarme todas las tiras para tenerlas en el disco duro. Si han leido xkcd seguro sabran de los textos adicionales que Randall Munroe pone en el atributo title de las imágenes, este texto es complementario a la tira y en muchas ocasiones mas gracioso que la tira misma.

    Así que si descargaba las tiras tenia que hacerlo con todo y titulo. Tuve un tiempo libre esta navidad y me puse a recolectar información de como hacerlo, lo primero era descargar las imágenes y guardar el texto del tooltip en los metadatos de la imagen, para esto me fue de mucha ayuda este articulo donde se explica como hacerlo usando la libreria PIL.

    Lo siguiente era crear un visor de imágenes que mostrara los tooltip, algo complicado y mas teniendo en cuenta que esta es la segunda interfaz gráfica "seria" que hago, pero encontré muy buenos recursos como este libro online sobre tkinter con muy buenos ejemplos, ademas de un script que implementa un tooltip que me cayo de perlas.

    Luego de varias horas de pelearme acomodando los widget (con pack y grid), he aquí el visor de imágenes junto con todas las tiras hasta la fecha (1-995).
    Si bajan el código fuente necesitaran instalar las siguientes librerías:
    • PIL (en Windows y Linux)
    • ImageTk (solo en Linux: python-imaging-tk)
    • Tkinter (solo en Linux)
    Si tienen alguna sugerencia no duden en dejarla en los comentarios, siempre es bueno saber en que mejorar.

    lunes, 26 de diciembre de 2011

    Actualización: canvas-event-js 0.2

    Después de meses sin actualizar, he aquí algunas cosas nuevas que pueden encontrar en canvas-event:
    Ideas que tengo pero no he implementado:
    • Drag-n-Drop live para evitar llamar drag en cada objeto creado, ya que demasiados callback pueden poner lenta las aplicaciones.
    • moveUp, moveDown, toFront, toBack: para mover objetos entre capas (como en PowerPoint). 
    Todo esto lo pueden encontrar en el repositorio de github a donde he movido el proyecto, donde ademas pueden dejar sus sugerencias y reportes de errores, su ayuda es muy importante y siempre bien recibida.

    P.D.: Has creado alguna aplicación usando canvas-event, deja el link en los comentarios (simple curiosidad *¬*)
     
    © 2009 NovatoZ. All Rights Reserved | Powered by Blogger
    Design by psdvibe | Bloggerized By LawnyDesignz