Pular navegação

Fazer o aplicativo de desenho da capa

Fazer o aplicativo de desenho da capa

Conforme discussão prévia, a capa ficou assim:

O que nós queremos é que o leitor possa desenhar na capa usando os pontos assim:

No site do livro haverá um aplicativo em Flash ou Javascript que permitirá fazer este desenho e enviar o código fonte do desenho para um amigo, que irá executar o código na capa do livro dele, usando caneta.

O código fonte para o desenho acima é o seguinte, considerando as letras na vertical como colunas e as na horizontal como linhas:

LE - LG, LE - IU, LG - NR, UE - UI, RG - RN, UE - EI, RI - EI

Esse código fonte será armazenado em nosso banco de dados mas não será renderizado para o amigo que recebê-lo de presente. Será um presente surpresa! Só será possível saber depois que for executado. 

Precisamos de alguém que deseje programar este aplicativo simples. O nome e link do programador aparecerá logo abaixo do aplicativo, permitindo assim a divulgação de seu trabalho.

Alguém se habilita?

Conhecimentos relacionados: 
Protótipo funcional

Comentários

#1

Estou codificando um protótipo e logo envio pra vcs!!!

#2

Beleza Thiago! Você é o responsável então. Estamos no aguardo!

#3

Turma tem um protótipo em:

http://www.webisland.com.br/temp/Design_Livre/index.html
 
Deixei um campo pra testar os desenhos, é só inserir as coordenadas (linha/coluna). Tentei seguir as especificações.
 
Ainda tá na versão alpha do beta, mas dá pra testar.
T+
Thiago

#4

Foi feito em HTML5 por questões de compatibilidade com os tablets e tal. Ainda está um pouco crú e a vesão que está disponível é mais pra gerar os desenhos e testar.

O código ficou bem leve, pois não precisei usar nenhuma biblioteca externa, está semi-documentado e vou estruturá-lo melhor pra facilitar a conversação com quem quiser ajudar.

No exemplo acima, o conjunto de letras não estava correto (ou eu não entendi). Tinha a letra U que eu acho que deveria ser V. Além disso não estava padronizado a ordem de entrada das letras, tive que fazer isso, pode ser? Assim:

- Linhas: Caracteres da palavra LIVRE

- Colunas: Caracteres da palavra DESIGN

Sendo assim, o crreto será LI, LN, ES e não GL, NR, SV

O código está sendo implementado pensando na ampliação da grade (não vai ficar amarrado), caso no futuro desejamos ampliar a quantidade de pontos.

O código ainda pode conter alguns bugs (crossbrowsers test,  feedbacks de erros, etc) mas já dá pra ter uma idéia.

Preciso do tipo que construirão as palavras "DESIGN LIVRE".

Preciso também de detalhes quanto a interação. Como pensam em enviar e o que vamos armazenar (no banco) pra eu ir providenciando.

Abraços e

Aguardo feedbacks

#5

Valeu Tiago! Funcionou até aqui no iPad! A fonte do título é essa Lerotica http://openfontlibrary.org/font/lertica O V dela parece um U mesmo, mas consideremos como V. Concordo quanto a linha vir primeiro no código. No aplicativo, senti falta da possibilidade de fazer uma pausa no desenho, levantar a caneta. Caso eu deseje por exemplo fazer dois elementos desconectados visualmente. Acho que a grafia do código ficaria melhor assim: LI-LN, ES-RI onde o traço é uma linha e a vírgula interrompe o desenho. Outra coisa que não descrevi bem nos requisitos é que o desenho na interface web seria feito com o mouse, sem precisar escrever o código fonte. O usuário clica num ponto e uma linha parte dali até o cursor do mouse. Essa linha atualiza de acordo com o movimento do mouse até que seja clicado um novo ponto, fixando a linha e gerando o código. Deve ser possível um voltar última ação ou apagar todo o desenho e começar de novo. O envio do código será bem simples, um email com o código e um link explicando como executá-lo na capa.

#6

Certo Fred,

A pausa no desenho você quer dizer de uma linha pra outra né? A ligação dos pontos pra pessoa ver o desenho montar ao invés de montar no seco, isso ? Acho que uma animaçãozinha ia bem

Quanto a grafia, humanamente fica mais entendível mesmo, vou ver como fazer aqui!

Em relação a interface, então serão duas correto?

Interface A - Permite o usuário desenhar e entrega um código pra ele enviar pra alguém por email (diretamente pela página)

Interface B - Entrega o desenho de acordo com o código recebido. Confirma?

Essa primeira interface na verdade foi mais pra ver se os códigos inseridos serão desenhados corretamente (a página de quem vai receber o código). Vou providenciar a interação com o mouse. 

Vc tá em Curitiba?

#7

Thiago, estou no Rio de Janeiro agora. Daqui uns dias retorno à Europa. 

A pausa que eu digo é se o sujeito quizer desenhar um coração de um lado e um ponto de exclamação do outro, por exemplo. Elementos visuais desconectados, sem linhas. 

A Interface A é isso mesmo. A Interface B não é necessária. O código vem pelo email. Para que esse código seja surpresa não pode haver uma interface como essa que você fez, onde seria possível colar o código e renderizar o desenho. A proposta é justamente não saber qual é o desenho antes de colocar na capa. Perigoso, mas excitante!

Pra interação com o mouse, estou colocando um exemplo que programei muitos anos atrás, quando eu ainda mexia no Flash, pra um exercício de ligar as opções. Só não precisaria do rastro de linhas deixado ali. 

Pré-visualizarAnexoTamanho
ligue_pontas2.swf5.99 KB
ligue_pontas2.fla85.83 KB

#8

O lance é: uma pessoa (eu, você, o Fred, qualquer um) pode desenhar uma capa na interface e mandar para outra pessoa. Mas, para mandar para a pessoa, não dá para mandar a imagem, tem que mandar o código. Assim, quem estiver com o livro em mãos vai "ganhar uma capa", ou seja, vai ganhar um código, que ele só vai saber o que é quando fizer na sua própria capa (por isso, o mistério do que tem na capa acabaria, se a pessoa pudesse "testar" o código em algum lugar. o legal é direcionar para que o código seja testado na capa e se revele ali que capa é. Será que expliquei melhor? rs

Assim, as capas podem ser compartilhadas, mas somente "codificadas", remetendo a metáfora da Caixa Preta que se revela quando a capa é feita :)

#9

OK Fred, a pausa dos pontos ficou claro e já atualizei o código (não esqueça de dar um shift+F5). veja se é isso mesmo. Cola esse exemplo lá:

VE-LE,LE-LS,IE-IS,VI-LI,LI-LG,LG-VG,II-IG,RE-EE,EE-ES,RI-EI,EI-EG,EG-RG

A interface A ainda coloquei o campo apenas pra conferir se o desenho está representando a coordenada. Isso até a interação com o ouse ficar pronta.

Gonzzato, acho que entendi sim. É que na verdade eu misturei as coisas mais pra poder testar mesmo. Assim que a interação estiver redonda, vamos separas as coisas OK?!

Desculpe pedir tantos detalhes, mas é pra não fazer besteira mesmo.

Gonzzato, esse fim de semana estarei em Curitiba, aí tiro mais algumas dúvidas com você, pode ser?!

#10

Ficou muito massa Thiago! É isso mesmo. Se tiver alguma idéia para melhorar o fluxo do aplicativo, pode propor também. Contribuições são bem vindas.

#11

Muitoooo legal!!

Vamos conversar no fds, sim :D

#12

E aí Thiago, alguma novidade?

#13

Olá Turma, como no fim de semana fui pra Pós, tive que dar uma parada pro TCC, mas ja estou de volta no trabalho. O Gonzatto me esclareceu algumas dúvidas. Fiz as modificações para aceitar as interações com o mouse e agora estou ajustando a interação. Postei uma amostra lá pra vocês observarem, mas ainda não está pronta, é só pra testar o desenho. Na amostra que disponibilizei é necessário clicar em cada ponto para traçar a linha. Mas já estou mexendo pra linha seguir o mouse e só quando ele soltar o ponto, formar a linha.

Trabalhar com desenho no HTML5 é um pouco diferente do Flash e por isso está demorando um pouco, é meu primeiro trampo co o Canvas hehe.

Vou acelerar aqui, até por que o livro já saiu, hehe! Parabéns!

#14

Se ficar difícil da linha acompanhar o mouse em tempo real como no Flash que mandei, uma alternativa é aumentar o tamanho do ponto de origem enquanto a linha não está feita. 

Fiz uma capa bem doida. O lance de não poder pausar o desenho me fez pensar bastante sobre o controle que o sistema exerce sobre meu desenho. Até que é uma influência interessante!

V-E,I-S,I-I,V-G,R-G,V-I,I-I,V-S,R-S,E-I,E-S,R-E,V-E,E-I,I-I,V-S,R-I,V-E,E-S,R-I,V-G,I-N,V-N,I-G,L-N,R-N,E-G,I-N,E-N,I-G,L-G,E-N,L-G,L-N,I-G,L-N,L-N,V-N,L-N,V-N,V-N,L-N,L-N,L-N,E-G,E-N,E-N,V-N,I-N,I-N,I-N,I-N,V-N,I-N,L-N,L-N,I-N,V-N,R-N,E-N,E-G,R-G,I-I,I-I,R-G,E-G,R-I,R-I,E-I,E-G,

#15

Fred, tentei jogar esse teu código lá, mas não consegui testa-lo.

#16

Oi Fred, realmente fazendo desenhos sem pausas acabamos seguindo um modelo mental diferente. E fica divertido de desenhar também.

Gonzatto, nao funcionou porque eu tinha desabilitado o desenho a partir do código.

No início da tarde vou substituir a página já podendo desenhar!!

Outra coisa,em qual banco de dados vamos guardar os envios ? E onde hopedaremos a página? Se precisar tenho host disponível.

#17

Galera, dá uma olhada lá!! Arrasta e solta !! O lance ta funcionando, só vou agora melhorar a interação (feedback), undo e clear e disparar o email.

É necessário quem desenha ver o código que vai ser enviado? Posso tirar né ?

Ps. desculpe a demora, tá difícil conciliar o tempo aqui!!!

#18

No exemplo que está lá, o movimento da linha está rígido (quando fica arrastando). Fiz um teste com ele suave, ficou melhor. O que acham?

#19

Nossa, tá demais esse app! Quem desenha pode ver o código só no final, na hora de mandar. Até porque pode querer copiar para si também, etc. Sobre o banco de dados, não saberei ajudar! O Fred está no Interaction para uma palestra, acredito que assim que voltar ele responde.

#20

Muito bom Thiago! Tá quase pronto hein? Um bug que encontrei: quando você só clica no ponto, sem arrastar, a linha é registrada no código, mas não é renderizada no desenho. Creio que deva ser possível desenhar sem arrastar e soltar, o que não é óbvio. 

Seria bem legal se tivéssemos aquele desenho da linha em tempo real, seguindo o mouse como fiz no meu flash. Será que é muito difiícil?

Quando estiver pronto, a gente vai disponibilizar lá o próprio site do livro http://designlivre.faberludens.com.br O banco de dados será muito simples, só guardar a string de código gerada, emails enviados e talz. Isso só servirá pra nós mesmos, não exibiremos estes dados.

#21

O desenho ta em tempo real agora, veja lá. To corrigindo os bugs!!

#22

Ta bem legal :)

tem um bug, que pode ser encarado como uma feature  também, que é o de você poder ligar os mesmos pontos novamente. Quando você faz isso a linha fica mais forte devido a sobreposição.

#23

Thiago, ficou muito massa o lance de ter o desenho em tempo real. Faz toda a diferença. Só ainda sinto falta da possibilidade de marcar os pontos sem arrastar e soltar: clicando primeiro num ponto e depois no outro. 

Senti falta de um jeito de apagar linhas. Acho que funcionaria bem clicar numa linha existente e apagar. Também é importante ter um botão para limpar tudo e começar do zero.

Fiz um fantasminha do Pac-man EE-IE,IE-LS,LS-LG,LG-IN,IN-EN,ES-RS,EI-RI,EG-RG,IS-VS,VS-VG,VG-IG,IG-IS,II-VI

#24

Oi Turma, realmente o arrastar e soltar apenas pode confundir, vou fazer interação pro clique também.

Pra apagar as linhas tinha pensado em um UNDO. O problema que undo é sequencial, clicar na linha ou nos pontos que formam a linha já desenhada para apagá-la dá mais liberdade realmente.

Já apliquei o tipo Lerotica nas letras e assim que terminar essas coreções ja mando pro servidor e aviso vocês.

#25

Maravilha Thiago, estamos no aguardo. Veja também a proporção do grid, que está um pouco quadrada, quando na capa é retangular (vertical maior q  horizontal). 

Acredito que o aplicativo será importante para motivar a venda dos livros impressos. Até agora apenas 8 exemplares foram vendidos. Não que a gente receba algum retorno financeiro com isso, mas acredito que o impacto do livro impresso é maior do que o digital, pela facilidade de leitura. 

#26

Fred, você sugere quais dimensões? considerando que a área de desenho deve caber na tela sem cortar. No modelo ele está 600x600, que tal 450x600 ?

#27

450x600 é praticamente o tamanho do livro prum monitor de 14". Ótimo. 

Vi que você já colocou a fonte Lerotica. Bem mais real agora. 

A interação por clique sem arraste acho que deve haver a possibilidade de levantar a caneta, tipo: primeiro clique > primeiro ponto  > segundo clique > desenha linha e para de desenhar > recomeça. Continuar desenhando do último ponto não me parece fazer sentido nesse caso.

#28

Ah sim Fred, fica melhor mesmo, é que eu não finalizei a interação com o mouse ainda. 

#29

Turma, de uma conferida na interação do desenho agora. Tanto arrastando quanto clicando funciona. Acho que estamos perto agora. Vou corrigir o limpar tmb, vi agora que ele parou de funcionar pq eu mexi em vários pontos do código.

#30

Maravilha Thiago! Só tá faltando poder apagar uma linha e o botão limpar desenho, q vc ainda tá mexendo. 

Daí tem que ver em quais navegadores funciona e já podemos publicar!

#31

Oi turma, desculpe o sumiço. To finalizando o TCC pra apresentar dia 25 e tive que dar uma pequena pausa, pois ainda falta coisa pra caramba. Me de mais alguns dias que entrego ok?!

#32

Tranquilo Thiago! Faz com calma aí.

#33

Galera, to retomando o desenho da capa e queria ver com vocês o seguinte: que tal fazer uma instruçãozinha para quando a pessoa acessar a página, nos exibirmos a ela? estilo lightbox mesmo.

Pensei em ago assim: http://www.webisland.com.br/temp/Design_Livre/instrucao.png

a imagem está aberta pra fireworks caso queiram mexer.

#34

Eu acho que não precisa de instrução Thiago. O aplicativo tá bem óbvio. E depois quem recebe o desenho (o amigo) é que precisa interpretar o código e desenhar na capa. Aí nesse email a gente providencia as instruções.

#35

E aí Thiago? Como é que anda o aplicativo? 

#36

Oi Fred, ta pronto!

Apenas pra apagar o desenho, como eu usei o canvas do HTML sem um recurso auxiliar, é como se fosse uma camada única, então o desenho vai ser apagado por completo ok?! Tem problema ? Estou procurando uma solução

Preciso saber como podemos fazer a publicação.

#37

Vou fazer um limpa no código e publico no mesmo local !

#38

Tranquilo Thiago! Vamos fazer com o apagar tudo. Acho que seria melhor você anexar o código-fonte aqui no comentário do Corais quando estiver pronto, assim fica registrado. 

Pode deixar comigo a implementação server-side!

#39

Fred, antes por favor, olhe a versão final que publiquei hoje. Corrigi os bugs que tinha identificado. Teste o envio e veja se o fluxo do negócio está de acordo.

Já está gravando em banco. Me mande as mudanças que achar necessária!

Aguardo!

#40

Legal Thiago! O aplicativo tá quase pronto. Pra quem não viu, segue a url de novo http://www.webisland.com.br/temp/Design_Livre/index.html 

O único bug que encontrei é depois de enviar o email não consigo voltar. Seria legal poder voltar e enviar o mesmo desenho pra mais amigos. Talvez até seja bacana colocar um lance de separe emails por uma vírgula.

O texto do email, poderia ser: 

Olá!
Nome_user desenhou uma capa do livro Design Livre especialmente pra você. Design Livre é um livro que discute a atitude de design em tempos de co-criação, software livre, crowdfunding, impressão 3D.

Esse é o código do desenho da capa que Nome_user fez pra você:

_código_

Veja como transferir esse código para a capa do seu livro

_ link_

Instituto Faber-Ludens de Design de Interação

www.faberludens.com.br

Gonzatto ou alguém que tenha uma edição impressa ainda sem desenho (a minha já tá desenhada), você pode fazer um tutorial com fotos tipo esse da edição Faça-você-mesmo mostrando como passar o código pro livro impresso? Acho que dá pra colocar inclusive as instruções nessa mesma página.

#41

Certo Fred, já atualizei lá, dê uma conferida e me avise pra eu postar o código.

#42

Beleza Thiago! Tudo certo agora. Pode postar o código-fonte.

#43

Então segue o código dos arquivos usados.

<!-- index.html - Página principal-->

<!doctype html>
<html>
<head>
<!--
#canvas1 = BG (letras)
#canvas2 = pontos
#canvas3 = linhas
-->

  <meta charset="utf-8">
  <title>Design Livre</title>
  <link rel="stylesheet" href="style.css" type="text/css" charset="utf-8" >
  <link rel="stylesheet" href="colorbox.css" type="text/css" charset="utf-8" >
  <!--[if IE]><script type="text/javascript" src="excanvas.compiled.js"></script><![endif]-->

<script src="scripts/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="scripts/jquery.colorbox-min.js" type="text/javascript"></script>
<script src="scripts/script.js" type="text/javascript"></script>
<meta name = "viewport" content = "user-scalable=no, width=device-width">
</head>
<body>
<div id="container">
  <h2>Design Livre - Capa do Livro</h2>
  <div id="button-container">   
<a href="javascript://" id="bt-limpar" class="bt_link">Limpar desenho</a>
<a href="scripts/envia_form.php" id="bt-enviar" class="bt_link">Enviar código por email</a>
  </div>
  <canvas id="canvas"  style="z-index: 1; "></canvas>
  <canvas id="canvas2" style="z-index: 2;"></canvas>
  <canvas id="canvas3" style="z-index: 3;cursor:pointer"></canvas>
  <span id="codigo" style="display:none"></span>
  </div>

</body>
</html>

#44

Folha de Estilo: /* style.css */

body {
   font-family: Arial;
   
}
#container {
    width:610px;
   margin: 0 auto;
    position:relative;
}
#container a {
    color:#4F9FFF;
text-decoration:none;
}
#canvas {
  border:1px #ccc solid;
position:absolute;
font-family:Lerotica, Arial;
   box-shadow: 1px 1px 1px #ccc, -1px -1px 2px #ccc;
  -moz-box-shadow: 1px 1px 1px #ccc, -1px -1px 2px #ccc;
-webkit-box-shadow: 1px 1px 1px #ccc, -1px -1px 2px #ccc;
}
#canvas2, #canvas3 {
   position:absolute;

}
#button-container {
  padding:10px 0;
    margin-bottom:10px;
    width:450px;
}
.input_field {
  padding:4px;
   width:200px;
   margin:0px 5px 0px 0;
  font-size:16px;
    color: #196CCF;
    border:1px #196CCF solid;
margin-bottom:30px;
    background-color:#f8f8f8;

}
label {   
   display: block;
}
.button {
    padding:4px 8px;
   margin:0px 0px 5px 0px;
    font-size:16px;
    color: white;
  background-color:#196CCF;
border:none;
   cursor:pointer;
    border-radius:3px;
-moz-border-radius:3px;
    -webkit-border-radius: 3px;
}
.button:hover {
  background-color:#4F9FFF;
}
small {
   font-size:9px;
color:#666;
}
.bt_link {
   font-size:12px;

}
#bt-limpar {
    background: url(images/ic_delete.png) no-repeat 0 -1px;
    padding-left:20px;

}
a#bt-limpar {
   color:#BBB;
}
a#bt-limpar:hover {
  color:#666;
}
a#bt-enviar {
    background: #DFEEFF url(images/ic_mail.png) no-repeat 4px 4px;
padding:6px 6px 6px 24px;
  float:right;
   font-weight:bold;
  border-radius:3px;
-moz-border-radius:3px;
    -webkit-border-radius: 3px;
}
a#bt-enviar:hover {
  background-color: #9FCBFF;
color:white;
}
p.sucesso {
margin-top:20px;
   color: #196CCF;
   font-size:16px;
    background: url(images/ic_check.png) no-repeat 2px 2px;
    padding-left:22px;
}
p.erro {
  margin-top:20px;
   color: #cc0000;
    font-size:16px;
}
a.link_feedback {
    text-decoration: none;
font-size:11px;
    color:#4F9FFF;
}

#45

Funções Javascript, inlusive do desenho /* scripts/script.js */

jQuery(document).ready(function() {
  // Pré-recarrega a imagem. Se nao usar, é necessário atualizar a página novamente depois do carregamento
  var images = [
  'images/c_0.gif',
    'images/c_1.gif',
    'images/c_2.gif',
    'images/c_3.gif',
    'images/c_4.gif',
    'images/c_5.gif',
    'images/l_1.gif',
    'images/l_2.gif',
    'images/l_3.gif',
    'images/l_4.gif',
    'images/l_5.gif'
  ];

  $(images).each(function() {
var image = $('<img />').attr('src', this);
  });
  // acao do botao enviar
  jQuery('#bt-enviar').colorbox(
     {
          iframe: true,
         width:  "400px",
         height: "260px",
         title:  "Envie por email",
       data: {
          envia: 1
         },
         onLoad: function() {
         cod = jQuery('#codigo').val();
         }
        }
  );
 
  // acao do botao limpar
  jQuery("#bt-limpar").click(function() {
    limpaCanvas(context3);
click = new Array();
   jQuery("#codigo").val('');
  });
  // ÁREA DE DESENHO
  // Parametros de inicializacao
  var letras_linha  = ["D", "E", "S", "I", "G", "N"];
  var letras_coluna = ["" , "L", "I", "V", "R", "E"]; // a coluna deve ter um espaco para nao chocar com a primeira letra da linha   
  var click     = new Array();
  var clickPar  = new Array();
  var num_linha      = letras_linha.length; // numero de linhas
  var num_coluna     = letras_coluna.length; // numero de colunas
  canvas_w     = 450;
  canvas_h       = 600;
  cor_linha      = '#CC0000';
  largura_linha = 2;
  padding_canvas= 10; // espacamento interno de folga da area
  var pontos = new Array();
  var espaco_linha  = parseInt(canvas_h/num_linha);  // espaco entre os pontos na linha
  var espaco_coluna = parseInt(canvas_w/num_coluna); // espaco entre os pontos na coluna
  var deslocamento_left = document.getElementById("container").offsetLeft;
  var deslocamento_top  = document.getElementById("container").offsetTop;
 
  // Configuracao do canvas
  var canvas  = document.getElementById("canvas");
  var canvas2 = document.getElementById("canvas2");
  var canvas3 = document.getElementById("canvas3");
  canvas.width   = canvas_w-padding_canvas*2;
  canvas.height  = canvas_h-padding_canvas*2;
  canvas.style.padding = padding_canvas+'px';
  canvas2.width  = canvas_w;
  canvas2.height = canvas_h;
  canvas3.width  = canvas_w;
  canvas3.height = canvas_h;
  var context  = canvas.getContext('2d');  // Pontos e letras
  var context2 = canvas2.getContext('2d'); // Mouse Over Eventos
  var context3 = canvas3.getContext('2d'); // Click eventos
  context.lineWidth = largura_linha;
  context.strokeStyle = cor_linha;
  function rads(x) { return Math.PI*x/180; }
  // Pontos de ligacao
  var quad = {
  draw: function(x,y) {
      context.fillStyle = '#AAA';
      context.fillRect(x,y,4,4);
     context.closePath();
   }
  }
  // Circulo acionado ao passar o mouse sobre o ponto
  var circ = {
draw: function(x,y,alpha) {
        context2.beginPath();
      context2.fillStyle="rgba(100%,0%,0%,"+alpha+")"
        context2.arc(x,y,10,0,rads(360),false);
        context2.fill();
       context2.closePath();
      }
   }
   // Verifica qual ponto foi clicado, considerando os pontos simplificados. Usado para descobrir a letra correspondente ao ponto
   function qualPonto(x,y,pontos) {
       for(ab=0; ab<pontos.length;ab++) {
          g = pontos[ab];
            if ((g[0]/espaco_coluna==x) && (g[1]/espaco_linha==y)) {
              return ab;
         }
     }
  }
  // Desenha a área de desenho de acordo com a matriz de letras. Atualmente as letras são imagens. O uso de fonte nativa com CSS3 não teve um comportamente ideal.
    function desenhaCanvas(input) {   
       c = 0;
     context.font='normal 30pt Lerotica';
     for (i=0; i<canvas_w; i+=espaco_coluna) {
           img = new Image();
         img.src= "images/c_"+(i/espaco_coluna)+".gif";
         context.drawImage(img,i+2,5);
          for (j=0; j<=canvas_h+espaco_linha; j+=espaco_linha) {  
               if (i==0 && j<canvas_h && j>=num_linha) {
                    img = new Image();
                 img.src= "images/l_"+(j/espaco_linha)+".gif";
                  context.drawImage(img,i,j-15);
                 //context.fillText(letras_coluna[j/espaco_linha],i-2,j);
               }
              if (i!=0 && j!=0) {
                   quad.draw(i, j);
               }
              pontos.push([i, j]);
               //context.fillText(c,j+10,i+12); // usado para debugar os pontos
               c++;
           }
      }
  }
  // Liga os pontos
  function ligaPontos(input) {   
       input = input.toUpperCase();
       input = input.replace(" ","");
     input = input.split(",");
        limpaCanvas(context3);
     context3.beginPath();  
       for (i = 0; i<=input.length-1;i++) {
          input_tmp = input[i].split("-");
         for (j = 0; j<=input_tmp.length-1; j++) {     
             c1 = input_tmp[j].substr(0,1); // pega a primeira letra
            c2 = input_tmp[j].substr(1,1); // pega a segunda  letra
       
           x = letras_coluna.indexOf(c1);
             y = letras_linha.indexOf(c2);
                
            p = pontos[qualPonto(x,y,pontos)];
             if (j==0) context3.moveTo(p[1], p[0]);
             context3.lineTo(p[1]+2, p[0]+2);
             //console.log(c1+""+c2+", - "+qualPonto(x,y,pontos)+" ("+p[0]+" - "+p[1]+")");
           }

     }
     context.stroke();
      context.closePath();
      
   }
 
   function limpaCanvas(c) {
      c.clearRect(0, 0, canvas_w,canvas_h);
  }
  // Usado para capturar a coordenada do mouse na tela.
  captureMouse = function (element) {
       var mouse = {x: 0, y: 0};   
      element.addEventListener('mousemove', function (event) {
        var x, y;
     if (event.pageX || event.pageY) {
       x = event.pageX;
          y = event.pageY;
        } else {
        x = event.clientX + document.body.scrollLeft +
            document.documentElement.scrollLeft;
          y = event.clientY + document.body.scrollTop +
             document.documentElement.scrollTop;
      }       
      x -= element.offsetLeft;
      y -= element.offsetTop;
       mouse.x = x;
      mouse.y = y;
    }, false); 
     return mouse;
};
// Retorna a string de acordo com as coordenadas informadas. Vai concatenando de acordo com o desenho
  function numeroGerado(arr) {
       s = "";
      c = 1;     
       for(i = 0; i<=arr.length-1;i++) {
           conc = "";
           p = pontos[arr[i]];
            if (c % 2==0) { conc="-"; clickPar.push(letras_coluna[(p[1]/espaco_linha)]+""+letras_linha[(p[0]/espaco_coluna)]) } else { conc = ","; }
         s += conc+letras_coluna[(p[1]/espaco_linha)]+""+letras_linha[(p[0]/espaco_coluna)];
          c++;
       }
      return s.substr(1);
    }
  // Abaixo, logo depois de preparar a área de desenho, após o carregamento da página os eventos de mouse começam a serem observados.
    window.onload = function () {
     // Desenha o background
        desenhaCanvas();               
       mouse  = captureMouse(canvas2);
        mouse2 = captureMouse(canvas3);
        var click1 = -1;
       var click2 = -1;
       canvas3.addEventListener('mousemove', function (event) {
            limpaCanvas(context2);
         if ((mouse2.x>deslocamento_left+70) && (mouse2.x<deslocamento_left+canvas_w-60)) {
               mx  = Math.round((mouse2.x-deslocamento_left)/espaco_coluna);
              my  = Math.round((mouse2.y-deslocamento_top)/espaco_linha);
                p   = pontos[qualPonto(mx, my, pontos)];
               if (click1!=-1) {
                  context2.beginPath();
                  context2.strokeStyle = "rgba(50%,50%,50%,0.5)"
                   context2.moveTo(click1[0]+13,click1[1]+13);
                    context2.lineTo(mouse2.x-deslocamento_left,mouse2.y-deslocamento_top);
                 context2.stroke(); 
                   context2.closePath();
                  circ.draw(mouse2.x-deslocamento_left,mouse2.y-deslocamento_top,0.4);
               }
              if ((mouse2.x>=p[0]-5 || mouse2.x<=p[0]+5) && (mouse2.y>=p[1] || mouse2.y<=p[1]) && (mouse2.x>espaco_coluna-10 && mouse2.y>espaco_linha-10)) {
                   circ.draw(p[0]+13,p[1]+13,0.1);
                } else {
                   limpaCanvas(context2);
             }
             
           }
      }, false);
     canvas3.addEventListener('mousedown', function (event) { 
           if (mouse2.x>=espaco_coluna && mouse2.y>=espaco_linha-10) {
              context3.strokeStyle = "rgba(100%,0%,0%,1)"
              context3.beginPath();
              mx  = Math.round((mouse2.x-deslocamento_left)/espaco_coluna);
              my  = Math.round((mouse2.y-deslocamento_top)/espaco_linha);        
               p = pontos[qualPonto(mx, my, pontos)];
             click1 = p;            
               context3.moveTo(p[0]+13,p[1]+13);
              context3.lineTo(p[0]+13,p[1]+13);
              context3.stroke();
                click.push(qualPonto(mx, my, pontos)); 
           }
      });
        canvas3.addEventListener('mouseup', function (event) {
       limpaCanvas(context2);
         mx  = Math.round((mouse2.x-deslocamento_left)/espaco_coluna);
          my  = Math.round((mouse2.y-deslocamento_top)/espaco_linha);
            p = pontos[qualPonto(mx, my, pontos)]; 
          
           if (click1 == p) {                 
               context3.moveTo(p[0]+13,p[1]+13);
              if (click2==-1) {                              
                   context3.lineTo(p[0]+13,p[1]+13);
                  context3.stroke();             
               } else {               
                   c2 = click[click.length-2];
                   c1 = click[click.length-1];                                    
                   context3.lineTo(pontos[c2][0]+13,pontos[c2][1]+13);
                    context3.stroke();                 
                   click1 = -1;
               }
              if (click2==-1) { click2 = p; } else { click2 = -1; }          
           } else {       
               context3.lineTo(p[0]+13,p[1]+13);
              context3.stroke();
             click.push(qualPonto(mx, my, pontos));                 
               click1 = -1;
           }                                  
           jQuery('#codigo').val(numeroGerado(click));
      })         
    };
});

#46

Formulário de envio apresentado ao usuário: /* scripts/envia_form.php */

<!doctype html>
<head>
  <meta charset="UTF-8">
  <title>Design Livre</title>
  <link rel="stylesheet" href="../style.css" type="text/css" charset="utf-8" >
    <script src="jquery-1.7.1.min.js" type="text/javascript"></script>
    <script src="jquery.colorbox-min.js" type="text/javascript"></script>
<script>     
       jQuery(document).ready(function() {
              <?php if (!isset($_GET['codigo'])) { // verifica se voltou depois de enviar?>
             jQuery('#codigo').val(parent.cod);
           <? } ?>
             jQuery("#formulario").submit(function() {
              var emailReg = /^([\w-.][email protected]([\w-]+.)+[\w-]{2,4})?$/;
              if (jQuery("#nome").val()=='') {
                   alert('Ué, e o nome ?');
                 return false;
              }
              if (jQuery('#email').val()=='') {
                  alert('Ué, e o email ?');
                    return false;
              }
              //if(!emailReg.test(jQuery('#email').val())) {
               //  alert('Esse email não é válido!');
               //  return false;
              //}
                if (jQuery("#codigo").val()=='') {
                 alert('Você precisa desenhar a capa');
                   return false;
              }
            });
      });
    </script>
</head>
<body>
     <div>
        <form action="envia.php" method="post" name="form" id="formulario">
              <label for="nome">Seu Nome:</label>
          <input type="text" value="<?php echo isset($_GET['nome']) ? $_GET['nome'] : ''; ?>" name="nome" id="nome" class="input_field" />
           <label for="email">Email que receber&aacute; o c&oacute;digo:<br /><small>separe com , para vários emails</small></label>
          <input type="text" value="" name="email" id="email" class="input_field" />
        
           <input type="hidden" name="codigo" id="codigo" value="<?php echo isset($_GET['codigo']) ? $_GET['codigo'] : ''; ?>" />
           <input type="submit" value="Enviar" id="executa-form" class="button" />
      </<form>
      </div>
</body>
</html>

#47

Submissão do formulário: /* scripts/envia.php /

<!doctype html>
<?php
// Verifica se o email é válido
function check_email($email) {
 
$validation = TRUE;
    if(!
eregi("^[_a-z0-9-]+(.[_a-z0-9-]+)</em>@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,4})$", $email)) {
      
$validation = FALSE;
   }
  return
$validation;
}
/** Configuracao do Banco **/
mysql_connect("localhost","base_dl","******") or die("Não foi possível conectar ao banco!");
mysql_select_db("database_name") or die("Nao foi possível conectar à tabela!");

$erro = "";
$sucesso = "";

if ((
$_POST['nome']!='') && ($_POST['email']!='')  && ($_POST['codigo']!='')) {
$query = "INSERT INTO capas (nome_remetente, email_destino, codigo, data_hora) VALUE ('".$_POST['nome']."', '".$_POST['email']."', '".$_POST['codigo']."', now())";
    if (
mysql_query($query)) {
    
$headers  = 'MIME-Version: 1.0' . "\r\n";
     
$headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
       
$msg  = "Olá! <br >";
     
$msg .= "<b>".$_POST['nome']."</b> desenhou uma capa do livro Design Livre especialmente pra você. Design Livre é um livro que discute a atitude de design em tempos de co-criação, software livre, crowdfunding, impressão 3D.";
       
$msg .= "<p>Esse é o código do desenho da capa que ".$_POST['nome']." fez pra você:</p>";
       
$msg .= "<p style='font-weight:bold; font-size:16px;'>".$_POST['codigo']."</p>";
      
$msg .= "<p>Veja como transferir esse código para a capa do seu livro</p>";
     
$msg .= "<p><a href='#'>[link aqui]</a></p>";
     
$msg .= "<p>Instituto Faber-Ludens de Design de Interação<br /><a href='http://www.faberludens.com.br' target=_blank>www.faberludens.com.br</a></p>";
       
$q = explode(',',$_POST['email']);
     if (
count($q)==0) {
            if (
check_email($_POST['email'])) {
              if (
mail(trim($_POST['email']),"Desenhe na capa do seu livro",$msg, $headers)) {
                  
$sucesso = "Enviamos sua sugestão de capa para: <br /><i>".$_POST['email']."</i>";
             } else {
                  
$erro = "Erro ao enviar email";
              }
          } else {
              
$erro = "Erro ao enviar email. Email inválido!";
         }
      } else {
           foreach(
$q as $m) {
                if (
check_email($m)) {
                 if (
mail(trim($m),"Desenhe na capa do seu livro",$msg, $headers)) {
                     
$sucesso = "Enviamos sua sugestão de capa!";
                 }
              }
         }
      }
  } else {
      
$erro = "Não foi possível enviar a capa";
    }
} else {
$erro = "Erro: verifique se os campos estão preenchidos";
}

?>


<html>
<head>

  <meta charset="utf-8">
  <title>Design Livre - Coverdraw (HTML5)</title>
  <link rel="stylesheet" href="../style.css" type="text/css" charset="utf-8" >
</head>
<body>
<?php
// Tudo OK!
if ($sucesso!='') {
?>

    <p class="sucesso">
        <?php echo $sucesso; ?>
  </p>
<a href="envia_form.php?codigo=<?php echo $_POST['codigo']; ?>&nome=<?php echo $_POST['nome']; ?>" class="link_feedback">voltar e enviar novamente</a><?php
// Deu problema!
} else { ?>

<p class="erro">
   <?php echo $erro; ?><br />
<small><?php echo mysql_error(); ?></small>
  <a href="envia_form.php?codigo=<?php echo $_POST['codigo']; ?>&nome=<?php echo $_POST['nome']; ?>" class="link_feedback">voltar e tentar enviar</a>
   
</p>

<?php } ?>
</body>
</html>

#48

Outras bibliotecas pode ser encontradas em;

jQuery: http://www.jquery.com

Colorbox: http://www.jacklmoore.com/colorbox 

Excanvas (pra "tentar" fazer o canvas do HTML5 funcionar no IE): http://code.google.com/p/explorercanvas/

A estrutura dos diretórios é a seguinte:

- index.html

- colobox.css

- excanvas.compiled.js

- style.css

/images

    - [todas as imagens inclusive ícones]

/scripts

    - envia_form.php

    - envia.php

    - jquery-1.7.1.min.js

    - jquery.colorbox-min.js

    - script.js

Abaixo o SQL com a estrutura do Banco de Dados (MySQL):

CREATE TABLE IF NOT EXISTS `capas` (

  `id` int(11) NOT NULL auto_increment,

  `nome_remetente` varchar(100) NOT NULL,

  `email_destino` varchar(70) NOT NULL,

  `codigo` tinytext NOT NULL,

  `data_hora` datetime NOT NULL,

  PRIMARY KEY  (`id`)

) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=29 ;

Ainda vou fazer os testes em outros navegadores e qualquer modificação eu informo.

Fred, mandarei os arquivos no seu email para publicação.

Sugestões de melhoria ou qualquer dificuldade, me chamem!

#49

Já coloquei o aplicativo no ar, Thiago! Fiz uma inserção simples de Iframe http://designlivre.faberludens.com.br/de-uma-capa-de-presente/ 

Muito obrigado, cara, ficou demais!

Acho que aqui no Corais seria melhor anexar aquele ZIP que você me mandou ao invés de colar o código no texto dos comentários. 

Quando você tiver um tempo livre, seria legal fazer uma tabela pra nós administradores verem as capas que foram feitas. Clicou no registro, ele abre o código escolhido no aplicativo. 

#50

Certo Fred, vou anexar hj o ZIP aqui. Vou providenciar a área administrativa também!

#51

Fiquei com isso agora na cabeça: tem que licenciar o código, a parte? Ou posts aqui também estão com lincenças?

#52

Minha edição do livro não tem desenho ainda. Posso fazer um tutorial, sim.

De quem que vou ganhar o desenho? rs :D eu mesmo?

#53

Então segue os arquivos! 

Pré-visualizarAnexoTamanho
design_livre_capa.zip104.7 KB