<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Tutoriais &#8211; Velho Bit</title>
	<atom:link href="https://velhobit.com.br/tutoriais/feed" rel="self" type="application/rss+xml" />
	<link>https://velhobit.com.br</link>
	<description>Artigos, Notícias e Tutoriais sobre Web Design, Design Gráfico, Desenvolvimento e Programação Web... e um tico de games</description>
	<lastBuildDate>Thu, 24 Apr 2025 11:49:43 +0000</lastBuildDate>
	<language>pt-BR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://velhobit.com.br/wp-content/uploads/2024/10/cropped-minieu-32x32.png</url>
	<title>Tutoriais &#8211; Velho Bit</title>
	<link>https://velhobit.com.br</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Como Liberar Espaço no iPhone: Guia Completo para Otimizar Seu Dispositivo</title>
		<link>https://velhobit.com.br/tutoriais/como-liberar-espaco-no-iphone-guia-completo-para-otimizar-seu-dispositivo.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Thu, 24 Apr 2025 11:49:43 +0000</pubDate>
				<category><![CDATA[Aplicativos e Serviços]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[dados]]></category>
		<category><![CDATA[espaço]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[otimização]]></category>
		<guid isPermaLink="false">https://site.velhobit.com.br/?p=41</guid>

					<description><![CDATA[Se você está notando que seu&#160;iPhone&#160;está mais lento, com menos espaço de armazenamento disponível ou simplesmente deseja melhorar seu desempenho geral, limpar dados do sistema pode ser uma solução eficaz. No entanto, muitos usuários não sabem exatamente como realizar essa limpeza de maneira segura e eficiente. Neste artigo, explicaremos passo a passo como limpar dados [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Se você está notando que seu&nbsp;<strong>iPhone</strong>&nbsp;está mais lento, com menos espaço de armazenamento disponível ou simplesmente deseja melhorar seu desempenho geral, limpar dados do sistema pode ser uma solução eficaz. No entanto, muitos usuários não sabem exatamente como realizar essa limpeza de maneira segura e eficiente. Neste artigo, explicaremos passo a passo como limpar dados do sistema no iPhone, melhorar a performance do seu dispositivo e liberar espaço de armazenamento.</p>



<figure class="wp-block-image size-full"><img fetchpriority="high" decoding="async" width="471" height="1024" src="https://velhobit.com.br/wp-content/uploads/2025/04/screenshot-armazenamento-ios-471x1024-1.png" alt="" class="wp-image-44" srcset="https://velhobit.com.br/wp-content/uploads/2025/04/screenshot-armazenamento-ios-471x1024-1.png 471w, https://velhobit.com.br/wp-content/uploads/2025/04/screenshot-armazenamento-ios-471x1024-1-184x400.png 184w, https://velhobit.com.br/wp-content/uploads/2025/04/screenshot-armazenamento-ios-471x1024-1-276x600.png 276w" sizes="(max-width: 471px) 100vw, 471px" /></figure>



<h2 class="wp-block-heading">O que São &#8220;Dados do Sistema&#8221; no iPhone?</h2>



<p>No iPhone, os&nbsp;<strong>dados do sistema</strong>&nbsp;referem-se a uma série de arquivos essenciais para o funcionamento do dispositivo. Esses dados incluem:</p>



<ul class="wp-block-list">
<li><strong>Arquivos temporários</strong>: Cache de aplicativos, logs do sistema e outros arquivos temporários.</li>



<li><strong>Armazenamento de dados de aplicativos</strong>: Como arquivos de configuração e dados de cache.</li>



<li><strong>Arquivos do sistema operacional iOS</strong>: Componentes essenciais para o funcionamento do sistema.</li>
</ul>



<p>Embora os dados do sistema sejam necessários para que o iPhone funcione corretamente, eles podem se acumular ao longo do tempo, ocupando uma quantidade significativa de espaço de armazenamento e impactando o desempenho do dispositivo.</p>



<h3 class="wp-block-heading">Por Que Limpar os Dados do Sistema?</h3>



<p>Limpar os dados do sistema pode ajudar em diversas situações, tais como:</p>



<ul class="wp-block-list">
<li><strong>Liberar espaço</strong>: Com o tempo, o armazenamento do seu iPhone pode ficar saturado com caches e arquivos temporários que não são mais necessários.</li>



<li><strong>Melhorar o desempenho</strong>: A limpeza dos dados do sistema pode ajudar a reduzir o uso de recursos do dispositivo, tornando-o mais rápido e eficiente.</li>



<li><strong>Correção de falhas</strong>: Às vezes, arquivos corrompidos ou desnecessários podem causar problemas no iPhone, e uma limpeza pode ajudar a resolver essas falhas.</li>
</ul>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Libere Espaço no iPhone: Dicas Infalíveis para Aproveitar o iCloud!" width="500" height="375" src="https://www.youtube.com/embed/ug6Rfh146W0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading">Como Limpar Dados do Sistema no iPhone</h2>



<h3 class="wp-block-heading">1.&nbsp;<strong>Reiniciar o iPhone</strong></h3>



<p>Uma das maneiras mais simples de limpar parte dos dados do sistema no iPhone é reiniciar o dispositivo. Isso ajuda a limpar caches temporários e reiniciar o funcionamento normal dos aplicativos.</p>



<p><strong>Passos</strong>:</p>



<ol class="wp-block-list">
<li>Pressione e segure o botão de liga/desliga (ou o botão lateral, dependendo do modelo) até que apareça o slider de desligamento.</li>



<li>Arraste o slider para desligar o iPhone.</li>



<li>Após o dispositivo desligar, aguarde alguns segundos e ligue-o novamente pressionando o botão de liga/desliga.</li>
</ol>



<h3 class="wp-block-heading">2.&nbsp;<strong>Limpar o Cache de Aplicativos</strong></h3>



<p>Muitos aplicativos, como Safari, YouTube e WhatsApp, acumulam dados de cache ao longo do tempo. Limpar esses caches pode liberar uma quantidade significativa de espaço no iPhone.</p>



<h4 class="wp-block-heading">Limpar Cache do Safari:</h4>



<ol class="wp-block-list">
<li>Abra o <strong>Ajustes</strong> do iPhone.</li>



<li>Role para baixo e toque em <strong>Safari</strong>.</li>



<li>Toque em <strong>Limpar Histórico e Dados dos Sites</strong>.</li>



<li>Confirme a ação tocando em <strong>Limpar Histórico e Dados</strong>.</li>
</ol>



<p>Isso removerá o cache, cookies e o histórico de navegação do Safari, ajudando a liberar espaço de armazenamento.</p>



<h4 class="wp-block-heading">Limpar Cache de Outros Aplicativos:</h4>



<p>Para limpar o cache de outros aplicativos, a maioria dos apps não oferece uma opção direta no iPhone. No entanto, você pode desinstalar e reinstalar o aplicativo para limpar todos os dados temporários e o cache acumulado.</p>



<ol class="wp-block-list">
<li><strong>Desinstalar o aplicativo</strong>: Toque e segure o ícone do aplicativo até que ele comece a tremer e toque no &#8220;X&#8221; para remover.</li>



<li><strong>Reinstalar o aplicativo</strong>: Vá até a App Store e instale o aplicativo novamente.</li>
</ol>



<h3 class="wp-block-heading">3.&nbsp;<strong>Gerenciar Armazenamento do iPhone</strong></h3>



<p>O iPhone possui uma ferramenta integrada que permite gerenciar o espaço de armazenamento de maneira eficiente. Para acessar essas configurações:</p>



<ol class="wp-block-list">
<li>Abra <strong>Ajustes</strong> no seu iPhone.</li>



<li>Toque em <strong>Geral</strong>.</li>



<li>Selecione <strong>Armazenamento do iPhone</strong>.</li>



<li>Aqui você verá uma lista de aplicativos e a quantidade de espaço que cada um ocupa, incluindo <strong>Dados do Sistema</strong>.</li>
</ol>



<p>Se você notar que algum aplicativo está ocupando muito espaço com dados de sistema, você pode optar por excluir o aplicativo e reinstalá-lo para liberar espaço.</p>



<h3 class="wp-block-heading">4.&nbsp;<strong>Limpar Arquivos de Sistema e Dados de Backup Antigos</strong></h3>



<p>Alguns arquivos de sistema podem ser armazenados em seu iPhone, ocupando espaço sem que você perceba. Além disso, backups antigos do iCloud podem consumir espaço de forma desnecessária. Para limpar essas informações:</p>



<h4 class="wp-block-heading">Apagar Backups Antigos do iCloud:</h4>



<ol class="wp-block-list">
<li>Abra <strong>Ajustes</strong>.</li>



<li>Toque no seu nome no topo da tela para acessar o <strong>iCloud</strong>.</li>



<li>Selecione <strong>Gerenciar Armazenamento</strong>.</li>



<li>Toque em <strong>Backups</strong>.</li>



<li>Veja a lista de dispositivos que têm backups e exclua os backups antigos que você não precisa mais.</li>
</ol>



<h4 class="wp-block-heading">Limpar Dados de Sistema:</h4>



<p>Infelizmente, não há uma opção direta para limpar os dados do sistema do iPhone, mas com a limpeza dos caches e a remoção de backups antigos, você pode reduzir consideravelmente o uso de armazenamento pelo sistema.</p>



<h3 class="wp-block-heading">5.&nbsp;<strong>Restaurar o iPhone de Fábrica</strong></h3>



<p>Se, após seguir todas as etapas acima, você ainda sentir que o iPhone está lento ou com problemas relacionados aos dados do sistema, você pode realizar uma&nbsp;<strong>restauração de fábrica</strong>. Este processo apagará todos os dados do dispositivo, incluindo dados do sistema, e restaurará o iPhone para suas configurações originais.</p>



<p><strong>Passos</strong>:</p>



<ol class="wp-block-list">
<li>Faça um <strong>backup</strong> de todos os seus dados importantes (fotos, contatos, etc.).</li>



<li>Vá até <strong>Ajustes > Geral > Redefinir</strong>.</li>



<li>Selecione <strong>Apagar Conteúdo e Ajustes</strong>.</li>



<li>Confirme a ação e siga as instruções para restaurar o iPhone.</li>
</ol>



<p>Após a restauração, você precisará configurar seu iPhone novamente, como se fosse um dispositivo novo. Isso pode ser uma solução eficaz para liberar espaço e corrigir problemas com dados do sistema.</p>



<h2 class="wp-block-heading">Conclusão</h2>



<p>Limpar dados do sistema no iPhone pode ser uma maneira eficaz de liberar espaço de armazenamento e melhorar o desempenho do dispositivo. Embora o processo de remoção de dados do sistema não seja totalmente automático, você pode utilizar as etapas mencionadas acima para otimizar o seu iPhone. Desde a reinicialização simples até a exclusão de backups antigos e a restauração de fábrica, existem várias formas de manter seu dispositivo funcionando de maneira eficiente.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como fazer backup ou transferência de cloud drive com rclone</title>
		<link>https://velhobit.com.br/tutoriais/como-usar-o-rclone-para-transferencias-seguras-e-personalizadas-de-arquivos-na-nuvem.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Fri, 18 Apr 2025 09:56:56 +0000</pubDate>
				<category><![CDATA[Aplicativos e Serviços]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[clone]]></category>
		<category><![CDATA[cloud]]></category>
		<category><![CDATA[drive]]></category>
		<category><![CDATA[google drive]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[onedrive]]></category>
		<guid isPermaLink="false">https://site.velhobit.com.br/?p=32</guid>

					<description><![CDATA[Ferramenta de linha de comando para gerenciar arquivos entre diferentes serviços de armazenamento em nuvem]]></description>
										<content:encoded><![CDATA[
<p>O <strong>rclone</strong> é uma ferramenta de linha de comando extremamente poderosa para quem precisa gerenciar arquivos entre diferentes serviços de armazenamento em nuvem. Ele é ideal para usuários que desejam:</p>



<ul class="wp-block-list">
<li>Fazer backup dos seus arquivos em nuvens diferentes</li>



<li>Sincronizar conteúdo entre um serviço e outro</li>



<li>Baixar todos os seus dados de uma conta antes de encerrá-la</li>



<li>Copiar arquivos em massa com muito mais controle e confiabilidade do que as ferramentas oficiais</li>
</ul>



<p>Em muitos casos, como no OneDrive, essa necessidade se tornou ainda mais comum devido ao aumento dos preços dos planos, em decorrências a outros serviços com preços mais em conta. Além disso, quando você tenta baixar muitos dados simultâneos em diversos serviços o download trava ou resulta em pastas vazias ao copiar dos aplicativos oficiais, ao transferir pastas.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Instalação do rclone</h2>



<h3 class="wp-block-heading">macOS (via Homebrew)</h3>



<pre class="wp-block-code"><code>brew install rclone</code></pre>



<h3 class="wp-block-heading">Linux (Debian, Ubuntu e derivados)</h3>



<pre class="wp-block-code"><code>curl https://rclone.org/install.sh | sudo bash</code></pre>



<p>Ou via gerenciador de pacotes:</p>



<pre class="wp-block-code"><code>sudo apt install rclone</code></pre>



<h3 class="wp-block-heading">Windows</h3>



<ol start="1" class="wp-block-list">
<li>Acesse:&nbsp;<a>https://rclone.org/downloads/</a></li>



<li>Baixe a versão .zip para Windows</li>



<li>Extraia e coloque a pasta em um local fixo (ex:&nbsp;<code>C:\Program Files\rclone</code>)</li>



<li>Adicione o caminho da pasta ao Path do sistema para usar via terminal</li>
</ol>



<div class="observation">
<h3>Como adicionar o rclone ao PATH no Windows</h3>
<p>Localize a pasta onde está o executável</p>
<p>Após extrair o .zip do Rclone, você terá algo como:</p>
<code>
C:\Program Files\rclone ou C:\Users\SeuUsuario\Downloads\rclone-vXXX-windows-amd64
</code>
<p>Copie o caminho completo da pasta. Por exemplo:</p>
<code>
C:\Program Files\rclone
</code>
<p>Abra as variáveis de ambiente</p>
<p>Pressione Win + S e digite variáveis de ambiente</p>
<p>Clique em “Editar variáveis de ambiente do sistema”</p>
<p>Na janela que abrir, clique no botão “Variáveis de ambiente…” no canto inferior direito</p>
<p>Em Variáveis do sistema, encontre a variável chamada Path e clique em Editar…</p>
<p>Clique em Novo e cole o caminho da pasta que você copiou</p>
<p>Clique em OK em todas as janelas para confirmar</p>
</div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Configurando o acesso ao OneDrive (ou outra nuvem)</h2>



<p>Execute:</p>



<pre class="wp-block-code"><code>rclone config</code></pre>



<p>Siga as instruções passo a passo:</p>



<ol start="1" class="wp-block-list">
<li>Digite&nbsp;<code>n</code>&nbsp;para criar uma nova configuração</li>



<li>Escolha um nome para ela (ex:&nbsp;<code>onedrive</code>)</li>



<li>Aparecerá uma lista numerada de serviços de nuvem. Escolha o número correspondente ao&nbsp;<strong>OneDrive</strong>.Importante: essa lista pode mudar de ordem conforme a versão do Rclone. Leia atentamente ao lado de cada número.</li>



<li>Quando for perguntado sobre &#8220;client_id&#8221; e &#8220;client_secret&#8221;, pode apenas pressionar Enter para usar os padrões do Rclone.</li>



<li>No prompt sobre &#8220;Edit advanced config?&#8221;, escolha&nbsp;<code>n</code>, a menos que saiba o que está fazendo.</li>



<li>Quando perguntado sobre usar &#8220;auto config&#8221;, escolha&nbsp;<code>y</code>&nbsp;se estiver em um computador com navegador instalado. Isso abrirá o login da Microsoft no navegador para autorização.</li>



<li>Depois de autorizado, volte ao terminal e confirme a gravação da configuração.</li>
</ol>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">É obrigatório sincronizar os arquivos?</h2>



<p><strong>Não.</strong>&nbsp;O <strong>rclone</strong> permite tanto&nbsp;<strong>copiar</strong>&nbsp;quanto&nbsp;<strong>sincronizar</strong>&nbsp;arquivos:</p>



<ul class="wp-block-list">
<li><code>rclone copy</code>&nbsp;copia arquivos de origem para destino&nbsp;<strong>sem apagar nada</strong></li>



<li><code>rclone sync</code>&nbsp;sincroniza origem e destino,&nbsp;<strong>apagando do destino o que não existir mais na origem</strong></li>
</ul>



<p>Para a maioria dos usuários que estão apenas fazendo backup ou transferindo dados, o ideal é usar&nbsp;<code>copy</code>, pois é mais seguro.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Exemplo: Copiar tudo do OneDrive (exceto algumas pastas)</h2>



<pre class="wp-block-code"><code>rclone copy onedrive: ~/OneDriveBackup \
  --progress \
  --exclude "Vídeos Compartilhados/**" \
  --exclude "Backup do GOG/**"</code></pre>



<p>Esse comando faz o seguinte:</p>



<ul class="wp-block-list">
<li>Copia todos os arquivos do OneDrive para a pasta local <code>~/OneDriveBackup</code> (você pode dar o nome que quiser à pasta)</li>



<li>Exibe o progresso durante a transferência</li>



<li><strong>Ignora</strong> as pastas <code>Vídeos Compartilhados</code> e <code>Backup do GOG</code>, assim como todos os arquivos e subpastas dentro delas</li>
</ul>



<p>Se quiser testar antes sem copiar nada, use a opção <code>--dry-run</code>:</p>



<pre class="wp-block-code"><code>rclone copy onedrive: ~/OneDriveBackup --dry-run --exclude "Videos Compartilhados/**"</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Outras opções úteis</h2>



<h3 class="wp-block-heading">Listar as pastas da raiz:</h3>



<pre class="wp-block-code"><code>rclone lsd onedrive:</code></pre>



<h3 class="wp-block-heading">Listar arquivos:</h3>



<pre class="wp-block-code"><code>rclone ls onedrive:</code></pre>



<h3 class="wp-block-heading">Sincronizar (com cautela):</h3>



<pre class="wp-block-code"><code>rclone sync onedrive: ~/OneDriveBackup --progress</code></pre>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>Atenção:&nbsp;<code>sync</code>&nbsp;pode apagar arquivos locais se eles não existirem mais na nuvem.</p>
</blockquote>



<p>Validar arquivos por tamanho pode ser útil para quando você copia os arquivos de outra origem e não quer sobrevescrever um arquivo que você já possua na pasta.</p>



<pre class="wp-block-code"><code>rclone copy onedrive: ~/OneDriveBackup --size-only</code></pre>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h2 class="wp-block-heading">Concluindo</h2>



<p>O <strong>rclone</strong> é uma ferramenta robusta para quem precisa mais controle sobre arquivos em nuvem. Ele não depende de interfaces gráficas, é multiplataforma, e é confiável mesmo para grandes volumes de dados.</p>



<p>Se você está migrando de um serviço para outro, fazendo backup, ou tentando contornar limitações do aplicativo oficial (como as do OneDrive), o <strong>rclone</strong> é uma solução altamente recomendada.</p>



<p>Manter o controle total dos seus dados nunca foi tão fácil.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Se quiser aprofundar ainda mais, você pode consultar a documentação oficial em:&nbsp;<a href="https://rclone.org/">https://rclone.org/</a></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Libere Espaço no iPhone: Dicas Infalíveis para Aproveitar o iCloud!</title>
		<link>https://velhobit.com.br/tutoriais/libere-espaco-no-iphone-dicas-infaliveis-para-aproveitar-o-icloud.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Tue, 01 Oct 2024 20:51:16 +0000</pubDate>
				<category><![CDATA[Gestão]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[armazenamento]]></category>
		<category><![CDATA[backup]]></category>
		<category><![CDATA[dicas de tecnologia]]></category>
		<category><![CDATA[dicas para iPhone]]></category>
		<category><![CDATA[iCloud]]></category>
		<category><![CDATA[iphone]]></category>
		<category><![CDATA[liberar espaço]]></category>
		<category><![CDATA[otimização de fotos]]></category>
		<category><![CDATA[vídeos no iPhone]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=2229</guid>

					<description><![CDATA[Descubra dicas essenciais para liberar espaço no seu iPhone e aproveitar ao máximo o iCloud. Otimize backups, fotos e vídeos sem perder seus arquivos importantes!]]></description>
										<content:encoded><![CDATA[
<p>Uma das principais reclamações que ouço de usuários de iPhone é que, mesmo contratando vários terabytes de iCloud, o espaço do aparelho continua insuficiente. Mas por que isso acontece e como resolver?</p>



<p>A verdade é que o iCloud não funciona exatamente como um “backup mágico” que libera espaço no seu iPhone. Na realidade, ele é um serviço de <strong>sincronização em nuvem</strong>, projetado para compartilhar seus dados entre seus dispositivos e manter um backup em caso de perda ou roubo de algum deles.</p>



<p>No entanto, existem maneiras de usar o iCloud da forma como muitos imaginam – para economizar espaço no iPhone. Abaixo, confira algumas dicas de como otimizar o uso e liberar armazenamento no seu aparelho.</p>



<p>Dê play caso prefira assistir estas dicas no Youtube ao invés de ler:</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-4-3 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="Libere Espaço no iPhone: Dicas Infalíveis para Aproveitar o iCloud!" width="500" height="375" src="https://www.youtube.com/embed/ug6Rfh146W0?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading">Dica 1 &#8211; Configuração econômica do iCloud</h2>



<p>Por padrão, o iPhone está configurado para fazer um backup completo do aparelho, e não apenas de arquivos e fotos. Esse backup pode ocupar quase o mesmo espaço no iCloud que você já consome no seu telefone, já que é uma imagem completa do estado atual do dispositivo. No entanto, a maioria das pessoas não precisa desse backup completo. Se você adquirir um iPhone novo porque perdeu o antigo, por exemplo, reconfigurar o aparelho do zero não é um grande inconveniente – o mais importante é não perder suas fotos e arquivos essenciais.</p>



<p>Para liberar espaço no iCloud, siga os passos abaixo:</p>



<p>Abra o app Ajustes, toque no seu nome no topo da tela e vá em <strong>iCloud > Backup do iPhone</strong>. Desative <strong>Fazer Backup Deste iPhone</strong>. Isso <strong>não</strong> desativará o backup das suas fotos.</p>



<figure class="wp-block-image size-large is-resized"><img loading="lazy" decoding="async" width="1024" height="1015" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone1-1024x1015.png" alt="Tela de Ajustes:
- Principal
- Conta da Apple

com foco na opção iCloud" class="wp-image-2230" style="width:840px;height:auto" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone1-1024x1015.png 1024w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone1-400x397.png 400w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone1-768x761.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone1-600x595.png 600w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone1.png 1414w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone2-1003x1024.png" alt="Telas de Ajustes
 - iCloud+  &gt; Backup do iCloud
- Backup &gt; Fazer Backup Deste iPhone desabilitado" class="wp-image-2231" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone2-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone2-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone2-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone2-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone2.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<p>Agora, volte ao menu do iCloud e toque em <strong>Fotos</strong>. Role para baixo até encontrar a opção <strong>Otimizar no iPhone</strong> e mantenha-a ativada, caso ainda não esteja. Com essa configuração, o iPhone, quando precisar de espaço, substituirá o arquivo original da foto por uma versão otimizada e mais leve, deixando o arquivo completo apenas na nuvem. Quando você quiser editar ou compartilhar a imagem, o iPhone fará o download da versão final.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone3-1003x1024.png" alt="Tela Ajustes
- iCloud + &gt; Fotos
- Fotos do iCloud &gt; Selecionado Otimizar no iPhone" class="wp-image-2232" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone3-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone3-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone3-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone3-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone3.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<h2 class="wp-block-heading">Dica 2 &#8211; Salve as fotos que quer guardar fora da galeria em uma pasta não sincronizada</h2>



<p>Dentro do iPhone, há um app chamado <strong>Arquivos</strong>, que permite armazenar e acessar documentos, imagens, vídeos, PDFs, e outros formatos diretamente na nuvem ou no aparelho. Ele oferece a flexibilidade de manter esses arquivos exclusivamente na nuvem, liberando espaço no dispositivo.</p>



<p>Para criar um backup em uma pasta não sincronizada, siga os passos abaixo:</p>



<p>1. Abra o app <strong>Arquivos</strong>, toque nos três pontos no canto superior direito e selecione <strong>Nova Pasta</strong>. Nomeie a pasta como preferir.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone4-1003x1024.png" alt="Home do iPhone - App arquivos selecionado
App Arquivos &gt; iCloud Drive &gt; Mais opções abertas selecionando Nova Pasta" class="wp-image-2233" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone4-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone4-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone4-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone4-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone4.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone5-1003x1024.png" alt="Tela do app Arquivos &gt; iCloud Drive - Pasta Backup selecionada
Tela do app Fotos &gt; botão Compartilhar selecionado e algumas fotos marcadas como seleção" class="wp-image-2234" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone5-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone5-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone5-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone5-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone5.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<p>2. Vá ao app <strong>Fotos</strong>, selecione as imagens que deseja guardar e toque no botão de <strong>compartilhar</strong>. Em seguida, escolha a opção <strong>Salvar em Arquivos</strong>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone7-1003x1024.png" alt="Tela de compartilhamento &gt; Opção Salvar em Arquivos
Tela de Compartilhamento iCloud Drive &gt; Backup, com o texto &quot;A Pasta Está Vazia&quot;" class="wp-image-2235" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone7-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone7-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone7-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone7-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone7.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<p>3. Volte ao app <strong>Arquivos</strong> e aguarde o upload ser concluído. Depois, pressione e segure a pasta recém-criada até que apareçam as opções e toque em <strong>Remover Download</strong>. Com isso, essas fotos ficarão salvas somente na nuvem, sem ocupar espaço no seu iPhone.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone8-1003x1024.png" alt="App arquivos &gt; Backup &gt; Sincronizando
App arquivos &gt; Opções de Pasta &gt; Remover Download" class="wp-image-2236" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone8-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone8-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone8-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone8-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone8.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<p>4. Por fim, retorne ao app <strong>Fotos</strong> e exclua as imagens que você acabou de fazer o backup. Elas permanecerão acessíveis pelo app Arquivos sempre que precisar.</p>



<h2 class="wp-block-heading">Dica 3 &#8211; Use a câmera de forma inteligente</h2>



<p>A câmera do iPhone pode ser sua aliada ou inimiga na hora de economizar espaço e dados. Muitas vezes, ao buscar a melhor qualidade possível, fazemos ajustes que acabam sendo desnecessários para nossas necessidades do dia a dia.</p>



<p>Um exemplo é o sensor de 48MP do iPhone, que, por padrão, gera fotos de 12MP. Isso acontece porque o iPhone utiliza um processo de pós-produção que combina e seleciona pixels para otimizar a iluminação da imagem, resultando em uma foto mais leve de 12MP. Apesar de usar os 48MP, o sistema reduz a imagem de forma inteligente, mantendo a qualidade ideal para redes sociais.</p>



<p>Por outro lado, o iPhone oferece o modo ProRAW, que gera imagens de 48MP com pouquíssimo pós-processamento, criando arquivos até 10 vezes maiores. A imagem fica mais “lavada”, ideal para quem quer editar posteriormente com maior controle das cores e detalhes.</p>



<p>Quando falamos de vídeo, as opções se expandem. Embora o iPhone permita gravar em várias resoluções e fps, é bom lembrar que plataformas como Instagram e TikTok utilizam apenas 1080p, tornando desnecessário gravar em 4K – a menos que você pretenda aplicar zoom na edição.</p>



<p>Há também o modo Cinema, que adiciona informações de profundidade, criando o famoso efeito de desfoque no fundo. Isso, junto com o HDR, aumenta significativamente o tamanho dos arquivos. Se o desfoque não for importante para você, evite usar esse modo.</p>



<p>O modo Câmera Lenta, apesar de impressionante, consome uma quantidade enorme de memória, especialmente nos modelos iPhone 16 e 16 Pro, que têm resoluções maiores. Use com cautela, principalmente em vídeos longos.</p>



<p>Por fim, o modo ProRes é voltado para profissionais de vídeo. Com uma média de 6GB por minuto, ele é extremamente pesado e gera vídeos crus, sem pós-processamento, perfeitos para edições detalhadas. No entanto, para a maioria dos usuários, o uso desse modo deve ser evitado.</p>



<p>Para ajustar as configurações ideais para suas necessidades, vá até o app <strong>Ajustes</strong>, selecione <strong>Câmera</strong> e ajuste conforme suas preferências. Não se esqueça de ativar a opção <strong>Alta Eficiência</strong> em <strong>Formatos</strong> para garantir que suas fotos e vídeos sejam salvos em HEIF, um formato mais leve e compatível com sistemas e aplicativos modernos.</p>



<p>Lembre-se que, a qualquer momento, você pode, diretamente na câmera, você pode fazer algum ajuste no momento de usar a câmera.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone9-1003x1024.png" alt="App Ajustes &gt; Câmera
Opções de Câmera" class="wp-image-2237" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone9-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone9-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone9-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone9-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone9.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1003" height="1024" src="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone10-1003x1024.png" alt="App Ajustes &gt; Camera &gt; Opção Formatos marcado como Alta Eficiência
Destaque nas opções das fotos, no app de Camera" class="wp-image-2238" srcset="https://velhobit.com.br/wp-content/uploads/2024/10/iPhone10-1003x1024.png 1003w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone10-392x400.png 392w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone10-768x784.png 768w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone10-588x600.png 588w, https://velhobit.com.br/wp-content/uploads/2024/10/iPhone10.png 1373w" sizes="auto, (max-width: 1003px) 100vw, 1003px" /></figure>



<p>Em conclusão, liberar espaço no iPhone vai muito além de apenas contratar mais armazenamento no iCloud. Compreender como o iCloud funciona como uma ferramenta de sincronização, ajustar corretamente as configurações de backup e otimizar o uso da câmera são passos essenciais para evitar a falta de espaço no dispositivo. Além disso, usar o app Arquivos para criar pastas não sincronizadas e escolher formatos mais eficientes como o HEIF garante um uso mais inteligente da memória. Seguindo essas dicas, você poderá aproveitar ao máximo o iCloud sem comprometer o desempenho ou o armazenamento do seu iPhone.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como centralizar verticalmente elementos HTML com CSS</title>
		<link>https://velhobit.com.br/tutoriais/como-centralizar-verticalmente-elementos-html-com-css.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Wed, 02 Jun 2021 22:40:30 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[ajustes]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[diagramação]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[webdesign]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=2151</guid>

					<description><![CDATA[Veja 3 técnicas diferentes de como alinhar elementos verticalmente usando CSS e como elas podem ser usadas.]]></description>
										<content:encoded><![CDATA[
<p>Uma das coisas mais comuns, mas ao mesmo tempo mais chatas de se fazer no CSS é alinhar verticalmente elementos em tela. Existem várias formas de fazer isso. Neste post, vou elencar as minhas formas favoritas de fazer isso.</p>



<h2 class="wp-block-heading">Alinhamento com Flexbox</h2>



<p>Flex é uma propriedade incrível do CSS que permite organizar elementos. Se outrora tínhamos que fazer inúmeras gambiarras com float, o flex nos permite controlar o comportamentos dos filhos de um container. Para centralizar verticalmente um objeto, podemos usar a direção de coluna, em seu container pai.</p>



<script async src="//jsfiddle.net/velhobit/q1xsybp9/embed/result,html,css/"></script>



<h2 class="wp-block-heading">Alinhamento com position</h2>



<p>Com um pouco de matemática, conseguimos fazer um alinhamento vertical com o position absolute. Porém, é importante lembrar que o objeto será flutuante e que seu pai, necessariamente, precisa ser um position relative. O problema de usar esse tipo de alinhamento é que o conteúdo da posição precisa ser fixo. Felizmente, hoje, conseguimos fazer cálculos com variáveis de CSS, o que facilita a forma de implementarmos essa técnica. A vantagem dessa técnica é poder usar, justamente, em ambientes flutuantes que se sobreponham. Porém, caso você não precise que ele se alinhe ao pai, mas à viewport, você pode usar também o position como fixed.</p>



<iframe loading="lazy" width="100%" height="500" src="//jsfiddle.net/velhobit/qd8fn6r9/1/embedded/result,html,css/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>



<h2 class="wp-block-heading">Alinhamento com Grid</h2>



<p>Outra forma moderna de alinhar verticalmente é através do uso de grids. A vantagem de usar grids é que o tamanho do conteúdo do elemento alinhado corresponderá ao tamanho da grid que se deseja utilizar. Ou seja, é adaptável de acordo com a viewport, e não referente ao seu conteúdo. Para isso, basta definirmos a quantidade de colunas e linhas que desejamos e estabelecemos onde o objeto alinhado vai iniciar e terminar.</p>



<iframe loading="lazy" width="100%" height="400" src="//jsfiddle.net/velhobit/r869swqz/embedded/result,html,css/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>



<h2 class="wp-block-heading">Exemplo de uso (Modal Alinhado ao Centro)</h2>



<p>Para mostrar como pode ser usado os alinhamentos, que tal criarmos um simples modal alinhado ao centro da tela? </p>



<p>Um modal é composto por uma cortina que reveste o conteúdo original, seguido de um painel com alguma informação dentro. É convenção de que os modals carreguem essas informações no centro da tela, afim de que a informação fique direcionada e encapsulada, levando, assim, o usuário à uma atenção maior àquela informação. Ou seja, isolar e destacar. O exemplo abaixo foi feito usando a primeira estratégia de alinhamento vertical aqui apresentada, pois, desta forma, o tamanho do modal que vai ser a referência para a centralização. Alguns efeitos foram adicionados para ilustrar melhor.</p>



<iframe loading="lazy" width="100%" height="500" src="//jsfiddle.net/velhobit/pbgmvu2x/embedded/result,css,html,js/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como centralizar verticalmente elementos HTML com CSS</title>
		<link>https://velhobit.com.br/tutoriais/como-centralizar-verticalmente-elementos-html-com-css-2.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Wed, 02 Jun 2021 15:55:00 +0000</pubDate>
				<category><![CDATA[Design e Front-End]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[front-end]]></category>
		<guid isPermaLink="false">https://site.velhobit.com.br/?p=79</guid>

					<description><![CDATA[Uma das coisas mais comuns, mas ao mesmo tempo mais chatas de se fazer no CSS é alinhar verticalmente elementos em tela. Existem várias formas de fazer isso. Neste post, vou elencar as minhas formas favoritas de fazer isso. Alinhamento com Flexbox Flex é uma propriedade incrível do CSS que permite organizar elementos. Se outrora [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p id="block-6649b4be-5663-4f89-88e0-637dda1ae9f9">Uma das coisas mais comuns, mas ao mesmo tempo mais chatas de se fazer no CSS é alinhar verticalmente elementos em tela. Existem várias formas de fazer isso. Neste post, vou elencar as minhas formas favoritas de fazer isso.</p>



<h2 class="wp-block-heading" id="block-044e5df1-377f-4af3-9fca-89873d318cc9">Alinhamento com Flexbox</h2>



<p id="block-76c3e40b-7e0a-4b6f-96fc-b607806b82e5">Flex é uma propriedade incrível do CSS que permite organizar elementos. Se outrora tínhamos que fazer inúmeras gambiarras com float, o flex nos permite controlar o comportamentos dos filhos de um container. Para centralizar verticalmente um objeto, podemos usar a direção de coluna, em seu container pai.</p>



<script async src="//jsfiddle.net/velhobit/q1xsybp9/embed/result,html,css/"></script>



<h2 class="wp-block-heading" id="block-67d6f3aa-0db2-4282-af69-76386eb87f4e">Alinhamento com position</h2>



<p id="block-2ea4513d-94ab-48e7-852d-60717d06ce04">Com um pouco de matemática, conseguimos fazer um alinhamento vertical com o position absolute. Porém, é importante lembrar que o objeto será flutuante e que seu pai, necessariamente, precisa ser um position relative. O problema de usar esse tipo de alinhamento é que o conteúdo da posição precisa ser fixo. Felizmente, hoje, conseguimos fazer cálculos com variáveis de CSS, o que facilita a forma de implementarmos essa técnica. A vantagem dessa técnica é poder usar, justamente, em ambientes flutuantes que se sobreponham. Porém, caso você não precise que ele se alinhe ao pai, mas à viewport, você pode usar também o position como fixed.</p>



<iframe loading="lazy" width="100%" height="500" src="//jsfiddle.net/velhobit/qd8fn6r9/1/embedded/result,html,css/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>



<h2 class="wp-block-heading" id="block-d8b5915e-f1e6-40f7-bcda-b1d4c3c87e33">Alinhamento com Grid</h2>



<p id="block-34c78db0-4bd9-4bf3-90ab-6be7cd1f11b2">Outra forma moderna de alinhar verticalmente é através do uso de grids. A vantagem de usar grids é que o tamanho do conteúdo do elemento alinhado corresponderá ao tamanho da grid que se deseja utilizar. Ou seja, é adaptável de acordo com a viewport, e não referente ao seu conteúdo. Para isso, basta definirmos a quantidade de colunas e linhas que desejamos e estabelecemos onde o objeto alinhado vai iniciar e terminar.</p>



<iframe loading="lazy" width="100%" height="400" src="//jsfiddle.net/velhobit/r869swqz/embedded/result,html,css/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>



<h2 class="wp-block-heading" id="block-524d9cba-b523-427b-a79e-c81a23ce8c7e">Exemplo de uso (Modal Alinhado ao Centro)</h2>



<p id="block-fb03f0a5-9a2b-4fc8-a6c4-648568030b0c">Para mostrar como pode ser usado os alinhamentos, que tal criarmos um simples modal alinhado ao centro da tela?</p>



<p id="block-46b25bbb-6bf5-445d-a3d2-281f12147810">Um modal é composto por uma cortina que reveste o conteúdo original, seguido de um painel com alguma informação dentro. É convenção de que os modals carreguem essas informações no centro da tela, afim de que a informação fique direcionada e encapsulada, levando, assim, o usuário à uma atenção maior àquela informação. Ou seja, isolar e destacar. O exemplo abaixo foi feito usando a primeira estratégia de alinhamento vertical aqui apresentada, pois, desta forma, o tamanho do modal que vai ser a referência para a centralização. Alguns efeitos foram adicionados para ilustrar melhor.</p>



<iframe loading="lazy" width="100%" height="500" src="//jsfiddle.net/velhobit/pbgmvu2x/embedded/result,css,html,js/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como adicionar e remover dinamicamente campos HTML em um form? (Javascript puro)</title>
		<link>https://velhobit.com.br/tutoriais/como-adicionar-e-remover-dinamicamente-campos-html-em-um-form-javascript-puro.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sun, 14 Feb 2021 16:04:00 +0000</pubDate>
				<category><![CDATA[Design e Front-End]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[estilo]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascrip]]></category>
		<category><![CDATA[jsvanilla]]></category>
		<guid isPermaLink="false">https://site.velhobit.com.br/?p=82</guid>

					<description><![CDATA[O Javascript nos permite criar conteúdos dinâmicos e podemos usar isso para adicionar remover e adicionar elementos de acordo com as opções do usuário. Dados como informações sobre dependentes, links de mídias sociais, e-mails adicionais, etc. são curtos e não fazem sentido criarmos um formulário separado apenas para estes. Por isso, é interessante incluirmos a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p id="block-e8021681-0362-4698-bab1-e06ce8fcdc26">O Javascript nos permite criar conteúdos dinâmicos e podemos usar isso para adicionar remover e adicionar elementos de acordo com as opções do usuário. Dados como informações sobre dependentes, links de mídias sociais, e-mails adicionais, etc. são curtos e não fazem sentido criarmos um formulário separado apenas para estes. Por isso, é interessante incluirmos a opção de adicionar diretamente esses campos em um subformulário dinâmico.</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p id="block-7b013644-fd16-427f-ad7f-0dac65241e16">Obs. Se quiser ir direto para o código final, procure o link do JsFiddle no final do post.</p>
</blockquote>



<h2 class="wp-block-heading" id="block-50427a97-6435-4fe2-b0db-0ab0a0900e76">HTML</h2>



<p id="block-38a0b969-940d-488c-97fd-4070c90e2c76">Para iniciarmos, basta criar um container no HTML onde você quer que os elementos sejam exibidos, além do botão simples de adição e um botão de captura de dados, para que, desta forma, possamos enviar o JSON resultante para o back-end.</p>



<p id="block-0cea6af6-c9bb-4ce3-8f87-10fcfb3593bf">A organização dos containers é sempre muito importante quando trabalhamos com Javascript e nos dedicamos ao uso correto da web semântica.</p>



<pre class="wp-block-code"><code>&lt;div class="dependentes">
  &lt;button id="btnAdicionarDependentes">
  &#x1f4dd;Adicionar Dependentes
  &lt;/button>
  &lt;div class="container" id="dependentesContainer">
  &lt;/div>
  &lt;button class="green" id="btnCapturarDados">
  &#x2705; Capturar Dados
  &lt;/button>
&lt;/div>
&lt;pre id="containerDados">  
&lt;/pre></code></pre>



<h2 class="wp-block-heading" id="block-79778471-435b-4794-a208-bf0e3f8ac0df">Javascript</h2>



<p id="block-740ad472-30ad-4f46-84c9-50f7fcb0c77c">Como de praxe, usaremos o Javascript puro para realizar essa tarefa, dessa forma você poderá usar em qualquer lugar o que aprender aqui.</p>



<p id="block-8418b415-53dc-42c7-8343-a447bc7bc2c4">Para poder capturar e devolver os dados, usaremos um objeto JSON, dessa forma fica fácil remontar, tanto no <em>back-end</em>, quando no <em>front-end</em>, os dados nas formatações e/ou elementos que precisamos.</p>



<p id="block-5e272e83-5318-45b2-832b-693f35e68ee3">Vamos criar, como exemplo, o JSON abaixo, e vamos declará-lo em uma variável global chamada dependentes, seguindo a ideia de um cadastro de lista de dependentes, então temos:</p>



<pre class="wp-block-code"><code>var dependentes = &#91;{
  identificador: 13,
  nome: "Joana da Silva",
  idade: 12,
}];</code></pre>



<p id="block-9661ff72-c21f-4444-939c-6b7f24254659">Agora vamos nos focar nas funções. A primeira coisa que vamos fazer é criar um método que pegue os dados do JSON e o converta para elementos HTML renderizados na tela. Dessa forma, usaremos um laço para ler o JSON e aplicamos seus dados em uma <em>template string</em> e o adicionamos no container específico:</p>



<pre class="wp-block-code"><code>function carregarDependentes() {
  let dependentes_container = document.querySelector("#dependentesContainer");
  dependentes_container.innerHTML = "";
  dependentes.forEach((el) =&amp;gt; {
    let identificador = el.identificador;
    let nome = el.nome;
    let idade = el.idade;
    let dependente_container = `&lt;div class="dependente" data-id="${identificador}">
    								&lt;input class="nome" placeholder="Digite o nome" type="text" value="${nome}">
                                    &lt;input class="idade" placeholder="Digite a idade" type="number" value="${idade}">
                                    &lt;div class="action">
                                        &lt;a href="#" class="salvar">salvar &#x1f4be;&lt;/a>
                                        &lt;a href="#" class="remover">&#x274c;&lt;/a>
									&lt;/div>
                                &lt;/div>`;
    dependentes_container.innerHTML += dependente_container;
  });
}</code></pre>



<p id="block-e3a01ded-6e1f-4742-968c-475a44d36414">Agora vem o segredo que facilita o processo e o deixa mais organizado. Ao invés de remover e adicionar os elementos na tela, iremos nos focar em remover e adicionar do JSON e, em seguida, regenerar os elementos a partir desse objeto. Ficando, assim, com um código mais limpo. Outro motivo pelo qual usamos a regeneração dos elementos é para evitar criarmos IDs únicos temporários. Ao regenerar, podemos usar os índices do próprio <em>array </em>como identificador.</p>



<p id="block-ff072f21-a361-4bf0-8520-f4ad84f120a7">Para adicionar um novo item, basta incluirmos um dado vazio no JSON, porém, seguindo nosso modelo, e mandamos gerar novamente os elementos:</p>



<pre class="wp-block-code"><code>function adicionarDependentes() {
  dependentes.push({ identificador: "", nome: "", idade: "" });
  carregarDependentes();
}</code></pre>



<p id="block-2639192c-d7f1-45ad-a887-05818f80f05a">Para remover, similar a criação de um novo, vamos usar um laço, porém para adicionar o evento aos botões de excluir. Usaremos então o método <em>splice </em>para remover o <em>array</em>. Depois, obviamente, vamos regenerar os elementos a partir da função carregarDependentes():</p>



<pre class="wp-block-code"><code>function removerDependentes() {
  document
    .querySelectorAll("#dependentesContainer .remover")
    .forEach((el, i) =&amp;gt; {
      el.addEventListener("click", () =&amp;gt; {
        dependentes.splice(i, 1); // O splice vai remover um item do array no JSON
        carregarDependentes(); // E chamamos o método para regenerar os elementos
      });
    });
}</code></pre>



<p id="block-f9a40aa0-2a1e-4949-a1be-e25e8d278dd2">Uma vez que adicionamos uma nova linha em branco precisamos salvar seu preenchimento e aí iremos usar a mesma lógica de remoção, mas usaremos o <em>splice </em>para substituir e não para remover um dado do JSON. Porém, adicionaremos uma pequena validação para evitar entrar dados incompletos:</p>



<pre class="wp-block-code"><code>unction salvarDependentes() {
  document
    .querySelectorAll("#dependentesContainer .salvar")
    .forEach((el, i) =&amp;gt; {
      el.addEventListener("click", () =&amp;gt; {
        let identificador = el.parentElement.parentElement.getAttribute(
          "data-id"
        );
        let nome = el.parentElement.parentElement.querySelector(".nome").value;
        let idade = el.parentElement.parentElement.querySelector(".idade")
          .value;

        if (!nome.length || !idade.length) { // Verifica se nome e idade foram preenchidos
          alert("Nome e idade precisam ser preenchidos para salvar.");
          return false;
        }
        dependentes.splice(i, 1, {
          identificador: identificador,
          nome: nome,
          idade: idade,
        }); // Substitui o dado no JSON
        carregarDependentes(); //  E chamamos o método para regenerar os elementos
      });
    });
}</code></pre>



<p id="block-5febd00c-a838-48a5-a8a6-ea01d4d76e6a">Um outro método que precisamos adicionar é uma forma de <strong>bloquear </strong>para que um usuário consiga clicar em outros elementos ao redor, sem antes finalizar a edição do item. Para isso, iremos fazer um laço que adiciona uma classe de CSS, que vamos chamar de <em>disabled</em>, em todos os elementos, exceto o que está sendo editado. Essa classe possui um <strong><em>point-events: 0</em></strong> e um <strong><em>opacity: 0.5</em></strong>. Para demonstrar que está desativado, você pode ainda adicionar outros efeitos, como filtros de baixo contraste ou escala de cinza.</p>



<pre class="wp-block-code"><code>function travarOutros(element) {
  if (element == false) { // Passar false como parâmetro para que todos os elementos fiquem habilitados novamente, ao invés de apenas o elemento que queremos liberar
    document
      .querySelectorAll(".dependentes button, .dependentes .container &amp;gt; div")
      .forEach((el) =&amp;gt; {
        el.classList.remove("disabled");
      });
    document.querySelector("#containerDados").innerHTML = "";
    return false;
  }
  document
    .querySelectorAll(".dependentes button, .dependentes .container &amp;gt; div")
    .forEach((el) =&amp;gt; {
      if (el != element) {  // Verifica se o elemento no laço é o que está sendo editado
        el.classList.add("disabled");
      }
    });
}</code></pre>



<p id="block-be0547a1-dea2-4448-8a5e-9514278a94d4">Agora, antes de continuarmos, vamos revisitar as funções acima para chamar, quando necessário, uma função dentro da outra (leia os comentários no código para entender), ficando assim:</p>



<pre class="wp-block-code"><code>function carregarDependentes() {
  let dependentes_container = document.querySelector("#dependentesContainer");
  dependentes_container.innerHTML = "";
  dependentes.forEach((el) =&amp;gt; {
    let identificador = el.identificador;
    let nome = el.nome;
    let idade = el.idade;
    let dependente_container = `&lt;div class="dependente" data-id="${identificador}">
    															&lt;input class="nome" placeholder="Digite o nome" type="text" value="${nome}">
                                  &lt;input class="idade" placeholder="Digite a idade" type="number" value="${idade}">
                                  &lt;div class="action">
                                  	&lt;a href="#" class="salvar">salvar &#x1f4be;&lt;/a>
                                    &lt;a href="#" class="remover">&#x274c;&lt;/a>
																	&lt;/div>
															  &lt;/div>`;
    dependentes_container.innerHTML += dependente_container;
  });
  salvarDependentes(); // Adicionamos o método aqui para que o laço seja aplicado nos novos items adicionados
  removerDependentes(); // Adicionamos o método aqui para que o laço seja aplicado nos novos items adicionados
  travarOutros(false); // Adicionamos para destravar tudo
}

function removerDependentes() {
  document
    .querySelectorAll("#dependentesContainer .remover")
    .forEach((el, i) =&amp;gt; {
      el.addEventListener("click", () =&amp;gt; {
        dependentes.splice(i, 1);
        carregarDependentes(); // Regenerar os elementos HTML após remover do JSON
      });
    });
}

function adicionarDependentes() {
  dependentes.push({ identificador: "", nome: "", idade: "" });
  carregarDependentes(); // Regenerar os elementos HTML após remover do JSON
  travarOutros(
    document.querySelector("#dependentesContainer &amp;gt; div:last-child")
  ); // Desabilitar todos os outros elementos, exceto o que acabou de ser adicionado
}

function salvarDependentes() {
  document
    .querySelectorAll("#dependentesContainer .salvar")
    .forEach((el, i) =&amp;gt; {
      el.addEventListener("click", () =&amp;gt; {
        let identificador = el.parentElement.parentElement.getAttribute(
          "data-id"
        );
        let nome = el.parentElement.parentElement.querySelector(".nome").value;
        let idade = el.parentElement.parentElement.querySelector(".idade")
          .value;

        if (!nome.length || !idade.length) {
          alert("Nome e idade precisam ser preenchidos para salvar.");
          return false;
        }
        dependentes.splice(i, 1, {
          identificador: identificador,
          nome: nome,
          idade: idade,
        });
        carregarDependentes(); // Regenerar os elementos HTML após remover do JSON
        travarOutros(false); // Liberar todos os elementos novamente
      });
    });
}

function travarOutros(element) {
  if (element == false) {
    document
      .querySelectorAll(".dependentes button, .dependentes .container &amp;gt; div")
      .forEach((el) =&amp;gt; {
        el.classList.remove("disabled");
      });
    document.querySelector("#containerDados").innerHTML = "";
    return false;
  }
  document
    .querySelectorAll(".dependentes button, .dependentes .container &amp;gt; div")
    .forEach((el) =&amp;gt; {
      if (el != element) {
        el.classList.add("disabled");
      }
    });
}</code></pre>



<p id="block-ab9c8db0-380f-4d31-b0a5-d84dda993870">Agora, tudo o que precisamos fazer é incluir os comandos de inicialização, onde aplicamos o método de adição ao evento de clique do botão e carregamos os dados iniciais do JSON:</p>



<pre class="wp-block-code"><code>//init
document.querySelector("#btnAdicionarDependentes").addEventListener("click", adicionarDependentes);
carregarDependentes();</code></pre>



<p id="block-d689a75a-a671-4218-878b-1e4b41b1034a">Por fim, vamos criar uma função para o botão de capturar dados apenas para extrair e mostrar os dados em JSON. Você pode, eventualmente, usar esses dados e enviar via POST, por AJAX ou via campo oculto, e pegar no back-end para guardar ou processar os dados (como com um json_decoder, do PHP):</p>



<pre class="wp-block-code"><code>//capturarDados
document.querySelector("#btnCapturarDados").addEventListener("click", ()=&amp;gt;{
	document.querySelector("#containerDados").innerHTML = JSON.stringify(dependentes, undefined, 4);
});</code></pre>



<h2 class="wp-block-heading" id="block-525d96fb-9ba9-40d1-b78e-867b44f386a7">CSS</h2>



<p id="block-1ed39d06-f9d5-405c-8d18-47bec57b5d66">O único CSS que precisaremos usar é para aplicar a classe <em>disabled</em>. Se por acaso você está usando algum <em>framework </em>CSS, recomendo que você use o relativo a esta classe deste. Consulte a documentação, onde geralmente está relacionado aos <em>helpers</em>:</p>



<pre class="wp-block-code"><code>.disabled{
  pointer-events: none;
  opacity: .5;
}</code></pre>



<p id="block-6f8b1d9a-075f-4ca6-9508-3128557d4d10">Se você quer usar o CSS mais elaborado que usei aqui, veja abaixo o link do JsFiddle.</p>



<h2 class="wp-block-heading" id="block-fa6cb5c7-c024-4cd6-bca2-b05c15a5988f">Finalizando</h2>



<p id="block-dc6ff86e-45f8-4824-a83a-c908fcc3dca2">Criar formulários dinâmicos auxilia a usabilidade à medida que permite que o usuário adicione dados de forma mais rápida e com respostas visuais imediatas. O uso aqui do Javascript puro visa a facilidade para que você possa implementar em quaisquer projetos, incluindo os com Typescript. Trabalhe um pouco no código para adequá-lo à sua necessidade. E, como sempre, você poderá puxar o código e testar direto do JsFiddle.</p>



<p id="block-5f910d6b-c133-434b-be75-bfeb33999629">Aproveite e entre para nosso grupo de discussão no <a href="https://t.me/designprogramacao" target="_blank" rel="noreferrer noopener">Telegram</a>.</p>



<script async="" src="//jsfiddle.net/velhobit/mwh8f2o1/embed/"></script>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Erro no VCRUNTIME140.dll está impedindo de abrir o Photoshop. Como resolver?</title>
		<link>https://velhobit.com.br/tutoriais/erro-vcruntime140-dll-como-resolver.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Wed, 27 May 2020 22:32:21 +0000</pubDate>
				<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[biblioteca]]></category>
		<category><![CDATA[dll]]></category>
		<category><![CDATA[erros]]></category>
		<category><![CDATA[photoshop]]></category>
		<category><![CDATA[problemas]]></category>
		<category><![CDATA[windows]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1994</guid>

					<description><![CDATA[Após a última atualização do Windows, muitas pessoas (inclusive eu) tem tido relatos sobre um erro constante em todos os aplicativos da Adobe, o erro em questão tem a seguinte mensagem: A execução de código não pode continuar porque VCRUNTIME140.dll não foi encontrado. Reinstalando o programa para corrigir o problema. Erros de português à parte, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Após a última atualização do Windows, muitas pessoas (inclusive eu) tem tido relatos sobre um erro constante em todos os aplicativos da Adobe, o erro em questão tem a seguinte mensagem:</p>



<div class="wp-block-image"><figure class="aligncenter size-large"><img loading="lazy" decoding="async" width="380" height="159" src="https://velhobit.com.br/wp-content/uploads/2020/05/photo_2020-05-27_19-02-02.jpg" alt="" class="wp-image-1995"/></figure></div>



<h4 class="wp-block-heading"><strong>A execução de código não pode continuar porque VCRUNTIME140.dll não foi encontrado. Reinstalando o programa para corrigir o problema.</strong></h4>



<p>Erros de português à parte, talvez você já tenha tentado corrigir o problema reinstalando os programas da Adobe, mas sem sucesso. <strong>Para resolver faça o seguinte, simplesmente você precisa baixar a última versão do  <a rel="noreferrer noopener" href="https://www.visualstudio.com/downloads/" target="_blank">Microsoft Visual C++ Redistribuível para Visual Studio 2015, 2017 e 2019</a>.</strong></p>



<p>Para encontrar a mais recente, simplesmente abra no site específico da Microsoft (<a rel="noreferrer noopener" href="https://support.microsoft.com/pt-br/help/2977003/the-latest-supported-visual-c-downloads" target="_blank">https://support.microsoft.com/pt-br/help/2977003/the-latest-supported-visual-c-downloads</a>) e baixe a versão adequada para seu computador. Como você usa os apps da Adobe, muito provavelmente é o <strong><a rel="noreferrer noopener" href="https://aka.ms/vs/16/release/vc_redist.x64.exe" target="_blank">vc_redist_x64.exe</a></strong> (clique para baixar direto).</p>



<p><strong>Caso esteja na dúvida no tipo de arquitetura do seu Windows, clique com o botão direito no ícone de iniciar e vá em Sistema.</strong></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="837" height="419" src="https://velhobit.com.br/wp-content/uploads/2020/05/image.png" alt="" class="wp-image-1996" srcset="https://velhobit.com.br/wp-content/uploads/2020/05/image.png 837w, https://velhobit.com.br/wp-content/uploads/2020/05/image-400x200.png 400w, https://velhobit.com.br/wp-content/uploads/2020/05/image-768x384.png 768w, https://velhobit.com.br/wp-content/uploads/2020/05/image-600x300.png 600w" sizes="auto, (max-width: 837px) 100vw, 837px" /></figure>



<p>Em Tipo de Sistema, você poderá ver se está usando versão x64, x86 ou ARM e baixar corretamente no site da Microsoft.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>PHP no Windows 10 &#8211; Esqueça o Xampp e Instale o Apache no Subsistema Linux</title>
		<link>https://velhobit.com.br/tutoriais/php-no-windows-10-esqueca-o-xampp-e-instale-o-apache-no-subsistema-linux.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sat, 12 Oct 2019 14:27:19 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[desenvolvedor]]></category>
		<category><![CDATA[desenvolvimento]]></category>
		<category><![CDATA[desevnolvimento]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[programação]]></category>
		<category><![CDATA[programador]]></category>
		<category><![CDATA[wamp]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[wsl]]></category>
		<category><![CDATA[xamp]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1882</guid>

					<description><![CDATA[Trabalhe, mesmo no Windows, com um ambiente mais próximo ao servidor de produção e com mais liberdade. Use o WSL como servidor local de desenvolvimento.]]></description>
										<content:encoded><![CDATA[
<p>Uma das melhores coisas do Windows 10 é a possibilidade de instalar um subsistema Linux nele. Com isso, você pode montar o seu servidor Apache direto nesse subsistema, deixando o ambiente local muito mais similar a onde você vai efetivamente publicar, e com<strong> muito mais performance e liberdade</strong> do que os AMPs disponíveis para o Windows (Xamp, Wamp, Mamp).</p>



<h2 class="wp-block-heading">Habilitando e Instalando o Subsistema</h2>



<p>Primeiro certifique-se que está usando a versão mais recente do Windows 10. Apesar do susbsistema Linux estar disponível há alguns anos, é interessante manter sempre sua máquina atualizada.</p>



<p>Clique em iniciar e digite <strong>Ativar ou Desativar Recursos do Windows</strong>, ou acesse a partir do Painel de Controle Clássico.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="786" height="319" src="https://velhobit.com.br/wp-content/uploads/2019/09/image-1.png" alt="" class="wp-image-1884" srcset="https://velhobit.com.br/wp-content/uploads/2019/09/image-1.png 786w, https://velhobit.com.br/wp-content/uploads/2019/09/image-1-400x162.png 400w, https://velhobit.com.br/wp-content/uploads/2019/09/image-1-768x312.png 768w, https://velhobit.com.br/wp-content/uploads/2019/09/image-1-600x244.png 600w" sizes="auto, (max-width: 786px) 100vw, 786px" /></figure>



<p>Ao abrir, desça a barra de rolagem até encontrar a opção <strong>Subsistema Linux para Windows</strong>. Ative a caixa e pressione em <strong>OK</strong>.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="759" height="737" src="https://velhobit.com.br/wp-content/uploads/2019/09/image-2.png" alt="" class="wp-image-1885" srcset="https://velhobit.com.br/wp-content/uploads/2019/09/image-2.png 759w, https://velhobit.com.br/wp-content/uploads/2019/09/image-2-400x388.png 400w, https://velhobit.com.br/wp-content/uploads/2019/09/image-2-600x583.png 600w" sizes="auto, (max-width: 759px) 100vw, 759px" /></figure>



<p>O Windows pedirá para reiniciar o sistema e fará alguns ajustes, para então permitir que você possa instalar uma distribuição Linux.</p>



<p>Uma vez reiniciado, você já pode fazer a instalação da distribuição. Para isso abra <strong>Microsoft Store</strong>. Na guia <strong>Pesquisar</strong>, pesquise por Linux. Uma grande opção contendo várias distribuições será mostrada a você.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="737" src="https://velhobit.com.br/wp-content/uploads/2019/09/image-3-1024x737.png" alt="" class="wp-image-1886" srcset="https://velhobit.com.br/wp-content/uploads/2019/09/image-3-1024x737.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/09/image-3-400x288.png 400w, https://velhobit.com.br/wp-content/uploads/2019/09/image-3-768x553.png 768w, https://velhobit.com.br/wp-content/uploads/2019/09/image-3-600x432.png 600w, https://velhobit.com.br/wp-content/uploads/2019/09/image-3.png 1365w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="633" src="https://velhobit.com.br/wp-content/uploads/2019/09/image-4-1024x633.png" alt="" class="wp-image-1887" srcset="https://velhobit.com.br/wp-content/uploads/2019/09/image-4-1024x633.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/09/image-4-400x247.png 400w, https://velhobit.com.br/wp-content/uploads/2019/09/image-4-768x475.png 768w, https://velhobit.com.br/wp-content/uploads/2019/09/image-4-600x371.png 600w, https://velhobit.com.br/wp-content/uploads/2019/09/image-4.png 1381w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Escolha a distribuição que melhor funcionar para você. Nesta demonstração iremos usar o Ubuntu, mas se você preferir uma distribuição baseada em outra distro, fique à vontade. Porém a integração do Ubuntu com o Windows é trabalhada em conjunto entre a Microsoft e a própria Canonical, o que deve garantir, teoricamente, uma integração melhor.</p>



<p>Para você trabalhar com o Subsistema Linux, você pode usar o próprio Prompt de Comando, ou o Power Shell, porém, a Microsoft lançou recentemente um Terminal para o Windows. Esse novo Terminal pode ser baixado diretamente pela Microsoft Store e é altamente recomendável seu uso, pois ele traz muitas melhorias para a usabilidade do <strong>WSL (<em>Windows  Subsystem Linux</em>)</strong>. </p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="312" src="https://velhobit.com.br/wp-content/uploads/2019/09/image-5-1024x312.png" alt="" class="wp-image-1888" srcset="https://velhobit.com.br/wp-content/uploads/2019/09/image-5-1024x312.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/09/image-5-400x122.png 400w, https://velhobit.com.br/wp-content/uploads/2019/09/image-5-768x234.png 768w, https://velhobit.com.br/wp-content/uploads/2019/09/image-5-600x183.png 600w, https://velhobit.com.br/wp-content/uploads/2019/09/image-5.png 1386w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Para finalizar a instalação, simplesmente abra o Terminal e digite: ubuntu (ou o nome da distribuição que você escolheu) e aguarde a instalação. Ele pedirá para você criar uma conta de administrador e a senha.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="270" height="249" src="https://velhobit.com.br/wp-content/uploads/2019/09/image-6.png" alt="" class="wp-image-1889"/></figure>



<p>Após instalar, se você fechar e abrir o Terminal, notará que apareceu mais uma opção para nova aba. Caso você prefira, você pode editar, em Settings, para que o Ubuntu seja o padrão, simplesmente alterando a configuração em seu json. Porém, se preferir, você também pode abrir o Ubuntu simplesmente digitando pelo OS a partir da barra de pesquisas, mas nesse caso ele abrirá o terminal dentro do console padrão do Windows.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="786" height="677" src="https://velhobit.com.br/wp-content/uploads/2019/10/image.png" alt="" class="wp-image-1900" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image.png 786w, https://velhobit.com.br/wp-content/uploads/2019/10/image-400x345.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-768x661.png 768w, https://velhobit.com.br/wp-content/uploads/2019/10/image-600x517.png 600w" sizes="auto, (max-width: 786px) 100vw, 786px" /></figure>



<h2 class="wp-block-heading">Instalando o PHP e MySQL em seu Ubuntu Linux</h2>



<p>A partir daqui não é diferente de instalar em um Ubuntu completo, porém, como a maioria dos usuários de Windows não possui familiaridade com os sistemas baseados em Linux, vamos detalhar passo a passo.</p>



<p class="has-very-light-gray-background-color has-background"><strong>Obs</strong>: Se você quiser copiar o código aqui digitado, você pode digitar <strong>ctrl+c</strong> aqui e, no terminal, apenas clicar com o botão direito (esta ação será equivalente ao<strong> ctrl+v</strong>).</p>



<p>Antes de tudo, vamos dar um update para preparar o ambiente.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo apt-get update</textarea></pre>
</div>



<h3 class="wp-block-heading">Instalando o Apache 2</h3>



<p>Para instalar o servidor do Apache, e verificar se a instalação está correta, simplesmente use os comandos abaixo, no Terminal:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo apt-get install apache2
sudo service apache2 start
sudo service apache2 status</textarea></pre>
</div>



<p>Ao iniciar o apache, é possível que você receba a seguinte mensagem:</p>



<p class="has-luminous-vivid-amber-color has-very-dark-gray-background-color has-text-color has-background">Windows TerminalProtocol not available: AH00076: Failed to enable APR_TCP_DEFER_ACCEPT</p>



<p>Não se preocupe com esse problema. Simplesmente esse protocolo ainda não está nativamente implementado no WSL. Você pode apenas ignorar ou adicionar as seguintes linhas no arquivo<strong> /etc/apache2/apache2.conf</strong> :</p>



<pre class="wp-block-code"><code>AcceptFilter https none
AcceptFilter http none</code></pre>



<h2 class="wp-block-heading">Instalando o PHP</h2>



<p>Instalaremos o PHP 7.4 (então versão mais atual na última atualização deste post), mas você pode utilizar qualquer tutorial para Ubuntu para outras versões, ou simplesmente trocar os caminhos aqui associados. Atualizaremos este post conforme forem surgindo novas atualizações. Digite <strong>Y</strong> (yes) para tudo o que for perguntado.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo apt-get update
sudo apt-get install php php-cli php-fpm php-json php7.4-pdo php7.4-mysql php-zip php-gd  php-mbstring php-curl php-xml php-pear php-bcmath
php -v</textarea></pre>
</div>



<p>Instlamos, assim, o cliente e os pacotes mais utilizados, mas você pode, futuramente, instalar pacotes adicionais para funções específicas. A terceira linha apenas verifica a versão do PHP instalada, para checar se está tudo correto.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="187" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-1-1024x187.png" alt="" class="wp-image-1901" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-1-1024x187.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/10/image-1-400x73.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-1-768x140.png 768w, https://velhobit.com.br/wp-content/uploads/2019/10/image-1-600x109.png 600w, https://velhobit.com.br/wp-content/uploads/2019/10/image-1.png 1504w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Instalando o MySQL</h2>



<p>Por último vamos instalar o MySQL. Você pode trabalhar com outros bancos de dados se quiser, basta, como dito anteriormente, usar qualquer tutorial para Ubuntu (ou a distro que você escolheu), pois, relembrando, o WSL é realmente um subsistema Linux instalado e integrado ao Windows. Ele não é uma máquina virtual ou emulação. Lembre-se de pressionar o <strong>Y</strong>, quando perguntado.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo apt-get install mysql-server mysql-client libmysqlclient-dev
sudo service mysql start</textarea></pre>
</div>



<p>Caso perguntado, você pode ou não definir uma senha para o root do MySQL. Como você está em um ambiente de desenvolvimento, isso não é importante por hora. Mas lembre-se que em ambientes de produção uma senha forte deve ser usada.</p>



<h3 class="wp-block-heading">Garantindo todos os privilégios para usuário administrador</h3>



<p>Para você poder gerenciar todos os bancos e não ter que criar um usuário para cada um, você pode criar um usuário administrador e facilitar seu trabalho. Use o código abaixo para acessar o cliente mysql. Use a senha criada anteriormente.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo mysql -u root -p</textarea></pre>
</div>



<p>Agora, use o código abaixo para criar o usuário administrador e você poder trabalhar de forma universal.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
CREATE USER 'nome_de_usuario'@'localhost' IDENTIFIED BY 'sua_senha';
GRANT ALL PRIVILEGES ON *.* TO 'nome_de_usuario'@'localhost';</textarea></pre>
</div>



<p>Digite <strong>\q </strong>para sair do cliente.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="240" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-3-1024x240.png" alt="" class="wp-image-1903" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-3-1024x240.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/10/image-3-400x94.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-3-768x180.png 768w, https://velhobit.com.br/wp-content/uploads/2019/10/image-3-600x141.png 600w, https://velhobit.com.br/wp-content/uploads/2019/10/image-3.png 1262w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h3 class="wp-block-heading">PHPMyAdmin</h3>



<p>Você pode usar algum cliente externo para administrar o MySQL, mas a opção mais comum usada é instalar o PHPMyAdmin. Simplesmente utilize o seguinte comando:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo apt-get install phpmyadmin</textarea></pre>
</div>



<p>Obs. A instalação irá perguntar se deseja instalar apache ou nginx, neste caso marque apache. <strong>Para marcar pressione espaço, se não fizer isso ele não instalará corretamente e você precisará rodar a instalação novamente.</strong></p>



<p>Durante a instalação, você será questionado para criar uma senha para o PHPMyAdmin, caso deseje.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="555" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-2-1024x555.png" alt="" class="wp-image-1902" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-2-1024x555.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/10/image-2-400x217.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-2-768x416.png 768w, https://velhobit.com.br/wp-content/uploads/2019/10/image-2-600x325.png 600w, https://velhobit.com.br/wp-content/uploads/2019/10/image-2.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Testando</h2>



<p>Uma vez que já instalamos e já inicializamos, podemos testar simplesmente acessando <strong>http://localhost</strong>. Para o PHPMyAdmin, use <strong>http://localhost/phpmyadmin</strong></p>



<p>Para entrar no PHPMyAdmin, utilize o usuário e senha criado acima, com os privilégios:</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="698" height="896" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-4.png" alt="" class="wp-image-1904" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-4.png 698w, https://velhobit.com.br/wp-content/uploads/2019/10/image-4-312x400.png 312w, https://velhobit.com.br/wp-content/uploads/2019/10/image-4-467x600.png 467w" sizes="auto, (max-width: 698px) 100vw, 698px" /></figure>



<h2 class="wp-block-heading">Habilitando as configurações do Apache</h2>



<p>Para poder funcionar corretamente certas opções, como o habilitar .htaccess, habilitar ou desabilitar determinados módulos, configurar max_*, etc., é ideal que você configure o Apache Virtual Hosts.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo bash -c "a2ensite '*.conf' &amp;&amp; a2dissite 000-default.conf default-ssl.conf &amp;&amp; systemctl restart apache2.service"</textarea></pre>
</div>



<p>Feito isso, você pode configurar o VirtualHost para diversos sites, portas, ou simplesmente especificando configurações específicas para cada site / sistema em que você está trabalhando.</p>



<p>O arquivo de configuração gerado, fica em: <strong>/etc/apache2/sites-available/000-default.conf</strong></p>



<h2 class="text-roxo wp-block-heading">Informações Importantes</h2>



<p>Você pode iniciar o apache e o mysql a qualquer momento, simplesmente abrindo o Windows Terminal, no Ubuntu (ou direto pelo app Ubuntu) e colocando:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo service apache2 start
sudo service mysql start</textarea></pre>
</div>



<p class="has-background" style="background-color:#fff8d7">A pasta padrão dos arquivos do Apache é:<br><strong>/var/www/html </strong></p>



<p>Para você abrir a pasta no Windows Explorer e você ver o os arquivos, digite no Terminal:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
cd /var/www/html/
explorer.exe .</textarea></pre>
</div>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="349" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-5-1024x349.png" alt="" class="wp-image-1906" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-5-1024x349.png 1024w, https://velhobit.com.br/wp-content/uploads/2019/10/image-5-400x136.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-5-768x262.png 768w, https://velhobit.com.br/wp-content/uploads/2019/10/image-5-600x204.png 600w, https://velhobit.com.br/wp-content/uploads/2019/10/image-5.png 1920w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Recomendo que, para você poder operar sem problemas, no Windows, você execute, para dar permissão total:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo chmod -R 777 /var/www/html/</textarea></pre>
</div>



<h2 class="wp-block-heading">Extra: Criando um SSL autoassinado</h2>



<p>Dependendo do que você estiver programando, pode ser necessário você utilizar uma conexão SSL. Isso geralmente é necessário em testes que irão alimentar diversas APIs ou até para utilizar alguns recursos do HTML5.</p>



<p>O Ubuntu já possui o openssl instalado nativamente no sistema. Então, basta você colocar:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/apache-selfsigned.key -out /etc/ssl/certs/apache-selfsigned.crt</textarea></pre>
</div>



<p>Enquanto você estiver criando o certificado, ele irá fazer algumas perguntas de identificação. Como é algo que vai ser usado localmente, essas informações não precisam ser reais ou fidedignas, basta responder. A ordem é:</p>



<ul class="wp-block-list"><li>Nome de País (em código de 2 dígitos) &#8211; Brasil é BR</li><li>Estado</li><li>Cidade</li><li>Nome da Organização</li><li>Unidade da Organização</li><li>Common Name &#8211; Digite <strong>localhost</strong></li><li>E-mail &#8211; Digite<strong> webmaster@localhost</strong></li></ul>



<p>Isso vai ser suficiente para criar um certificado auto-assinado, que vai funcionar localmente.</p>



<p>Agora vamos nas configurações do Virtual Hosts do Apache, para SSL.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo nano /etc/apache2/conf-available/ssl-params.conf</textarea></pre>
</div>



<p>Dentro do arquivo, cole o seguinte texto (é uma configuração genérica, mas suficiente para nosso caso):</p>



<pre class="wp-block-code"><code>SSLCipherSuite EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH
SSLProtocol All -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLHonorCipherOrder On
# Disable preloading HSTS for now.  You can use the commented out header line that includes
# the "preload" directive if you understand the implications.
# Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
# Requires Apache &gt;= 2.4
SSLCompression off
SSLUseStapling on
SSLStaplingCache "shmcb:logs/stapling-cache(150000)"
# Requires Apache &gt;= 2.4.11
SSLSessionTickets Off</code></pre>



<p class="has-very-light-gray-background-color has-background">Obs. Digite CTRL+X, seguido de Y, seguido de ENTER, para fechar o nano, salvando.</p>



<p>Agora vamos editar a configuração do SSL.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo nano /etc/apache2/sites-available/default-ssl.conf</textarea></pre>
</div>



<p>Com o arquivo aberto, você vai substituir os parâmetros abaixo, de acordo com o demonstrado na lista:</p>



<pre class="wp-block-code"><code>ServerAdmin webmaster@localhost.com
ServerName localhost

SSLCertificateFile /etc/ssl/certs/apache-selfsigned.crt
SSLCertificateKeyFile /etc/ssl/private/apache-selfsigned.key</code></pre>



<p>Por fim, basta colocar no terminal, para ativar o ssl no Apache:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo a2enmod ssl
sudo a2enmod headers
sudo a2ensite default-ssl
sudo a2enconf ssl-params
sudo apache2ctl configtest</textarea></pre>
</div>



<p>Se estiver tudo configurado corretamente, ele vai responder SINTAX OK.</p>



<p>Antes de recarregar o Apache, teremos que liberar a pasta onde salvamos o  certificado. Vamos liberar para 777, para facilitar, apenas porque estamos em ambiente de desenvolvimento. JAMAIS FAÇA ISSO EM AMBIENTE DE PRODUÇÃO.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
sudo chmod -R 777 /etc/ssl/private
service apache2 reload</textarea></pre>
</div>



<p>Por fim, precisamos adicionar o SSL como confiável no Windows. Caso contrário, ao entrar em https://localhost, você vai receber aquela clássica tela de certificado não confiável.</p>



<p>Agora vá até a pasta onde você baixou o certificado e abra a pasta no explorer. Procure pelo arquivo do certificado <strong>apache-selfsigned.crt</strong>. Clique duas vezes nele para instalar no Windows.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="shell" name="mshighlighter" >
cd /etc/ssl/certs/ 
explorer.exe .</textarea></pre>
</div>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="821" height="622" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-6.png" alt="" class="wp-image-1907" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-6.png 821w, https://velhobit.com.br/wp-content/uploads/2019/10/image-6-400x303.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-6-768x582.png 768w, https://velhobit.com.br/wp-content/uploads/2019/10/image-6-600x455.png 600w" sizes="auto, (max-width: 821px) 100vw, 821px" /></figure>



<p>Ao abrir o certificado, clique no botão <strong>Instalar Certificado</strong></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="405" height="515" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-7.png" alt="" class="wp-image-1908" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-7.png 405w, https://velhobit.com.br/wp-content/uploads/2019/10/image-7-315x400.png 315w" sizes="auto, (max-width: 405px) 100vw, 405px" /></figure>



<p>Simplesmente siga os passos para a instalação do certificado</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="535" height="523" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-8.png" alt="" class="wp-image-1909" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-8.png 535w, https://velhobit.com.br/wp-content/uploads/2019/10/image-8-400x391.png 400w" sizes="auto, (max-width: 535px) 100vw, 535px" /></figure>



<p>Na área de Importação, selecione para colocar no repositório de <strong>Autoridades de Certificações Confiáveis</strong>, como nas imagens abaixo.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="281" height="263" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-12.png" alt="" class="wp-image-1913"/></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="535" height="523" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-13.png" alt="" class="wp-image-1914" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-13.png 535w, https://velhobit.com.br/wp-content/uploads/2019/10/image-13-400x391.png 400w" sizes="auto, (max-width: 535px) 100vw, 535px" /></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="535" height="523" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-14.png" alt="" class="wp-image-1915" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-14.png 535w, https://velhobit.com.br/wp-content/uploads/2019/10/image-14-400x391.png 400w" sizes="auto, (max-width: 535px) 100vw, 535px" /></figure>



<p>Você vai precisar confirmar a instalação do certificado. Marque Sim.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="412" height="380" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-15.png" alt="" class="wp-image-1916" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-15.png 412w, https://velhobit.com.br/wp-content/uploads/2019/10/image-15-400x369.png 400w" sizes="auto, (max-width: 412px) 100vw, 412px" /></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="271" height="152" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-11.png" alt="" class="wp-image-1912"/></figure>



<p>Agora é só acessar o localhost com https e ser feliz!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="754" height="570" src="https://velhobit.com.br/wp-content/uploads/2019/10/image-16.png" alt="" class="wp-image-1917" srcset="https://velhobit.com.br/wp-content/uploads/2019/10/image-16.png 754w, https://velhobit.com.br/wp-content/uploads/2019/10/image-16-400x302.png 400w, https://velhobit.com.br/wp-content/uploads/2019/10/image-16-600x454.png 600w" sizes="auto, (max-width: 754px) 100vw, 754px" /></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>API do Whatsapp &#8211; Como quebrar linhas e passar parâmetros em links</title>
		<link>https://velhobit.com.br/tutoriais/api-do-whatsapp-como-quebrar-linhas-e-passar-parametros-em-links.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Wed, 20 Mar 2019 19:56:48 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[chat]]></category>
		<category><![CDATA[compartilhamento]]></category>
		<category><![CDATA[whatsapp]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1822</guid>

					<description><![CDATA[Um exemplo de como criar um link/botão para iniciar automaticamente um chat pelo Whatsapp]]></description>
										<content:encoded><![CDATA[
<p class="has-drop-cap">Quase todo site, sistema, ou app, hoje, precisa ter um botão para compartilhamento via Whatsapp. Para facilitar todo esse processo, o <a href="https://developers.facebook.com/docs/whatsapp/api/reference/?translation">Whatsapp disponibiliza uma API</a> própria para facilitar o processo para desenvolvedores.</p>



<p>Porém, para o trabalho mais básico, um simples link de interação com um início de conversa, a documentação não é muito clara quanto a caracteres especiais e links.</p>



<div class="genova">
<input type="text" id="celular" placeholder="Digite numero do telefone com DDD">
<textarea id="mensagem" placeholder="digite mensagem de teste">Mensagem de Teste:
Doom?token=iddqd</textarea>

<button onclick="enviarMensagem()">
Enviar Mensagem
</button>
</div>



<h2 class="wp-block-heading">Criando um link para iniciar a conversa</h2>



<p>Para você criar um link para iniciar uma conversa, basta usar a URL <strong><em>https://api.whatsapp.com/send</em></strong> e passar os parâmetros específicos.</p>



<p>Na prática, você poderia passar algo como:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" >
<a href="https://api.whatsapp.com/send?phone=telefonecompleto&amp;text=TextoParaEnviar">Enviar Mensagem</a></textarea></pre>
</div>



<p class="has-very-light-gray-background-color has-background"><strong>Importante:</strong> O telefone deve conter DDI e DDD e ser apenas número. Por exemplo, você vai mandar uma mensagem para alguém de Recife/PE &#8211; Brasil, o telefone precisa ser: 5581numero_do_celular.</p>



<p>Até aí é bem simples. O problema está quando você quer enviar um parâmetro em um link, ou quando você quer enviar caracteres especiais como quebra de texto. O que vai acontecer é que a API do Whatsapp simplesmente irá remover qualquer tipo de código que ele considerar inseguro, através de um processo chamado de <strong>Sanitização</strong>.</p>



<p>O Whatsapp, entretanto, utiliza-se de uma versão própria de parâmetros simples para tratar <em>richtexts</em>. Ou seja, simplesmente basta você converter os valores que você quer para <strong>URL <em>Encode</em></strong>. Isso fará com que o texto seja entregue da forma como você planejou e você possa aplicar caracteres especiais e formatação.</p>



<h2 class="wp-block-heading">Exemplo prático</h2>



<p>Digamos que você queira enviar a seguinte mensagem:</p>



<p class="has-background" style="background-color:#bbe5ff">A pia pinga, o pinto pia&#8230;<br>Quanto mais a pia pinga, mais o pinto pia.<br><br>Acesse https://ratimbum.com/?token=333 para saber mais.</p>



<p>Perceba que o texto possui negrito e quebra de texto e seu código será algo como:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" >
A pia pinga, o pinto pia...\n
Quanto mais a pia pinga, mais o pinto pia.\n\n
Acesse https://ratimbum.com/?token=333 para saber mais.</textarea></pre>
</div>



<p>Sim, você deverá usar \n para quebrar o texto. Porém, a sanitização vai retirar o \n e o ?, o que vai criar um resultado não esperado.</p>



<p>Para resolver o problema, basta você converter o texto para URL Encode. No <em><strong>javascript</strong></em>, por exemplo, ficará assim:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >
var texto = "A pia pinga, o pinto pia...\n
Quanto mais a pia pinga, mais o pinto pia.\n\n
Acesse https://ratimbum.com/?token=333 para saber mais.";
texto = window.encodeURIComponent(texto);

/*
O resultado será algo como:
A%20pia%20pinga%2C%20o%20pinto%20pia...%0A%0AQuanto%20mais%20a%20pia%20pinga%2C%20mais%20o%20pinto%20pia.%0A%0AAcesse%20https%3A%2F%2Fratimbum.com%2F%3Ftoken%3D333%20para%20saber%20mais.
*/</textarea></pre>
</div>



<p>Dessa forma, você pode optar por colocar esse código dinamicamente em um <strong>&lt;a&gt;</strong> ou, o que recomendo, enviar através da função <strong>window.open</strong>, do Javascript.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >
function enviarMensagem(){
	var celular = "55DDDNUMERODOCELULAR";
  
  var texto = "Texto que eu vou enviar \n com quebras de \n texto.";
  texto = window.encodeURIComponent(texto);
  
  window.open("https://api.whatsapp.com/send?phone=" + celular + "&amp;text=" + texto, "_blank");
	//Obs.. use "_system", no lugar de blank, caso você esteja usando Phonegap / Cordova / Ionic ou qualquer um baseado em webview;
}</textarea></pre>
</div>



<p class="has-very-light-gray-background-color has-background">Obs. Você não precisa converter para \n se for pegar o texto a partir de um <strong>&lt;textarea&gt;</strong>, como mostrado no exemplo mais abaixo.</p>



<p>É importante salientar que se você estiver testando no Whatsapp web, a quebra de linha não é mostrada na pre-visualização, mas será mostrada no momento do envio real da imagem.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1024" height="451" src="https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-1-1024x451.jpg" alt="" class="wp-image-1823" srcset="https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-1-1024x451.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-1-400x176.jpg 400w, https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-1-768x338.jpg 768w, https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-1-600x264.jpg 600w, https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-1.jpg 1233w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Durante a pré-visualização não é mostrado a quebra de linha&#8230;</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="753" height="139" src="https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-002.jpg" alt="" class="wp-image-1824" srcset="https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-002.jpg 753w, https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-002-400x74.jpg 400w, https://velhobit.com.br/wp-content/uploads/2019/03/whatsapp-002-600x111.jpg 600w" sizes="auto, (max-width: 753px) 100vw, 753px" /><figcaption>&#8230; mas na hora realmente do envio ele vai ter a quebra de linha.</figcaption></figure>



<h2 class="wp-block-heading">Corrigindo erro ERR_BLOCKED_BY_RESPONSE</h2>



<p>Foi relatado que, em alguns casos, ocorre o erro ERR_BLOCKED_BY_RESPONSE, em alguns navegadores ou condições específicas (principalmente no Firefox). Isso ocorreu devido a algumas atualizações não bem descritas da API do Whatsapp.</p>



<p>Para corrigir esse problema, faremos uma pequena atualização no código acima, o qual será necessário verificar se é mobile ou não, e passar o prefixo web no lugar de api. Acredito que também exista uma correlação quanto a navegadores desatualizados, que estejam causando o problema.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >
function enviarMensagem(){
	var celular = "55DDDNUMERODOCELULAR";
  
  var texto = "Texto que eu vou enviar \n com quebras de \n texto.";
  texto = window.encodeURIComponent(texto);

  let urlApi = "https://web.whatsapp.com/send";
  if(mobileCheck()){
  	urlApi = "https://api.whatsapp.com/send";
  }
  
  window.open(urlApi + "?phone=" + celular + "&text=" + texto, "_blank");
	//Obs.. use "_system", no lugar de blank, caso você esteja usando Phonegap / Cordova / Ionic ou qualquer um baseado em webview;
}


function mobileCheck(){
  let check = false;
  (function(a){if(/(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino/i.test(a)||/1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-/i.test(a.substr(0,4))) check = true;})(navigator.userAgent||navigator.vendor||window.opera);
  return check;
}</textarea></pre>
</div>



<p>Ocorre também que o código questão modifica um comportamento. Ele não mais alertará o usuário de que uma mensagem será enviada. Ao contrário disso, ele já abre direto no Whatsapp web.</p>



<h2 class="wp-block-heading">Outras opções</h2>



<p>Se o intuito, porém, for utilizar também outras propriedades do richtext, como negrito e itálico, você deverá simplesmente passar _ (itálico), * (negrito), ~ (riscado) ou &#8220;` (tamanho fixo). Exemplo:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >
var mensagemParaWpp = mensagem.replace(/<b>/g, "*").replace(/<\/b>/g,"*"); 
alert(s);</textarea></pre>
</div>



<p>Como sempre, no final do post tem um código de exemplo, onde você pode testar o envio de mensagem ou apenas copiar o código.</p>



<p class="has-very-light-gray-background-color has-text-color has-background has-small-font-size" style="color:#868788">(O código está compartilhado pelo jsfiddle. Então, para ver corretamente, use pelo desktop/laptop)</p>



<iframe loading="lazy" width="100%" height="300" src="//jsfiddle.net/velhobit/7r94u3vd/16/embedded/js,html,css,result/dark/" allowfullscreen="allowfullscreen" allowpaymentrequest frameborder="0"></iframe>



<p>Gostou da postagem? Siga nossas mídias sociais e compartilhe com os coleguinhas.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como criar um uploader drag &#038; drop, AJAX com porcentagem e Javascript puro?</title>
		<link>https://velhobit.com.br/programacao/como-criar-um-uploader-drag-drop-ajax-com-porcentagem-e-javascript-puro.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Fri, 01 Feb 2019 05:19:03 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Design]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[componentes]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[drag]]></category>
		<category><![CDATA[drop]]></category>
		<category><![CDATA[efeito]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[upload]]></category>
		<category><![CDATA[uploader]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1806</guid>

					<description><![CDATA[Um breve tutorial para mostrar como fazer um uploader HTML5 de múltiplos, com porcentagem, drag 'n drop e, o melhor, com Javascript puro!]]></description>
										<content:encoded><![CDATA[
<p>Eu sei, o título é grande, mas trata-se de uma tecnologia muito útil quanto a usabilidade. A ideia é criar, da forma mais simples possível um <em>uploader</em> que mostre a porcentagem do que está sendo enviado, com múltiplos arquivos. Porém, não apenas isso, mas da forma mais pura possível, sem a necessidade de <em>frameworks</em>, bibliotecas de terceiros ou pre-processadores.  <strong>Em nosso tutorial, usaremos PHP no back-end, mas você pode usar a linguagem que melhor lhe adequar</strong>. Abaixo você pode testar um exemplo:</p>



<div class="area-upload">
			<label for="upload-file" class="label-upload">
				<i class="fas fa-cloud-upload-alt"></i>
				<div class="texto">Clique ou arraste o arquivo</div>
			</label>
			<input type="file" accept="image/jpg,image/png" id="upload-file" multiple="">
			
			<div class="lista-uploads">
			</div>
		</div>



<p style="background-color:#fff4d4" class="has-text-color has-background has-vivid-red-color">DISCLAIMER: Para preservar você, o blog e a mim, o upload.php do exemplo não está fazendo upload de verdade, então você não vai ter acesso ao arquivo no final, porém, no link do github está o código funcional.</p>



<!-- Place this tag where you want the button to render. -->
<center><a class="github-button" href="https://github.com/velhobit/upload-html/archive/master.zip" data-size="large" aria-label="Download velhobit/upload-html on GitHub">Download</a></center>



<h2 class="wp-block-heading">HTML</h2>



<p>Antes de prosseguir, vou alertar que estou usando o <em><a rel="noreferrer noopener" aria-label="font-awesome  (abre em uma nova aba)" href="https://velhobit.com.br/design/como-criar-sua-propria-fonte-e-a-usar-como-icone.html" target="_blank">font-awesome</a></em><a rel="noreferrer noopener" aria-label="font-awesome  (abre em uma nova aba)" href="https://velhobit.com.br/design/como-criar-sua-propria-fonte-e-a-usar-como-icone.html" target="_blank"> </a>no exemplo, apenas para não ter que fazer nenhum <em>upload</em> de imagens por hora, mas ele não é obrigado para o que vamos fazer.</p>



<p>Iniciaremos com um HTML bem simples. Vamos definir apenas a área de <em>upload</em>, da lista e uma área onde ficará o <em>input</em>. Esse input deve ser do tipo file e deve estar com o atributo <em>mutiple</em> definido. Nada muito especial por enquanto, pois nosso trunfo está mais no CSS e Javascript.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><div class="area-upload">
			<label for="upload-file" class="label-upload">
				<i class="fas fa-cloud-upload-alt"></i>
				<div class="texto">Clique ou arraste o arquivo</div>
			</label>
			<input type="file" accept="image/jpg,image/png" id="upload-file" multiple/>
			
			<div class="lista-uploads">
			</div>
		</div></textarea></pre>
</div>



<h2 class="wp-block-heading">CSS3</h2>



<p>O CSS que usaremos tem pontos específicos aos quais devemos prestar atenção. Por isso, vamos ver por trechos:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >.area-upload{
	box-shadow: 0 5px 20px rgba(0,0,0,.2);
	margin: 20px auto;
	padding: 20px;
	box-sizing: border-box;
	
	width: 100%;
	max-width: 700px;
	position: relative;
}

.area-upload label.label-upload{
	border: 2px dashed #0d8acd;
	min-height: 200px;
	text-align: center;
	width: 100%;
	
	display: flex;
	justify-content: center;
	flex-direction: column;
	color: #0d8acd;
	position: relative;
	
	-webkit-transition: .3s all;
	-moz-transition: .3s all;
	-o-transition: .3s all;
	transition: .3s all;
}

.area-upload label.label-upload.highlight{
	background-color: #fffdaa;
}

.area-upload label.label-upload *{
	pointer-events: none;
}</textarea></pre>
</div>



<p>A área de <em>upload</em> é definida pelo CSS a partir de um espaço abrangente. O <em>label</em>, vai ser a referência que vamos usar para atingir toda a área pré-determinada e é o que vai também receber o estilo que indicará onde e quando pode soltar o objeto. Dessa forma, deve estar com um <em>position: absolute</em>, pegando toda a área do <em>upload</em>. Um detalhe importante é que esse label não pode possuir filhos com eventos do mouse, pois isso pode acarretar em funcionamento inadequado ao fazer um <em>hover</em> em uma área não indicada.</p>



<p>A área marcada como <em>hightlight</em> é justamente para demonstrar ao usuário que ele já pode soltar o arquivo.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >
.area-upload input{
	position: absolute;
	left: 0;
	top: 0;
	right: 0;
	bottom: 0;
	width: 100%;
	-webkit-appearance: none;
	opacity: 0;
}</textarea></pre>
</div>



<p>O <em>input</em> vai nos servir de área de <em>drop</em>. Isso já é um padrão tanto para <em>Windows</em>, <em>MacOS</em> e <em>Linux</em> – de receber um (ou mais arquivos) arrastando os dados para o botão. Retirando a aparência padrão, podemos nos aproveitar dessa função e economizar várias linhas de código do <em>Javascript</em>. Não havendo a necessidade de configurarmos eventos de arquivos.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >.area-upload .lista-uploads .barra{
	background-color: #e6e6e6;
	margin: 10px 0;
	width: 100%;
	position: relative;
}

.area-upload .lista-uploads .barra .fill{
	background-color: #a1f7ff;
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	min-width: 0;
	
	-webkit-transition: .2s all;
	-moz-transition: .2s all;
	-o-transition: .2s all;
	transition: .2s all;
}

.area-upload .lista-uploads .barra.complete .fill{
	background-color: #bcffdf;
}

.area-upload .lista-uploads .barra .text{
	z-index: 10;
	text-align: center;
	padding: 3px 5px;
	box-sizing: border-box;
	position: relative;
	width: 100%;
	color: black;
	font-size: 12px;
}
.area-upload .lista-uploads .barra .text a{
	color: black;
	font-weight: bold;
}

.area-upload .lista-uploads .barra.error .fill{	
	background-color: #c02929;
	color: white;
	min-width: 100%;
}

.area-upload .lista-uploads .barra.error .text{
	color: white;
}</textarea></pre>
</div>



<p>Talvez a área que possa confundir um pouco mais, principalmente os mais novatos, seja o CSS referente as barras de <em>loading</em>. As barras são definidas como <em>relative</em> e seu conteúdo como <em>absolute</em>. Dessa forma, podemos herdar a porcentagem do <em>upload</em> e usá-la diretamente no <em>min-width</em> do elemento. Usamos <em>min-width</em>, ao invés de <em>width</em> para utilizar o <em>transition</em>, dando uma leveza no <em>upload</em> ao invés de pequenos estalos.</p>



<h2 class="wp-block-heading">Javascript</h2>



<p>Inicialmente iremos definir os efeitos de <em>drag</em> and <em>drop</em>. Utilizaremos os eventos específicos para adicionar ou retirar o css de <em>hightlight</em>. Aquele que falamos acima ao montar o CSS.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >let drop_ = document.querySelector('.area-upload #upload-file');
drop_.addEventListener('dragenter', function(){
	document.querySelector('.area-upload .label-upload').classList.add('highlight');
});
drop_.addEventListener('dragleave', function(){
	document.querySelector('.area-upload .label-upload').classList.remove('highlight');
});
drop_.addEventListener('drop', function(){
	document.querySelector('.area-upload .label-upload').classList.remove('highlight');
});</textarea></pre>
</div>



<p>Agora precisamos validar os dados antes de colocar em nosso servidor. Compusemos uma validação que verifica o tipo de arquivo e a quantidade máxima de 2MB. Essa validação é totalmente no <em>front-end</em>. É recomendado que você também faça uma validação posterior no <em>back-end</em> para evitar fraudes. Essa função receberá como parâmetro um arquivo, o qual faremos a validação.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >function validarArquivo(file){
	console.log(file);
	// Tipos permitidos
	var mime_types = [ 'image/jpeg', 'image/png' ];
	
	// Validar os tipos
	if(mime_types.indexOf(file.type) == -1) {
		return {"error" : "O arquivo " + file.name + " não permitido"};
	}

	// Apenas 2MB é permitido
	if(file.size > 2*1024*1024) {
		return {"error" : file.name + " ultrapassou limite de 2MB"};
	}

	// Se der tudo certo
	return {"success": "Enviando: " + file.name};
}</textarea></pre>
</div>



<p>Para enviar os arquivos, usaremos uma função AJAX simples. Fazemos um <em>request</em> no método POST. Nesta função, iremos capturar também a porcentagem do <em>upload</em> e atualizaremos a barra a partir desta, através do evento <em>progress</em>. Essa nossa função receberá o índice, para identificar o arquivo que está sendo enviado e a barra que será modificada.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >function enviarArquivo(indice, barra){
	var data = new FormData();
	var request = new XMLHttpRequest();
	
	//Adicionar arquivo
	data.append('file', document.querySelector('#upload-file').files[indice]);
	
	// AJAX request finished
	request.addEventListener('load', function(e) {
		// Resposta
		if(request.response.status == "success"){
			barra.querySelector(".text").innerHTML = "<a href=\"" + request.response.path + "\" target=\"_blank\">" + request.response.name + "</a> <i class=\"fas fa-check\"></i>";
			barra.classList.add("complete");
		}else{
			barra.querySelector(".text").innerHTML = "Erro ao enviar: " + request.response.name;
			barra.classList.add("error");
		}
	});
	
	// Calcular e mostrar o progresso
	request.upload.addEventListener('progress', function(e) {
		var percent_complete = (e.loaded / e.total)*100;
		
		barra.querySelector(".fill").style.minWidth = percent_complete + "%"; 
	});
	
	//Resposta em JSON
	request.responseType = 'json';
	
	// Caminho
	request.open('post', 'upload.php'); 
	request.send(data);
}</textarea></pre>
</div>



<p>Por fim, iremos juntar um pouco de cada coisa que fizemos, adicionando uma função em um evento <em>change</em> do <em>input</em> do upload. Neste momento, também é feito o laço dentre o(s) arquivo(s) selecionado(s) para validar e, se for válido, fazer o <em>upload</em>, utilizando os outros métodos acima mencionados. É neste momento também que serão criadas dinamicamente as barras: uma para cada arquivo.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >
document.querySelector('#upload-file').addEventListener('change', function() {
var files = this.files;
for(var i = 0; i &lt; files.length; i++){
var info = validarArquivo(files[i]);
    //Criar barra
    var barra = document.createElement("div");
    var fill = document.createElement("div");
    var text = document.createElement("div");
    barra.appendChild(fill);
    barra.appendChild(text);

    barra.classList.add("barra");
    fill.classList.add("fill");
    text.classList.add("text");

    if(info.error == undefined){
        text.innerHTML = info.success;
        enviarArquivo(i, barra); //Enviar
    }else{
        text.innerHTML = info.error;
        barra.classList.add("error");
    }

    //Adicionar barra
    document.querySelector('.lista-uploads').appendChild(barra);
};
});</textarea></pre>
</div>



<h2 class="wp-block-heading">PHP</h2>



<p>E pra terminar com chave de ouro, um <em>PHPzinho</em> que receberá esses arquivos e retornará um <em>json</em> com a confirmação de sucesso ou erro. Não aplicamos muitas validações nesse PHP pois nosso foco era neste exemplo está no <em>front-end</em>, mas é suficiente para que você compreenda sua funcionalidade.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="php" name="mshighlighter" ><?php
ini_set('upload_max_filesize', '2M');
header('Content-Type: application/json');
$file = $_FILES['file'];

$ret = [];

if(move_uploaded_file($file['tmp_name'],'uploads/'.$file['name'])){
    $ret["status"] = "success";
    $ret["path"] = 'uploads/'. $file['name'];
    $ret["name"] = $file['name'];
}else{
    $ret["status"] = "error";
    $ret["name"] = $file['name'];
}

echo json_encode($ret, JSON_PRETTY_PRINT);
?></textarea></pre>
</div>



<p>E, como sempre, você pode baixar o código inteiro no <em>Github</em> e usar direto na sua aplicação.</p>



<!-- Place this tag where you want the button to render. -->
<center><a class="github-button" href="https://github.com/velhobit/upload-html/archive/master.zip" data-size="large" aria-label="Download velhobit/upload-html on GitHub">Download</a></center>



<p>Gostou? Se sim, compartilha com seus amiguinhos interessados na área e curte a página no <strong><em><a rel="noreferrer noopener" href="https://www.facebook.com/velhobit/" target="_blank">Facebook</a></em></strong>. O exemplo acima está levemente modificado para que funcione melhor aqui no site. Entre também no grupo de Design e Desenvolvimento. O <em>link</em> está abaixo do post.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como tirar uma foto usando a Webcam (Javascript + HTML)?</title>
		<link>https://velhobit.com.br/programacao/como-tirar-uma-foto-usando-a-webcam-javascript-html.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sat, 19 Jan 2019 20:07:22 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[biometria]]></category>
		<category><![CDATA[camera]]></category>
		<category><![CDATA[foto]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[identificação]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[registro]]></category>
		<category><![CDATA[rosto]]></category>
		<category><![CDATA[screenshot]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[webcam]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1748</guid>

					<description><![CDATA[Com o HTML5 podemos utilizar recursos de hardware em nossas páginas. Este tutorial mostra como usar Javascript e PHP para salvar screenshots da webcam.]]></description>
										<content:encoded><![CDATA[
<p class="has-very-light-gray-background-color has-background"><strong><em>Disclaimer:</em></strong> Provavelmente a funcionalidade de webcam não está acessível via navegador interno de aplicativo (como o navegador interno do app do Facebook ou outro app mobile). Experimente direto em um navegador (mobile ou desktop).</p>



<p>O HTML5 nos trouxe diversas opções interessantes para desenvolvimento de RIAs (<em>Rich Internet Applications</em>). Em diversos sistemas online, precisamos de uma foto da pessoa que está sendo cadastrada. Para sistemas de hotéis, saúde, academias, dentre outros, que precisam de maior identificação, podemos usar a <em>webcam</em> para fazer a foto na hora que poderá ser usada em posterior conferência. Recurso esse que também está disponível em dispositivos móveis.</p>



<p>A ideia é transformar a imagem corrente da <em>webcam</em> em uma imagem <em>base64</em>. Após isso, converter essa codificação em uma imagem JPG e devolver o caminho – quase como se fosse um upload. Dessa forma você poderá salvar apenas o caminho da imagem no seu banco de dados, sem ficar um campo muito extenso ou que possa falhar em dispositivos móveis. Neste exemplo, será usado Javascript puro, a fim de universalizar para quem quiser utilizar em sua aplicação web.</p>



<h2 class="wp-block-heading">Exemplo:</h2>



<button onclick="loadCamera()" class="cute-button"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f4f8.png" alt="📸" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Clique aqui para visualizar a Webcam</button>
<div class="area-do-video">

<video autoplay="true" id="webCamera"></video>

<textarea type="text" id="base_img" name="base_img"></textarea>
<button type="button" onclick="takeSnapShot()">Tirar foto e salvar</button>
<img id="imagemConvertida">
<p id="caminhoImagem" class="caminho-imagem"><a href="" target="_blank" rel="noopener"></a></p>
</div>



<h2 class="wp-block-heading">HTML5</h2>



<p>Vamos começar criando nosso exemplo com os elementos HTML. Tudo o que realmente precisamos é de uma tag <em>button</em> e uma tag <em>video</em>, mas para poder visualizar o exemplo, vamos colocar o retorno em um <em>img</em>, link da imagem gerada e um <em>textarea</em> para vermos o <em>base64</em>.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><div class="area">
			<video autoplay="true" id="webCamera">
			</video>
	
			<input type="text" id="base_img" name="base_img">
			<button type="button" onclick="takeSnapShot()">Tirar foto e salvar</button>
	
			<img id="imagemConvertida">
			<p id="caminhoImagem" class="caminho-imagem"><a href="" target="_blank" rel="noopener"></a></p>
			<script src="script.js"></script>
</div></textarea></pre>
</div>



<p>Não precisamos necessariamente de um CSS para poder funcionar, mas, apenas para exemplo, vamos colocar um <em>CSSzinho</em>&#8230;</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >body{
	font-family: sans-serif;
	margin: 0;
}

.area{
	margin: 10px auto;
	box-shadow: 0 10px 100px #ccc;
	padding: 20px;
	box-sizing: border-box;
	max-width: 500px;
}

.area video{
	width: 100%;
	height: auto;
	background-color: whitesmoke;
}

.area textarea{
	width: 100%;
	margin-top: 10px;
	height: 80px;
	box-sizing: border-box;
}

.area button{
	-webkit-appearance: none;
	width: 100%;
	box-sizing: border-box;
	padding: 10px;
	text-align: center;
	background-color: #068c84;
	color: white;
	text-transform: uppercase;
	border: 1px solid white;
	box-shadow: 0 1px 5px #666;
}

.area button:focus{
	outline: none;
	background-color: #0989b0;
}

.area img{
	max-width: 100%;
	height: auto;
}

.area .caminho-imagem{
	padding: 5px 10px;
	border-radius: 3px;
	background-color: #068c84;
	text-align: center;
}

.area .caminho-imagem a{
	color: white;
	text-decoration: none;
}

.area .caminho-imagem a:hover{
	color: yellow;
}</textarea></pre>
</div>



<h2 class="wp-block-heading">Javascript</h2>



<p>Agora vamos para a parte divertida. Basicamente vamos dividir nosso código em 3 partes: Chamar a webcam, tirar o instantâneo, e enviar/receber os dados do PHP. Criaremos o arquivo <strong><em>script.js</em></strong>.</p>



<p>A função <em>LoadCamera</em>, irá transformar a webcam em uma espécie de <em>streamming</em> local. Para isso, é necessário que o navegador tenha suporte a isso, logo, precisamos de um navegador moderno com total compatibilidade a HTML5. Basicamente, todos os navegadores modernos, então não pense em compatibilidade com <em>Internet Explorer</em>.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >function loadCamera(){
	//Captura elemento de vídeo
	var video = document.querySelector("#webCamera");
		//As opções abaixo são necessárias para o funcionamento correto no iOS
		video.setAttribute('autoplay', '');
	    video.setAttribute('muted', '');
	    video.setAttribute('playsinline', '');
	    //--
	
	//Verifica se o navegador pode capturar mídia
	if (navigator.mediaDevices.getUserMedia) {
		navigator.mediaDevices.getUserMedia({audio: false, video: {facingMode: 'user'}})
		.then( function(stream) {
			//Definir o elemento vídeo a carregar o capturado pela webcam
			video.srcObject = stream;
		})
		.catch(function(error) {
			alert("Oooopps... Falhou :'(");
		});
	}
}</textarea></pre>
</div>



<p>Você deve ter notado que a função acima tem um comentário com alguns parâmetros adicionais. Esses parâmetros são necessários para o funcionamento no iOS.</p>



<p>Já a função <em>takeSnapShot</em> irá justamente tirar o instantâneo. Essa função irá criar um elemento <em>canvas</em> e desenhar em seu conteúdo uma imagem matricial, baseada no vídeo (um ctrl+c / ctrl+v automático, digamos assim). A partir daí podemos obter o <em>base64</em> desse canvas e utilizá-lo para enviar posteriormente.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >function takeSnapShot(){
	//Captura elemento de vídeo
	var video = document.querySelector("#webCamera");
	
	//Criando um canvas que vai guardar a imagem temporariamente
	var canvas = document.createElement('canvas');
	canvas.width = video.videoWidth;
	canvas.height = video.videoHeight;
	var ctx = canvas.getContext('2d');
	
	//Desenhando e convertendo as dimensões
	ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
	
	//Criando o JPG
	var dataURI = canvas.toDataURL('image/jpeg'); //O resultado é um BASE64 de uma imagem.
	document.querySelector("#base_img").value = dataURI;
	
	sendSnapShot(dataURI); //Gerar Imagem e Salvar Caminho no Banco
}</textarea></pre>
</div>



<p>Você pode, inclusive, se quiser, já adicionar essa <em>base64</em> em no <em>src</em> de um elemento <em>img</em>.</p>



<p>Agora, precisamos enviar essa <em>base64</em> para o PHP. Usaremos o PHP para salvar a imagem em um arquivo jpg (você pode optar por png também). O PHP irá retornar, posteriormente, um <em>json</em> com o caminho completo da imagem, que iremos carregar no objeto <em>img</em> descrito no HTML supracitado. Faremos isso dinamicamente, por técnica de Ajax, sem formulário, pois o <em>submit</em> de um <em>form</em> poderá ser usado futuramente para a conclusão de um determinado cadastro:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="javascript" name="mshighlighter" >function sendSnapShot(base64){
var request = new XMLHttpRequest();
request.open('POST', 'save_photos.php', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
<pre><code>    request.onload = function() {
        console.log(request);
        if (request.status &gt;= 200 &amp;&amp; request.status &lt; 400) {
            //Colocar o caminho da imagem no SRC
            var data = JSON.parse(request.responseText);

            //verificar se houve erro
            if(data.error){
                alert(data.error);
                return false;
            }

            //Mostrar informações
            document.querySelector("#imagemConvertida").setAttribute("src", data.img);
            document.querySelector("#caminhoImagem a").setAttribute("href", data.img);
            document.querySelector("#caminhoImagem a").innerHTML = data.img.split("/")[1];
        } else {
            alert( "Erro ao salvar. Tipo:" + request.status );
        }
    };

    request.onerror = function() {
        alert("Erro ao salvar. Back-End inacessível.");
    }

    request.send("base_img="+base64); // Enviar dados</code></pre>
<p>}</textarea></div>



<h2 class="wp-block-heading">PHP</h2>



<p>No lado do PHP, basicamente, usaremos um $_POST para capturar o dado enviado via <em>Ajax</em> pelo <em>Javascript</em>. Criaremos então o arquivo <strong><em>salvar_photos.php</em></strong>.</p>



<p>Não há muitos segredos, mas é importante se atentar a dois detalhes:</p>



<ol class="wp-block-list"><li>Os dados chegam com o + transformado em espaço, então precisamos converter novamente para + com um <em>replace</em>.</li><li>Precisamos salvar apenas os dados <em>mime</em>, sem os cabeçalhos, logo precisamos dar um explode para coletar apenas os dados. </li></ol>



<p>Fora isso, basicamente colocamos os dados em um arquivo JPG e retornamos a URL em <em>json</em> para ser lido pelo <em>Javascript</em> novamente.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="php" name="mshighlighter" ><?php
	if(!isset($_POST['base_img'])){
		die("{\"error\": \" Flopou. Cadê o base_img?\"}");
	}

	$result = [];
	$data = str_replace(" ","+",$_POST['base_img']); //O envio do dado pelo XMLHttpRequest tende a trocar o + por espaço, por isso a necessidade de substituir. 
	$name = md5(time().uniqid()); 
	$path = "snaps/{$name}.jpg";

	//data
	$data = explode(',', $data);
	
	//Save data
	file_put_contents($path, base64_decode(trim($data[1])));
	
	//Print Data
	$result['img'] = $path;
	echo json_encode($result, JSON_PRETTY_PRINT);
?></textarea></pre>
</div>



<p>Uma vez tudo pronto, basta chamar a função <strong><em>loadCamera()</em></strong> no evento que você quer que ele seja disparado.</p>



<p>Como sempre, deixamos o código disponível para quem quiser utilizar. Desta vez, o código está no GitHub.</p>



<!-- Place this tag where you want the button to render. -->
<center style="margin-top:20px;"><a class="github-button" href="https://github.com/velhobit" data-size="large" data-show-count="true" aria-label="Follow @velhobit on GitHub">Follow @velhobit</a></center>



<p class="has-white-color has-luminous-vivid-orange-background-color has-text-color has-background"><strong>ATENÇÃO: O navegador não vai liberar o uso das ferramentas em um ambiente http. Você precisa necessariamente estar com seu site ou sistema em conexão segura (https).</strong></p>



<p>Se gostou, compartilha com seus amiguinhos interessados na área e curte a página no <strong><em><a rel="noreferrer noopener" aria-label="Facebook (abre em uma nova aba)" href="https://www.facebook.com/velhobit/" target="_blank">Facebook</a></em></strong>. O exemplo acima está levemente modificado para que funcione melhor aqui no site. Entre também no grupo de Design e Desenvolvimento. O link está abaixo do post.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>FAB (Botão Flutuante) com CSS3 e HTML (sem Javascript)</title>
		<link>https://velhobit.com.br/tutoriais/fab-botao-flutuante-com-css3-e-html-sem-javascript.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Mon, 24 Dec 2018 21:14:35 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[button]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[fab]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[interface do usuário]]></category>
		<category><![CDATA[interfaces]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[webdesign]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1728</guid>

					<description><![CDATA[Sabe aquele componente FAB? Aquele que é um botão flutuante que você clica e abre outros botões. Que tal fazermos algo parecido apenas com HTML e CSS?]]></description>
										<content:encoded><![CDATA[
<p style="background-color:#fffad9" class="has-background"><strong>Disclaimer</strong>: O comportamento não vai funcionar no iOS, pois o iOS desconsidera as pseudoclasses utilizadas aqui. No lugar, ele utiliza uma pseudoclasse de <strong><em>:hover</em></strong> para significar a seleção sem clique. Ainda estou vendo qual a melhor forma de usar no iOS sem <em>bugar</em> o comportamento em <em>desktop</em>.</p>



<p>Continuando com os exercícios de lógica com CSS e HTML, iremos desta vez ver se é possível criar um FAB (<em>Float Action Button</em>) sem usar Javascript. E, adianto, sim, é possível. Se você quer ver os outros exercícios, acesse a <a rel="noreferrer noopener" aria-label="categoria de Tutoriais (abre em uma nova aba)" href="https://velhobit.com.br/tutoriais" target="_blank">categoria de </a><strong><a rel="noreferrer noopener" aria-label="categoria de Tutoriais (abre em uma nova aba)" href="https://velhobit.com.br/tutoriais" target="_blank">Tutoriais</a></strong>, deste site.</p>



<p class="has-text-color has-background has-very-dark-gray-color has-very-light-gray-background-color">Editado -> Para quem quer aplicar uma interação melhor, eu adicionei um exemplo de uso com Javascript no final do Post.</p>



<p>Esse tipo de botão é comum em aplicativos <em>Android</em> com <em>Material Design</em>. Se trata de um botão flutuante que fica em uma das extremidades inferiores (geralmente a direita) que abre uma lista com outros botões. Bem, se você está nesta página, basta olhar logo abaixo <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f601.png" alt="😁" class="wp-smiley" style="height: 1em; max-height: 1em;" />.</p>



<div style="border-radius: 3px; border: 1px solid grey; background-color: whitesmoke; position:relative; height: 300px; width: 100%;">
 <div class="fab">
  <button class="main" onclick="void(0)">
  </button>
  <ul>
    <li>
      <label for="opcao1">Opção 1</label>
      <button id="opcao1">
      ⎈
      </button>
    </li>
    <li>
      <label for="opcao2">Opção 2</label>
      <button id="opcao2">
      ⎗
      </button>
    </li>
    <li>
      <label for="opcao3">Opção 3</label>
      <button id="opcao3">
      ☏
      </button>
    </li>
  </ul>
</div>
</div>



<h2 class="wp-block-heading">HTML + CSS</h2>



<p>Um dos desafios é conseguir fazer algo semanticamente correto. Então, o leiaute em si consistirá em um container que contém um botão e uma lista de botões. Cada botão terá uma etiqueta (<em>label</em>) que será a descrição do que ele pode fazer.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><div class="fab"  ontouchstart="">
  <button class="main" >
  </button>
  <ul>
    <li>
      <label for="opcao1">Opção 1</label>
      <button id="opcao1">
      ⎈
      </button>
    </li>
    <li>
      <label for="opcao2">Opção 2</label>
      <button id="opcao2">
      ⎗
      </button>
    </li>
    <li>
      <label for="opcao3">Opção 3</label>
      <button id="opcao3">
      ☏
      </button>
    </li>
  </ul>
</div></textarea></pre>
</div>



<p>No exemplo, há apenas 3 opções e com caracteres genéricos. Você pode substituir por imagens (mas tomando cuidado com o tamanho destas) ou usando <em>font-icons</em>, como o <em>Font-Awesome</em>, o <em>MaterialDesign Lite</em> ou até mesmo <a rel="noreferrer noopener" aria-label="criar os seus próprios font-icons, como mostra este tutorial (abre em uma nova aba)" href="https://velhobit.com.br/design/como-criar-sua-propria-fonte-e-a-usar-como-icone.html" target="_blank">criar os seus próprios font-icons, como mostra este tutorial</a>. Também pode colocar quantos items quiser na lista, apenas tomando cuidado para não ficar alto demais e enrolar o usuário.</p>



<p>Como sempre usaremos as <strong>pseudoclasses</strong> para poder reconhecer ações. No caso, utilizaremos a pseudoclasse :active e :focus para detectar o &#8220;<em>click</em>&#8221; ou o &#8220;foco&#8221; (quando o <em>tab</em> fica em cima). Você também notará a existência de um símbolo de positivo (<strong>+</strong>). No CSS, o símbolo <strong>+</strong> é um indicativo de que o item que deverá ser formatado é o item logo após o DOM atual, porém no mesmo container hierárquico. Ou seja, quando você declara <strong><em>input + p</em></strong>, você quer aplicar o estilo no <strong>p</strong> imediatamente após o <strong><em>input</em></strong>. </p>



<p>Sem mais enrolações, segue o CSS</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >
.fab{
  position: fixed;
  bottom:10px;
  right:10px;
}

.fab button{
  cursor: pointer;
  width: 48px;
  height: 48px;
  border-radius: 30px;
  background-color: #cb60b3;
  border: none;
  box-shadow: 0 1px 5px rgba(0,0,0,.4);
  font-size: 24px;
  color: white;
    
  -webkit-transition: .2s ease-out;
  -moz-transition: .2s ease-out;
  transition: .2s ease-out;
}

.fab button.main{
  position: absolute;
  width: 60px;
  height: 60px;
  border-radius: 30px;
  background-color: #5b19b7;
  right: 0;
  bottom: 0;
  z-index: 20;
}

.fab button.main:before{
  content: '⏚';
}

.fab ul{
  position:absolute;
  bottom: 0;
  right: 0;
  padding:0;
  padding-right:5px;
  margin:0;
  list-style:none;
  z-index:10;
  
  -webkit-transition: .2s ease-out;
  -moz-transition: .2s ease-out;
  transition: .2s ease-out;
}

.fab ul li{
  display: flex;
  justify-content: flex-start;
  position: relative;
  margin-bottom: -10%;
  opacity: 0;
  
  -webkit-transition: .3s ease-out;
  -moz-transition: .3s ease-out;
  transition: .3s ease-out;
}

.fab ul li label{
  margin-right:10px;
  white-space: nowrap;
  display: block;
  margin-top: 10px;
  padding: 5px 8px;
  background-color: white;
  box-shadow: 0 1px 3px rgba(0,0,0,.2);
  border-radius:3px;
  height: 18px;
  font-size: 16px;
  pointer-events: none;
  opacity:0;
  
  -webkit-transition: .2s ease-out;
  -moz-transition: .2s ease-out;
  transition: .2s ease-out;
}

.fab button.main:active,
.fab button.main:focus{
  outline: none;
  background-color: #7716ff;
  box-shadow: 0 3px 8px rgba(0,0,0,.5);
 }
 
.fab button.main:active:before,
.fab button.main:focus:before{
  content: '↑';
}

.fab button.main:active + ul,
.fab button.main:focus + ul{
  bottom: 70px;
}

.fab button.main:active + ul li,
.fab button.main:focus + ul li{
  margin-bottom: 10px;
  opacity: 1;
}

.fab button.main:active + ul li:hover label,
.fab button.main:focus + ul li:hover label{
  opacity: 1;
}</textarea></pre>
</div>



<p>O que estamos fazendo é aplicar um estilo na lista assim que o botão ganha foco ou é ativado. Você pode, se preferir, adicionar também ao passar em cima com o mouse, bastando adicionar, junto aos demais comandos do botão principal, a pseudoclasse <strong><em>:hover</em></strong> e repetindo o resto da declaração.</p>



<p>Simples, não é? E, como sempre, o exemplo no JsFiddle para você ir experimentando e fazendo seus próprios testes. Compartilhe com a galera!</p>



<script async="" src="//jsfiddle.net/velhobit/cm51d3vb/1/embed/html,css,result/"></script>



<p><strong>Versão com Javascript:</strong></p>



<script async src="//jsfiddle.net/velhobit/uxeyqb5z/2/embed/"></script>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Efeito float label animado com CSS3 &#8211; Igual ao do novo login do Google</title>
		<link>https://velhobit.com.br/tutoriais/efeito-float-label-animado-com-css3-igual-ao-do-novo-login-do-google.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Fri, 21 Dec 2018 18:41:44 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[efeito]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1722</guid>

					<description><![CDATA[Copiando o estilo novo de transição do Login das Contas do Google, com CSS puro. Dessa vez com as bordas reforçadas.]]></description>
										<content:encoded><![CDATA[
<p>No post anterior, eu mostrei como fazer aquele <a rel="noreferrer noopener" aria-label="efeito de label float do Material Design (abre em uma nova aba)" href="https://velhobit.com.br/design/como-fazer-efeito-float-label-animado-com-css3-puro.html" target="_blank">efeito de </a><em><a rel="noreferrer noopener" aria-label="efeito de label float do Material Design (abre em uma nova aba)" href="https://velhobit.com.br/design/como-fazer-efeito-float-label-animado-com-css3-puro.html" target="_blank">label float</a></em><a rel="noreferrer noopener" aria-label="efeito de label float do Material Design (abre em uma nova aba)" href="https://velhobit.com.br/design/como-fazer-efeito-float-label-animado-com-css3-puro.html" target="_blank"> do </a><strong><a rel="noreferrer noopener" aria-label="efeito de label float do Material Design (abre em uma nova aba)" href="https://velhobit.com.br/design/como-fazer-efeito-float-label-animado-com-css3-puro.html" target="_blank">Material Design</a></strong>. Eis que esta semana eu me deparo com o novo <em>input</em> do login do Google e achei bem legal, mas pensei que ninguém ia se interessar.</p>



<p>Como vi uma pergunta em um grupo do Facebook, resolvi rapidinho então fazer uma variação do que foi feito no anterior, para atingir o mesmo efeito do input login do novo login do Google. Ah e, mais uma vez, sem javascript <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" />.</p>



<div style="background-color: white; border-radius: 10px; padding: 1.2rem">
<div class="label-float">
  <input type="text" placeholder=" ">
  <label>Telefone</label>
</div>
<br>
<div class="label-float">
  <input type="text" placeholder=" " required="">
  <label>Nome de Usuário</label>
</div>
</div>



<h2 class="wp-block-heading">HTML e CSS</h2>



<p>Se precisarem de alguma explicação mais aprofundada, dê um olhada no artigo anterior. Só uma observação importante é que o <strong><em>top</em></strong>, do <em>label</em>, deverá ser ajustado de acordo com o tamanho da letra e a tipografia usada, pois tipografias diferentes mudam a sensação de tamanho.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><div class="label-float">
  <input type="text" placeholder=" ">
  <label>Telefone</label>
</div>
<br>
<div class="label-float">
  <input type="text" placeholder=" " required="">
  <label>Nome de Usuário</label>
</div></textarea></pre>
</div>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >.label-float{
  position: relative;
  padding-top: 13px;
}

.label-float input{
  border: 1px solid lightgrey;
  border-radius: 5px;
  outline: none;
  min-width: 250px;
  padding: 15px 20px;
  font-size: 16px;
  transition: all .1s linear;
  -webkit-transition: all .1s linear;
  -moz-transition: all .1s linear;
  -webkit-appearance:none;
}

.label-float input:focus{
  border: 2px solid #3951b2;
}

.label-float input::placeholder{
  color:transparent;
}

.label-float label{
  pointer-events: none;
  position: absolute;
  top: calc(50% - 8px);
  left: 15px;
  transition: all .1s linear;
  -webkit-transition: all .1s linear;
  -moz-transition: all .1s linear;
  background-color: white;
  padding: 5px;
  box-sizing: border-box;
}

.label-float input:required:invalid + label{
  color: red;
}
.label-float input:focus:required:invalid{
  border: 2px solid red;
}
.label-float input:required:invalid + label:before{
  content: '*';
}
.label-float input:focus + label,
.label-float input:not(:placeholder-shown) + label{
  font-size: 13px;
  top: 0;
  color: #3951b2;
}</textarea></pre>
</div>



<p>E, como sempre, o link, com o exemplo do jsFiddle, se você deseja apenas experimentar e treinar um pouco:</p>



<script async="" src="//jsfiddle.net/velhobit/1up08b4z/1/embed/html,css,result/"></script>



<p>Compartilhe se você achou legal!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como fazer efeito float label animado com CSS3 puro</title>
		<link>https://velhobit.com.br/tutoriais/como-fazer-efeito-float-label-animado-com-css3-puro.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Mon, 17 Dec 2018 02:17:10 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[componentes]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[design de interação]]></category>
		<category><![CDATA[efeito]]></category>
		<category><![CDATA[front]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[input]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[webdesign]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1709</guid>

					<description><![CDATA[Como criar um efeito float no label, quando input preenchido, com CSS3 puro e HTML (similar ao input do Android). E, melhor, sem Javascript!]]></description>
										<content:encoded><![CDATA[
<p>O último post sobre<a rel="noreferrer noopener" aria-label="O último post sobre como criar um efeito ON/OFF em um checkbox usando CSS3 puro fez muito sucesso. Dessa forma, pensei o que mais poderia ser legal para fazer com CSS3. Analisando um pouco o comportamento do Android, me lembrei de um componente bem interessante que é o input com um label float animado. Basicamente, ao preencher o conteúdo, o label sobe e vai para um pouco acima do input, como no exemplo abaixo: (abre em uma nova aba)" href="https://velhobit.com.br/design/input-checkbox-switch-on-off-apenas-com-css3.html" target="_blank"> como criar um efeito ON/OFF em um checkbox usando CSS3 puro</a> fez muito sucesso. Dessa forma, pensei o que mais poderia ser legal para fazer com CSS3. Analisando um pouco o comportamento do <em>Android</em>, me lembrei de um componente bem interessante que é o <em>input</em> com um <em>label float</em> animado. Basicamente, ao preencher o conteúdo, o <em>label</em> sobe e vai para um pouco acima do input, como no exemplo abaixo:</p>



<div class="inputes">
<div class="label-float">
  <input type="text" placeholder=" "/>
  <label>Telefone</label>
</div>
<br/>
<div class="label-float">
  <input type="text" placeholder=" " required/>
  <label>Nome de Usuário</label>
</div>
</div>



<h2 class="wp-block-heading">Agora&#8230; como fazer?</h2>



<p>O segredo está novamente nas <strong>pseudoclasses</strong> e <strong>operadores</strong>. Graças as pseudoclasses eu posso definir, com alguns gatilhos, o comportamento de um determinado elemento HTML.</p>



<p>No caso, esse gatilho é o placeholder, então é fundamental que o input possua um placeholder (vazio ou não) para criar o efeito. Pois o que identifica que algo foi preenchido ou não é justamente o <em>placeholder</em>. <strong>Sem o placeholder definido, o efeito não funciona.</strong> A pseudoclasse referente ao required também é usada em nosso exemplo:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><div class="label-float">
  <input type="text" placeholder=" "/>
  <label>Telefone</label>
</div>

<div class="label-float">
  <input type="text" placeholder=" " required/>
  <label>Nome de Usuário</label>
</div></textarea></pre>
</div>



<p>Já para o efeito de transição, usaremos o <em>transition</em> e o comportamento do <em>absolute</em> que, por definição, tem seus eixos referentes ao pai, no caso desse ser <em>relative</em>. Então basta usar o CSS abaixo:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >
.label-float{
  position: relative;
  padding-top: 13px;
}

.label-float input{
  border: 0;
  border-bottom: 2px solid lightgrey;
  outline: none;
  min-width: 180px;
  font-size: 16px;
  transition: all .3s ease-out;
  -webkit-transition: all .3s ease-out;
  -moz-transition: all .3s ease-out;
  -webkit-appearance:none;
  border-radius: 0;
}

.label-float input:focus{
  border-bottom: 2px solid #3951b2;
}

.label-float input::placeholder{
  color:transparent;
}

.label-float label{
  pointer-events: none;
  position: absolute;
  top: 0;
  left: 0;
  margin-top: 13px;
  transition: all .3s ease-out;
  -webkit-transition: all .3s ease-out;
  -moz-transition: all .3s ease-out;
}

.label-float input:required:invalid + label{
  color: red;
}
.label-float input:focus:required:invalid{
  border-bottom: 2px solid red;
}
.label-float input:required:invalid + label:before{
  content: '*';
}
.label-float input:focus + label,
.label-float input:not(:placeholder-shown) + label{
  font-size: 13px;
  margin-top: 0;
  color: #3951b2;
}</textarea></pre>
</div>



<p>Como sempre, estou disponibilizando o exemplo completo no JsFiddle!</p>


<p><script async src="//jsfiddle.net/velhobit/4eu2r0q5/embed/html,css,result/"></script></p>



<p>Gostou? Então curta a página no <a href="https://www.facebook.com/velhobit/" target="_blank" rel="noreferrer noopener" aria-label="Gostou? Então curta a página no Facebook e compartilhe com os coleguinhas! (abre em uma nova aba)">Facebook</a> e compartilhe com os coleguinhas!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Input Checkbox Switch ON / OFF apenas com CSS3</title>
		<link>https://velhobit.com.br/tutoriais/input-checkbox-switch-on-off-apenas-com-css3.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sun, 16 Dec 2018 00:14:00 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[html5]]></category>
		<category><![CDATA[UX]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1699</guid>

					<description><![CDATA[Estava cansado e resolvi pensar em uma forma de fazer um Switch ON / OFF similar ao que tem no Android e iOS, para usar pelo navegador, com HTML e CSS3]]></description>
										<content:encoded><![CDATA[
<p>O CSS é o mecanismo utilizado pelos navegadores para informar a estes como deve ser exibido determinado elemento HTML. Desde a versão 3 muitas coisas novas permitiram que a web fosse cada vez bonita e funcional.</p>



<p>Eu estava um pouco cansado do trabalho e para relaxar fiquei pensando em uma solução simples para simular um Switch ON/OFF que pudesse ser aplicado no lugar de um checkbox. E, para isso, usei simplesmente CSS3 e pseudoclasses:</p>



<div class="check-radio">
  <input type="checkbox"/>
</div>
<br/><br/>



<p>Basicamente, pseudoclasses nos permitem adicionar instruções específicas de acordo com determinados comportamentos ou condições dos elementos HTML. Neste pequeno exemplo, eu usei a pseudoclasse <strong>:checked</strong>, para verificar se está marcado ou não, e as que adicionam complementos antes e depois do elemento, são as <strong>:before</strong> e <strong>:after</strong>, respectivamente.</p>



<p>Mas o que você quer mesmo é o código, então para ficar fácil de você pegar, basta clicar visualizar o exemplo abaixo no JsFiddle: </p>



<script async src="//jsfiddle.net/velhobit/7Lwrzae4/3/embed/html,css,result/dark/"></script>



<p>Agora, se tudo o que você quer é o código puro, segue abaixo:</p>



<h2 class="wp-block-heading">HTML e CSS</h2>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><div class="check-radio">
  <input type="checkbox"/>
</div></textarea></pre>
</div>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >/**
* CSS do componente
**/
.check-radio{
  position: relative;
}

.check-radio input{
  -webkit-appearance: none;
  appearance: none;
  background-color: #eee;
  width: 40px;
  height: 15px;
  border-radius: 10px;
  box-shadow: inset 0 1px 5px rgba(0,0,0,.5);
}

.check-radio input:focus{
  outline: none;
  cursor: pointer;
}

.check-radio input:before{
  content: '';
  margin-top: -2.5px;
  display: block;
  width: 20px;
  height: 20px;
  background-color: white;
  border-radius: 50%;
  box-shadow: inset 0 0 0 2px #333, 0 2px 5px rgba(0,0,0,.5);
  position: absolute;
  left: 0;
  transition: left .3s ease-out;
  -webkit-transition: left .3s ease-out;
}

.check-radio input:after{
  content: 'FF';
  display: block;
  margin-top: -2.5px;
  left: 20px;
  position: absolute;
  font-size: 14px;
  font-weight: bold;
  transition: left .3s ease-out;
  -webkit-transition: left .3s ease-out;
  color: #666;
}

.check-radio input:checked{
  background-color: lime;
}

.check-radio input:checked:before{
  left: 22.5px;
  box-shadow: inset 0 0 0 2px green, 0 2px 5px rgba(0,0,0,.5);
}

.check-radio input:checked:after{
  content: 'N';
  left: 43.5px;
  color: green;
}</textarea></pre>
</div>



<p>Por hoje é só&#8230; esse post foi rapidinho&#8230; Se gostou, compartilhe e nos siga nas redes sociais. VelhoBit, no Facebook, Twitter e Instagram.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Destacando um Elemento HTML (coachmark): Efeito Spotlight ( com CSS3 e Javascript puro)</title>
		<link>https://velhobit.com.br/tutoriais/destacando-um-elemento-html-efeito-spotlight-com-css3-e-javascript-puro.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Fri, 07 Dec 2018 18:43:20 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[ajuda]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[efeitos]]></category>
		<category><![CDATA[front]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[frontend]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[js]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[UX]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1667</guid>

					<description><![CDATA[Um passo a passo de como criar um coachmark  com efeito de spotlight com CSS e Javascript puro, para ser usado em ferramentas de ajuda e tutoriais]]></description>
										<content:encoded><![CDATA[
<p><strong>Obs. Se você só quer o código pronto, pule para o final do post. Ou acesse o link do <a href="https://jsfiddle.net/velhobit/jcy5ftu4/" target="_blank" rel="noreferrer noopener" aria-label="Obs. Se você só quer o código pronto, pule para o final do post. Ou acesse o link do JSFiddle. (abre em uma nova aba)">JSFiddle</a>.</strong></p>



<p>As vezes precisamos encontrar formas de destacar elementos na tela (coachmark). Isso é muito útil principalmente quando você está tratando de pequenos tutoriais, afim de ajudar os usuários. Convém, também, entregar soluções simples e esteticamente elegantes para que ajudem no relacionamento com a ferramenta.</p>



<p>Faz algum tempo, um cliente meu quis criar um modo tutorial em seu sistema. Esse tutorial não deveria permitir que outras áreas da tela fossem clicadas até que a pessoa confirmasse que compreendeu. Como designer, lembrei que, anos atrás, no Android, a Google usava uma espécie de spotlight, mas não vi nada a respeito para websites. E, também, eu precisava que fosse dinâmico. Então eu resolvi usar meus conhecimentos de CSS3 e Javascript para usar essa ideia. E é disso que eu falarei neste tutorial.</p>



<p>Apesar de eu ter usado originalmente jQuery, para compartilhar com todos, resolvi fazer uma versão com Javascript puro, de forma que você poderá adicionar a qualquer aplicação web que você já tenha.</p>



<h2 class="wp-block-heading">Criando a Estrutura: HTML e o CSS3</h2>



<p>Para criar o efeito, vamos usar uma propriedade interessante do CSS3 chamada <strong><em>clip-path</em></strong>. O <em>clip-path</em> permite que criemos elementos vetoriais que serão usados como máscaras. <a href="https://velhobit.com.br/design/grafico-loader-radial-com-css-e-javascript-puro.html">Já utilizamos essa propriedade em um outro exemplo, no caso, sobre um loader</a>.</p>



<h2>Exemplo de uso do clip-path:</h2>
<p class="batman"></p>



<p>Dessa forma, se já não tiver, teu projeto deve possuir um container principal que é pai de todos os elementos, mas abaixo do &lt;body&gt;. Se não houver, o crie, é até uma questão lógica de organização para evitar problemas futuros. Veja um código de exemplo:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><!doctype html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
	</head>
<body>
	<div id="container" class="container">
	</div>
</body>
</html></textarea></pre>
</div>



<p>A div <strong>container</strong>&nbsp;vai ser justamente o elemento que iremos <em>clippar</em>. Para ajudar em nosso exemplo, vamos criar um form básico dentro do container, ficando assim:</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><!doctype html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
	</head>
<body>
	<div id="container" class="container">
		 <div class="form">
		  First name:<br>
		  <input type="text" name="firstname" id="firstname" value="Mickey">
		  <br>		  <br>
		  Last name:
		  <br>
		  <input type="text" name="lastname" id="lastname" value="Mouse">
		  <br><br>
		  <input type="submit" id="submeter" value="Submit">
		  <div class="btn_ajuda">?</div>
		</div> 
	</div>
</body>
</html></textarea></pre>
</div>



<p>Para finalizar nosso HTML, vamos colocar a caixa de mensagens. Repare que no código abaixo a caixa de mensagem vai ter uma div chamada&nbsp;<em>spacer</em>. O objetivo dessa div vai ser adicionar o espaço do elemento referência, para que o código funcione também em dispositivos móveis e ela deverá ficar fora do container da aplicação. Mais à frente isso vai ficar mais bem explicado.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="html" name="mshighlighter" ><!doctype html>
<html>
	<head>
		<meta charset="UTF-8">
		<meta name="viewport" content="width=device-width, initial-scale=1">
	</head>
<body>
	<div id="container" class="container">
		 <div class="form">
		  First name:<br>
		  <input type="text" name="firstname" id="firstname" value="Mickey">
		  <br>		  <br>
		  Last name:
		  <br>
		  <input type="text" name="lastname" id="lastname" value="Mouse">
		  <br><br>
		  <input type="submit" id="submeter" value="Submit">
		  <div class="btn_ajuda">?</div>
		</div> 
	</div>

		<!-- Mensagem de Ajuda-->
		<div class="mensagem_area" id="mensagemAjuda">
			<div class="spacer"></div>
			<div class="mensagem">
				<h2></h2>
				<p></p>
				<button onclick="ocultarAjuda()">
				  OK, entendi
				</button>
			</div>
		</div>
</body>
</html></textarea></pre>
</div>



<p>Agora que o HTML está pronto, vamos para o CSS inicial. A primeira fase é estabelecer todo comportamento da div que estamos usando como container. Também precisamos adicionar uma cor ao plano de fundo, que vai ser a cor que usaremos como base para a área em lowlight.</p>



<p>A animação ficará a cargo do recurso transition do CSS3. Importante ressaltar que uma animação criada por CSS é mais leve e possui melhor frequência do que uma criada pelo Javascript. Isso porque o navegador tenta usar a renderização da GPU nesses casos. Dessa forma, vamos aplicar o parâmetro&nbsp;<em>transition</em>&nbsp;para aplicar o efeito.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >body{
		    margin: 0;
		    font-family: sans-serif;
		    background-color: #15d115;
}
		    
.container{
			background-color: white;
			min-width: 100%;
/* Obs. A largura do clip-path, abaixo, está definido
como 3840 de diâmetro, porque ultrapassa
o tamanho do 4K - O clip-path considera o raio.
Posteriormente, você poderá trabalhar com
adição de classes, se você quiser evitar
a definição inicial desse tamanho,
mas é necessário haver uma para poder
ativar a animação.*/
			clip-path: circle(1920px at center);
			-webkit-clip-path: circle(1920px at center);
		    transition: 2s ease-in-out;
		    -webkit-transition: 1s ease-in-out;

		    position: absolute;
		    min-width: 100%;
		    min-height: 100%;
}</textarea></pre>
</div>



<p>O parâmetro&nbsp;<em>position</em>&nbsp;como&nbsp;<em>absolute</em>, com suas larguras e alturas mínimas marcados como 100% servirão para emular o comportamento do&nbsp;<em>body</em>. Isso só é necessário porque alguns sistemas costumam ter áreas menores do que a primeira dobra do navegador. Nesse caso, apenas, é necessário aplicar esses três parâmetros.</p>



<p>Já para o CSS do bloco de mensagem, você pode fazer algo do jeito que preferir.<strong> Apenas é importante lembrar que esse bloco deverá ficar com </strong><em><strong>position</strong></em><strong> </strong><em><strong>absolute</strong></em><strong>, ou </strong><em><strong>fixed</strong></em>, dependendo de como for sua aplicação, para que possa se encaixar no local correto.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="css" name="mshighlighter" >.mensagem_area{
		 position: fixed;
		 opacity: 0;
		  pointer-events: none;
		  transition: 2s ease-in-out;
		  -webkit-transition: 1s ease-in-out;
		  color: white;
		    
		  display: flex;
		  justify-content: flex-start;
		  flex-wrap: wrap;
}
.mensagem_area.show{
		    opacity: 1;
		    max-width: 100%;
		    pointer-events: all;
}
.mensagem_area .spacer{
	visibility: hidden;  
}
.mensagem_area .mensagem{
		    width: 250px;
		    padding: 15px;
		    box-sizing: border-box;
 }
.mensagem_area .mensagem h2{
		    font-size: 18px;
		    font-weight: bold;
		    margin: 0;
}
.mensagem_area .mensagem p{
		    font-size: 16px;
}</textarea></pre>
</div>



<h2 class="wp-block-heading">Criando as Funções Javascript</h2>



<p>&nbsp;Agora basta que a gente crie as funções de aparecer e desaparecer o <em>spotlight</em>. Originalmente eu havia usado jQuery, pois ele possui soluções rápidas e funcionais como o <em>offset</em> nativo e <em>outerWidth</em>, mas com uma pesquisa rápida conseguir adaptar, apesar do código ter ficado um pouquinho maior.</p>



<p>O código consiste em 4 blocos:</p>



<ul class="wp-block-list"><li>Capturar largura e posição em relação ao&nbsp;<em>document</em>, do objeto referência (que será passado como parâmetro), fazendo os cálculos apropriados para adição do círculo. Você irá reparar que é usado como base o raio e não o diâmetro, pois é a referência do parâmetro&nbsp;<em>clip-path</em>;</li><li>Adicionar o clip ao container;</li><li>Adicionar os textos da mensagem a partir dos parâmetros passados;</li><li>Aplicar os estilos com os novos parâmetros. O timeout que precede a adição da classe show da mensagem existe para que o texto apareça após a transição do spotlight.</li></ul>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="js" name="mshighlighter" >function mostrarAjuda(id_obj, titulo, mensagem){
	//Pegar raio e posição
	var raio = document.querySelector('#' + id_obj).offsetWidth / 2;
	var offset = document.querySelector('#' + id_obj).getBoundingClientRect();
		offset.top = offset.top + document.body.scrollTop;
		offset.left = offset.left + document.body.scrollLeft;
	
	//Adicionar clip
	var clip = "circle(" + parseInt(raio).toString() + "px at " + parseInt(offset.left + raio).toString() + "px " + parseInt(offset.top + offset.height/2).toString() + "px)";
	
	var container = document.querySelector('#container');
		container.style.clipPath = clip;
		container.style.webkitClipPath = clip;
		
	//Textos
	document.querySelector("#mensagemAjuda h2").innerHTML = titulo;
	document.querySelector("#mensagemAjuda p").innerHTML = mensagem;
	
	//Estilos
	document.querySelector("#mensagemAjuda .spacer").style.width = parseInt(raio * 2 + offset.left).toString() + "px";
	document.querySelector("#mensagemAjuda .spacer").style.height = parseInt(raio).toString() + "px";
	document.querySelector("#mensagemAjuda").style.top = parseInt(offset.top).toString() + "px";

	setTimeout(function(){
		document.querySelector("#mensagemAjuda").classList.add("show");
	}, 1500);
	
}</textarea></pre>
</div>



<p>Por fim, basta adicionar uma função que restaure as configurações originais dos estilos e textos.</p>


<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="js" name="mshighlighter" >function ocultarAjuda(){
	//Limpar
	document.querySelector("#mensagemAjuda").classList.remove("show");
	container.style.clipPath = "circle(1920px at center)";
	container.style.webkitClipPath = "circle(1920px at center)";
	setTimeout(function(){
		document.querySelector("#mensagemAjuda h2").innerHTML = "";
		document.querySelector("#mensagemAjuda p").innerHTML = "";
	}, 2000);
}</textarea></pre>
</div>



<p>Como sempre, deixei o código completo para você testar ou copiar. No caso, o código está no <strong><em>jsfiddle</em></strong> e você pode visualizar abaixo:</p>



<script async="" src="//jsfiddle.net/velhobit/jcy5ftu4/embed/result,js,html,css"></script>



<p>Se você gostou da publicação, curta e compartilhe esta página com o maior número de pessoas. Aproveite e curta nossa página do <a href="https://www.facebook.com/velhobit/">Facebook</a>.</p>



<p><strong>ATUALIZAÇÃO: Que tal experimentar uma versão com blur, usando o html2canvas? Obs. É meio pesado. Dê preferência a usar em projetos para desktop.</strong></p>



<script async="" src="//jsfiddle.net/velhobit/y2Lfwed0/embed/result,js,html,css/dark/"></script>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como Criar Sua Própria Fonte e A Usar Como Ícone?</title>
		<link>https://velhobit.com.br/tutoriais/como-criar-sua-propria-fonte-e-a-usar-como-icone.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Thu, 29 Nov 2018 22:17:11 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[aprendizado]]></category>
		<category><![CDATA[botao]]></category>
		<category><![CDATA[criar]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[design de interação]]></category>
		<category><![CDATA[design gráfico]]></category>
		<category><![CDATA[fonts]]></category>
		<category><![CDATA[ícones]]></category>
		<category><![CDATA[site]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web design]]></category>
		<guid isPermaLink="false">https://bitcolor.com.br/?p=71</guid>

					<description><![CDATA[Criar fontes pode ser útil para utilizar em identidades visuais ou como ícones, para uma página ou sistema. Este tutorial mostra o processo de como criar sua própria fonte.]]></description>
										<content:encoded><![CDATA[
<p>Quem está estudando para ser designer, precisa estudar um assunto muito importante: Tipografia. E, por muitas vezes, precisa criar a própria família tipográfica, ou seja, como criar fontes. Além disso, podemos usar uma tipografia personalizada como ícones, tornando o site ou o sistema, desenvolvido em HTML5, ainda mais leve e bonito.</p>



<p>Este tutorial visa ajudar você com o processo técnico de converter os símbolos e criar sua própria fonte OTF, TTF, SVG, etc. Também um pequeno resumo de como implementar sua fonte em CSS3 para funcionar como ícone.</p>



<div class="videoWrapper"><iframe loading="lazy" src="https://www.youtube.com/embed/vqPuOnBqeS8" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></div>



<p>Para começar, você vai precisar instalar o Inkscape em seu computador. Baixe a&nbsp;versão mais recente do aplicativo&nbsp;<a title="Link para o Inkscape" href="https://inkscape.org/pt/" target="_blank" rel="noopener">Inkscape</a>. Ele está disponível para Windows, Linux e Mac. Caso você use o MacOSX, será necessário instalar o&nbsp;<a title="Baixe o XQuartz" href="http://xquartz.macosforge.org/landing/">XQuartz</a>.</p>



<p>Você vai precisar também de algum programa para desenho vetorial, pode usar qualquer um de sua preferência, como o Illustrator, CorelDRAW ou o próprio Inkscape.</p>



<h2 class="wp-block-heading">Crie seu símbolo para cada caractere</h2>



<p>Primeiramente, é necessário criar os glifos. Você pode utilizar o Illustrator ou qualquer outro programa de ilustrações vetoriais. Exporte o arquivo no formato SVG. Você pode, se quiser, colocar todas as ilustrações no mesmo arquivo. Os desenhos não deverão ter contornos, somente preenchimento e devem ser compostos somente de preto.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/icone-illustrator-tutorial-fonte.jpg" alt="Fonte Criada no Illustrator"/></figure>



<h2 class="wp-block-heading">Anexando Glifos aos Caracteres no Inkscape</h2>



<p>No Inkscape, selecione&nbsp;<strong>File&gt;New&gt;fontforge_glyph</strong>. Essa opção adiciona as predefinições necessárias para criação coerente da família tipografica.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-selecionar-fontforge-tutorial-fonte.jpg" alt="New FontForge_Glyph"/></figure>



<p>Com o documento criado, importe os glifos (<strong>File&gt;Import</strong>) criado anteriormente por você. Caso você tenha feito todos os glifos no mesmo arquivo, o Inkscape irá importar todos agrupados na organização que foi salvo.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-importar-svg-tutorial-fonte.jpg" alt="Importar Arquivo no Inkscape"/></figure>



<p>Quando o arquivo é importado, ele vem agrupado e com algumas configurações que o Inkscape não reconhece corretamente.<br>Siga os passos abaixo para não haver erros e incompatibilidades:</p>



<p>Selecione o objeto, clique com o botão direito e escolha Ungroup. Faça isso quantas vezes for necessário até o objeto estar totalmente desagrupado;</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-ungroup-tutorial-fonte.jpg" alt="Desagrupar"/></figure>



<p>Ainda com o objeto selecionado, vá no menu&nbsp;<strong>Path&gt;Combine</strong>;</p>



<p>Em seguida vá no menu&nbsp;<strong>Path&gt;Union</strong>;</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-combine-union-tutorial-fonte.jpg" alt="Combinar e Unir"/></figure>



<p>Essas ações são necessárias para que o glifo se torne um unico objeto e possa ser anexado corretamente ao caractere escolhido.</p>



<p>O próximo passo é abrir a tela de edição de fontes. Selecione o menu&nbsp;<strong>Text&gt;SVG Font Editor</strong>.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-svg-font-editor-tutorial-fonte1.jpg" alt="Abrir o SVG Font Editor"/></figure>



<p>Será aberto o painel SVG Font Editor, que permite você criar uma fonte no formato SVG (interpretado pela maioria dos smartphones). A primeira coisa a se fazer é criar um nome e família para a fonte. No painel de edição de fonte, e com a guia&nbsp;<strong>GLOBAL SETTINGS</strong>&nbsp;ativada, clique &nbsp;no botão New. Em seguida, clique duas vezes no nome que foi gerado para que possa modificar e colocar o nome que você quiser.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-colocar-nome-fonte.jpg" alt="Colocando Nome na Fonte"/></figure>



<p>Agora, ainda no mesmo painel, abra a guia&nbsp;<strong>GLYPH</strong>&nbsp;e clique no botão&nbsp;<strong>Add Glyph</strong>, ele irá criar uma nova linha na tabela Glyph name/Matching string. Você deve dar dois cliques no nome criado para editar o nome. Ao lado, você deve dar dois cliques no espaço vazio (logo abaixo de Matching String) e você descobrirá (sim, está escondido) que você pode editar esse campo. Simplesmente digite a letra a qual você quer assimilar o glifo.</p>



<p>No exemplo a seguir, assimilei o meu glifo de Editar a letra &#8220;e&#8221; minúscula. Vale salientar que você pode vincular a qualquer caractere que deseja, inclusive caracteres especiais como #,ø,®,†, etc.</p>



<p>Por fim, selecione o objeto (ou grupo) que você quer vincular ao caractere e clique no botão Get curves from selection. Para verificar se foi adicionado corretamente, digite, em Preview Text, o caractere que deseja verificar.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/inkscape-svg-font-editor-tutorial-fonte.jpg" alt="Relacionar Fonte ao Caractere"/></figure>



<p><strong>ATENÇÃO</strong>: Caso o ícone não apareça no Preview Text corretamente, como aparecer pequeno ou simplesmente não aparecer, você deve repetir os passos acima de&nbsp;<strong>Ungroup, Combine e Union do objeto.</strong>&nbsp;Provavelmente o objeto não foi preparado corretamente e por isso não relacionou como deveria.</p>



<p>Salve o arquivo normalmente. No formato padrão de&nbsp;<strong>SVG do Inkscape.</strong></p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/icone-salvar-tutorial-fonte.jpg" alt="Salvar Fonte Criada no Inkscape"/></figure>



<h2 class="wp-block-heading">Transformando a fonte SVG em OTF ou TTF</h2>



<p>O arquivo SVG está pronto. Agora precisamos converter para uma fonte usável pelo sistema operacional. Há muitos sites que fazem essa conversão.</p>



<p>O que recomendo que faça&nbsp;a conversão é o&nbsp;<a title="Abrir o Free Font Converter" href="http://www.freefontconverter.com/" target="_blank" rel="noopener">FreeFontConverter</a>. Basta importar o seu arquivo SVG, escolher o formato (Aconselho OTF, primeiramente, que tem melhor acabamento) e depois clicar em convert. Ele fará o download automaticamente da fonte.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/selecionar-converter-tutorial-fonte.jpg" alt="Converter a Fonte em OTF"/></figure>



<p><strong>ATENÇÃO: Caso dê erro durante a conversão, você pode tentar salvar o arquivo em SVG Optmized, no Inskscape.</strong></p>



<p>Você pode ver que a fonte pode ser instalada normalmente no seu sistema operacional.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/fonte-convertida-tutorial-fonte.jpg" alt="Fonte Convertida"/></figure>



<h2 class="wp-block-heading">Usando a fonte personalizada em CSS e usando-a como ícone</h2>



<p>Para preparar um pacote com sua fonte personalizada, para ser usada em um site, o site&nbsp;<strong>FontSquirrel</strong>&nbsp;disponibiliza o&nbsp;<a title="Site Para Converter Fonts" href="http://www.fontsquirrel.com/tools/webfont-generator" target="_blank" rel="noopener">WebfontGenerator</a>. Para usá-lo basta enviar a sua fonte em OTF ou TTF, concorde com os termos e gere o kit.</p>



<figure class="wp-block-image"><img decoding="async" src="https://velhobit.com.br/wp-content/uploads/2017/01/font-face-tutorial-fonte.jpg" alt="Gerador de Fontes da FontSquirrel"/></figure>



<p>Feito o download, está na hora de incorporamos a fonte no seu CSS. Para isso, basta você copiar as fonts que foram geradas no kit para uma pasta font (ou outra de sua preferência) no seu site e chamar via CSS.</p>



<pre class="wp-block-preformatted prettyprint">@font-face {
    font-family: "minhafonteregular";

    src: url("fonts/minhafonte-webfont.eot");
    src: url("fonts/minhafonte-webfont.eot?#iefix") format("embedded-opentype"),
         url("fonts/minhafonte-webfont.woff") format("woff"),
         url("fonts/minhafonte-webfont.ttf") format("truetype"),
         url("fonts/minhafonte-webfont.svg#minhafonteregular") format("svg");

    font-weight: normal;
    font-style: normal;
}</pre>



<p>Para usar como ícone em um botão (ou em qualquer outro componente HTML5), basta você usar a opção content, do CSS3, como descrito abaixo:</p>



<pre class="wp-block-preformatted prettyprint">button.editar{
        padding:10px;
}

button.editar:before{
        font-family: "minhafonteregular";
        font-size:36px;
        content:"e";
        -webkit-content:"e";
        -moz-content:"e";
        -o-content:"e";
        -ms-content:"e";
}</pre>



<p>E basta adicionar a tag Button com a classe determinada:</p>



<p><strong>&lt;button class=&#8221;editar&#8221;&gt; &lt;/button&gt;</strong></p>



<p><span style="color: #800000;"><strong>ATENÇÃO (iOS): Devido a padrões do iOS, o ícone só vai aparecer se tiver uma cor de fundo (devido ao webkit-appearance), se você quiser, entretanto, usar a cor padrão, utilize o CSS abaixo:</strong></span></p>



<p><span style="color: #800000;"><strong>button{<br>background-color: buttonface;<br>}</strong></span></p>



<p>Abaixo, você pode ver o exemplo usado no vídeo (no topo do post), que tem uma forma um pouco diferente de usar.</p>



<center><button></button></center>



<p>Qualquer dúvida, deixe um comentário, mande uma mensagem no skype ou por email. Siga @velhobit no Twitter e curta nossa página no Facebook.</p>



<p>Até o próximo Tutorial.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como redirecionar seu site / página por localização</title>
		<link>https://velhobit.com.br/programacao/como-redirecionar-seu-site-pagina-por-localizacao.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sat, 25 Aug 2018 22:57:28 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[geolocalização]]></category>
		<category><![CDATA[idioma]]></category>
		<category><![CDATA[localização]]></category>
		<category><![CDATA[muitos idiomas]]></category>
		<category><![CDATA[multidioma]]></category>
		<category><![CDATA[redirecionamento]]></category>
		<category><![CDATA[redirecionar]]></category>
		<category><![CDATA[site multidioma]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1464</guid>

					<description><![CDATA[Uma forma simples e rápida de fazer o redirecionamento via Javascript ou PHP / cURL do seu site a partir da localização. Perfeito para sites multi-idiomas.]]></description>
										<content:encoded><![CDATA[<p>As vezes você precisa trabalhar com sites ou projetos multi-idiomas. Alguns desses projetos carregam dinamicamente a tradução ou possui páginas específicas em outro idioma. Redirecionar automaticamente para o conteúdo específico da região é um comportamento fundamental para uma boa experiência do usuário.</p>
<h2>Detecção por Geolocalização</h2>
<p>A forma mais simples e rápida de fazer isso, é através de uma API open-source online chamada <del>Nekudo (<a href="https://geoip.nekudo.com/">https://geoip.nekudo.com/</a>)</del>. O Nekudo não está mais disponível e virou IPI. Você precisa fazer um cadastro gratuito em https://ipapi.com/product e pegar sua chave e cadastrar o IP. Na dúvida de saber qual o IP do seu server, abra o seu prompt de comando (windows) ou terminal (Unix/Mac/Linux) e digite ping seusite.com.br.</p>
<p>A forma ideal de fazer isso é a partir da sugestão, ao invés do redirecionamento direto, como é feito no site da Apple e Adobe. Isso porque o usuário pode estar em viagem ou simplesmente preferir usar o conteúdo em outro idioma.</p>
<p>Vamos para a prática.</p>
<h2>Javascript</h2>
<p>Para facilitar, vamos usar um jQuery básico, que está presente em quase todos os sites e sistemas. Basta um &#8220;ajaxizinho&#8221; apenas para chamarmos a API do Geoplugin.</p>
<p>A URL <strong>https://api.ipapi.com/, seguido da chave e IP </strong>já devolve os dados em formato JSON. Como ele vai pegar o IP atual do usuário, não é necessário passar o IP:</p>
<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="js" name="mshighlighter" >
var ip = "check";
var access_key = "minhachavedeacesso";
jQuery.ajax({
url:'https://api.ipapi.com/' + ip + '?access_key=' + access_key
dataType: "json",
success: function(data){
console.log(data);
}
});</textarea></pre>
</div>
<p>O retorno então será:</p>
<div class="my-syntax-highlighter">
<pre id="result_code"></pre>
</div>
<p>Agora basta tratarmos o código para que execute uma ação e depois redirecione. Ficando assim:</p>
<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="js" name="mshighlighter" >

var ip = "check";

var access_key = "minhachavedeacesso";
jQuery.ajax({
url: 'https://api.ipapi.com/' + ip + '?access_key=' + access_key,
dataType: "json",
success: function(data){
if(data.country.code != "BR"){
var redirecionar = confirm("Hi, visitor! We checked you are in " + data.country.name + ". Would you like to visit english version?");
}
if(redirecionar){
window.location = "https://meusite.com/en/";//outra url
}
}
});</textarea></pre>
</div>
<p>Nesse ponto, apenas verificamos se não está no Brasil e ele vai redirecionar a página em questão.</p>
<p>Todavia, ele não vai guardar essa preferência. Logo, toda vez que a pessoa entrar no site, ela vai ter que responder a pergunta novamente. Mas para evitar que isso ocorra, podemos usar o localStorage. Garantindo assim que seja memorizada a opção e evitando que a API seja requerida desnecessariamente. O código final ficaria assim:</p>
<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="js" name="mshighlighter" >

var ip = "check";

var access_key = "minhachavedeacesso";

//Verifica primeiro se já tem o country code salvo
if(localStorage.sel_country_code == undefined){
jQuery.ajax({
url: 'https://api.ipapi.com/' + ip + '?access_key=' + access_key
dataType: "json",
success: function(data){
if(data.country.code != "BR"){
var redirecionar = confirm("Hi, visitor! We checked you are in " + data.country.name + ". Would you like to visit english version?");
}
if(redirecionar){
//Gravar o country_code
localStorage.sel_country_code = data.country.code
window.location = "https://meusite.com/en/";//outra url
}
}
});
}else{
//Caso já esteja definido
window.location = "https://meusite.com/en/";//outra url
//Obs. Use o valor armazenado em localStorage.sel_country_code, caso você tenha mais de um outro idioma
}</textarea></pre>
</div>
<p><center><br />
<button id="botaoTestes">Clique aqui para testar.</button></center></p>
<h2>Como saber se está funcionando?</h2>
<p>Para testar, basta você usar um serviço de VPN. Você pode fazer isso através de algum site, programa ou simplesmente rodando pelo Opera, que já possui uma VPN própria e é ótimo mantê-lo instalado para testes. Recomendamos que você use o Opera, pois, além de ser um bom navegador, ele é mais seguro para evitar usar sites duvidosos ou serviços de terceiros. O Opera Developer é uma boa opção e possui VPN integrado. <em><strong>Clique na imagem para ser direcionado a página de download oficial</strong></em>.</p>
<p><a href="https://www.opera.com/pt-br/computer/beta" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1477" src="https://velhobit.com.br/wp-content/uploads/2018/08/opera-developer.jpg" alt="Baixar Opera Developer" width="925" height="436" srcset="https://velhobit.com.br/wp-content/uploads/2018/08/opera-developer.jpg 925w, https://velhobit.com.br/wp-content/uploads/2018/08/opera-developer-400x189.jpg 400w, https://velhobit.com.br/wp-content/uploads/2018/08/opera-developer-768x362.jpg 768w, https://velhobit.com.br/wp-content/uploads/2018/08/opera-developer-600x283.jpg 600w" sizes="auto, (max-width: 925px) 100vw, 925px" /></a></p>
<p>Após instalar o Ópera, para habilitar o VPN, basta ir nas <strong>configurações</strong>, a partir do símbolo do <span style="color: #ff0000;"><em><strong>O</strong></em></span>, no canto superior esquerdo.</p>
<p><img decoding="async" class="aligncenter" style="max-width: 350px;" src="https://velhobit.com.br/wp-content/uploads/2018/08/opera-opcoes.jpg" /></p>
<p>Indo na guia Avançados &gt; Recursos, ele vai retornar a primeira opção como VPN. Simplesmente a habilite.</p>
<p><img loading="lazy" decoding="async" class="aligncenter wp-image-1482 size-full" src="https://velhobit.com.br/wp-content/uploads/2018/08/config-vpn.jpg" alt="" width="1017" height="304" srcset="https://velhobit.com.br/wp-content/uploads/2018/08/config-vpn.jpg 1017w, https://velhobit.com.br/wp-content/uploads/2018/08/config-vpn-400x120.jpg 400w, https://velhobit.com.br/wp-content/uploads/2018/08/config-vpn-768x230.jpg 768w, https://velhobit.com.br/wp-content/uploads/2018/08/config-vpn-600x179.jpg 600w" sizes="auto, (max-width: 1017px) 100vw, 1017px" /></p>
<p>Feito isso, a opção de VPN vai ficar visível e você poderá testar o funcionamento em diversos locais.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-1484" style="max-width: 450px;" src="https://velhobit.com.br/wp-content/uploads/2018/08/vpn.jpg" alt="" width="600" height="663" srcset="https://velhobit.com.br/wp-content/uploads/2018/08/vpn.jpg 600w, https://velhobit.com.br/wp-content/uploads/2018/08/vpn-362x400.jpg 362w, https://velhobit.com.br/wp-content/uploads/2018/08/vpn-543x600.jpg 543w" sizes="auto, (max-width: 600px) 100vw, 600px" /></p>
<h2>Ah, mas eu não quero redirecionar assim, quero que seja pelo servidor</h2>
<p>Muito bem, digamos que você queira que o redirecionamento seja feito direto pelo servidor porque você é mal que nem um pica-pau. Sem problemas.</p>
<p>Para isso, você pode usar o cURL da sua linguagem de preferência e fazer o redirecionamento através dela. Aqui vai um exemplo mais comum, em PHP:</p>
<div class="my-syntax-highlighter">
<pre><textarea id="mshighlighter" class="mshighlighter" language="php" name="mshighlighter" >
&lt;?php

// IP e chave
$ip = $_SERVER['REMOTE_ADDR'];
$access_key = 'SUA CHAVE DE ACESSO';

// Inicializar CURL:
$ch = curl_init('http://api.ipapi.com/'.$ip.'?access_key='.$access_key.'');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

// Capturar dados
$json = curl_exec($ch);
curl_close($ch);

// Decode JSON:
$retorno = json_decode($json, true);

if($retorno['country_code'] != "BR"){
header("location: https://seusite.com/idioma");
die();
}
?&gt;</textarea></pre>
</div>
<p><em>Lembrando que isso precisa ser inserido antes mesmo do doctype, pois se não pode retornar o erro de Headers Already Sent.</em></p>
<h2>Concluindo</h2>
<p>É bem simples testar o IP quanto a localização. Há diversos serviços, alguns pagos e outros gratuitos, que fazem esse tipo de redirecionamento. Também há plugins e extensões que você pode instalar em seu servidor, mas certamente a demonstrada aqui vai servir para a grande maioria dos projetos.</p>
<p>Curta e compartilhe <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f600.png" alt="😀" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Como Selecionar o Item de Uma Tabela HTML</title>
		<link>https://velhobit.com.br/tutoriais/como-selecionar-o-item-de-uma-tabela-html.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Tue, 26 Jun 2018 22:29:47 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[experiência]]></category>
		<category><![CDATA[front]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[html]]></category>
		<category><![CDATA[interface]]></category>
		<category><![CDATA[interface do usuário]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[tabela]]></category>
		<category><![CDATA[table]]></category>
		<category><![CDATA[ui]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[web]]></category>
		<category><![CDATA[web design]]></category>
		<category><![CDATA[webdesign]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1398</guid>

					<description><![CDATA[Um tutorial rapidinho para mostrar como selecionar as linhas de uma tabela HTML simples. Para isso, usamos um pouco de CSS e Javascript puro.]]></description>
										<content:encoded><![CDATA[<p>Uma dúvida foi postada no grupo de <a href="https://www.facebook.com/groups/designdesenvolvimento/" target="_blank" rel="noopener">Design e Programação</a> de nossa página, lá no Facebook, hoje. Essa pergunta era referente a como selecionar de uma linha de uma tabela HTML?</p>
<p>Para tal, basta usar um pouco de Javascript e CSS.</p>
<h2>Montando a Tabela</h2>
<p>Vamos montar, para testar, uma tabela simples, respeitando a semântica HTML básica. Vamos aproveitar para colocar logo um botão, que vai ser por onde podemos visualizar os dados da linha selecionada:</p>
<pre class="prettyprint">&lt;table id='minhaTabela'&gt;
     &lt;thead&gt;
          &lt;tr&gt;
               &lt;th&gt;ID&lt;/th&gt;
               &lt;th&gt;Nome&lt;/th&gt;
               &lt;th&gt;Idade&lt;/th&gt;
          &lt;tr&gt;
     &lt;/thead&gt;
     &lt;tbody&gt;
          &lt;tr&gt;
               &lt;td&gt;01&lt;/td&gt;
               &lt;td&gt;Rodrigo&lt;/td&gt;
               &lt;td&gt;33&lt;/td&gt;
               &lt;/tr&gt;
          &lt;tr&gt;
               &lt;td&gt;02&lt;/td&gt;
               &lt;td&gt;Taynara&lt;/td&gt;
               &lt;td&gt;21&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
               &lt;td&gt;03&lt;/td&gt;
               &lt;td&gt;Raveny&lt;/td&gt;
               &lt;td&gt;22&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
               &lt;td&gt;04&lt;/td&gt;
               &lt;td&gt;Sérgio&lt;/td&gt;
               &lt;td&gt;51&lt;/td&gt;
          &lt;/tr&gt;
          &lt;tr&gt;
               &lt;td&gt;05&lt;/td&gt;
               &lt;td&gt;Alice&lt;/td&gt;
               &lt;td&gt;20&lt;/td&gt;
          &lt;/tr&gt;
     &lt;/tbody&gt;
&lt;/table&gt;

&lt;button id="visualizarDados"&gt;Visualizar Dados&lt;/button&gt;
</pre>
<p>Agora precisamos incluir um estilo para que a tabela fique mais elegante.</p>
<p>É importantíssimo prestar atenção ao <em>class</em> &#8220;selecionado&#8221; que vai ser a referência para o seu javascript saber qual linha está selecionada na tabela.</p>
<pre class="prettyprint">#minhaTabela{
  width:80%;
  margin:0 auto;
  border:0;
  box-shadow: 0 5px 30px darkgrey;
  border-spacing: 0;
}

#minhaTabela thead th{
  font-weight: bold;
  background-color: black;
  color:white;
  
  padding:5px 10px;
}

#minhaTabela tr td{
  padding:5px 10px;
  text-align: center;
  
  cursor: pointer; /**importante para não mostrar cursor de texto**/
}

#minhaTabela tr td:last-child{
  text-align: right;
}

/**Cores**/
#minhaTabela tr:nth-child(odd){
  background-color: #eee;
}

/**Cor quando passar por cima**/
#minhaTabela tr:hover td{
  background-color: #feffb7;
}

/**Cor quando selecionado**/
#minhaTabela tr.selecionado td{
  background-color: #aff7ff;
}

button#visualizarDados{
  background-color: white;
  border: 1px solid black;
  width:50%;
  margin: 10px auto;
  padding:10px 0;
  display: block;
  color: black;
}
</pre>
<h2>Javascript</h2>
<p>Para sermos mais justos, vamos fazer o exemplo usando Javascript puro. No nosso exemplo, vamos contemplar a opção de selecionar uma única linha ou mais de uma linha, opção determinada apenas por um parâmetro. Ainda vamos ver como manipular os dados.</p>
<p>Inicialmente, precisamos capturar a tabela e adicionar, à ação de clique, uma função que adicione ou remova a classe de seleção:</p>
<pre class="prettyprint">var tabela = document.getElementById("minhaTabela");
var linhas = tabela.getElementsByTagName("tr");

for(var i = 0; i &lt; linhas.length; i++){
	var linha = linhas[i];
  linha.addEventListener("click", function(){
  	//Adicionar ao atual
		selLinha(this, false); //Selecione apenas um
                //selLinha(this, true); //Selecione quantos quiser
	});
}
</pre>
<p>A função selLinha() vai ser responsável por adicionar ou remover a <em>class</em> &#8220;selecionado&#8221; do nó. Passamos também um parâmetro que vai determinar se poderá selecionar mais que uma linha ou apenas uma. O primeiro laço, caso múltiplos seja falso, irá apenas desmarcar todos as linhas antes de marcar a linha clicada.</p>
<pre class="prettyprint">/**
Caso passe true, você pode selecionar multiplas linhas.
Caso passe false, você só pode selecionar uma linha por vez.
**/
function selLinha(linha, multiplos){
  if(!multiplos){
  	var linhas = linha.parentElement.getElementsByTagName("tr");
        for(var i = 0; i &lt; linhas.length; i++){
           var linha_ = linhas[i];
           linha_.classList.remove("selecionado");    
        }
  }
  linha.classList.toggle("selecionado");
}
</pre>
<p>Agora vamos adicionar uma função ao clique do botão para que a gente possa visualizar os dados selecionados. Para isso, iremos justamente capturar apenas as linhas que tiverem a <em>class</em> &#8220;selecionado&#8221; e, através de um laço, vamos concatenar os valores dentro dos nós &lt;td&gt; da(s) linha(s) selecionada(s).</p>
<pre class="prettyprint">/**
Exemplo de como capturar os dados
**/
var btnVisualizar = document.getElementById("visualizarDados");

btnVisualizar.addEventListener("click", function(){
	var selecionados = tabela.getElementsByClassName("selecionado");
  //Verificar se eestá selecionado
  if(selecionados.length &lt; 1){
  	alert("Selecione pelo menos uma linha");
    return false;
  }
  
  var dados = "";
  
  for(var i = 0; i &lt; selecionados.length; i++){
  	var selecionado = selecionados[i];
    selecionado = selecionado.getElementsByTagName("td");
    dados += "ID: " + selecionado[0].innerHTML + " - Nome: " + selecionado[1].innerHTML + " - Idade: " + selecionado[2].innerHTML + "\n";
  }
  
  alert(dados);
});
</pre>
<h2>Vamos Testar?</h2>
<table id="minhaTabela">
<thead>
<tr>
<th><span style="font-weight: 400;">ID</span></th>
<th><span style="font-weight: 400;">Nome</span></th>
<th><span style="font-weight: 400;">Idade</span></th>
</tr>
</thead>
<tbody>
<tr>
<td>01</td>
<td>Rodrigo</td>
<td>33</td>
</tr>
<tr>
<td>02</td>
<td>Taynara</td>
<td>21</td>
</tr>
<tr>
<td>03</td>
<td>Raveny</td>
<td>22</td>
</tr>
<tr>
<td>04</td>
<td>Sérgio</td>
<td>51</td>
</tr>
<tr>
<td>05</td>
<td>Alice</td>
<td>20</td>
</tr>
</tbody>
</table>
<p><button id="visualizarDados">Visualizar Dados</button></p>
<p>No entanto, se você preferir ver todo código completo, acesse o JsFiddle incorporado abaixo:</p>
<p><script async src="//jsfiddle.net/velhobit/cr7wz0a4/embed/js,html,css,result/dark/"></script><br />
Gostou do post curtinho? Tem dúvidas? Deixe seu comentário e compartilhe com quem você achar que vai gostar. Aproveite para entrar no nosso grupo de <a href="https://www.facebook.com/groups/designdesenvolvimento/" target="_blank" rel="noopener">Design e Programação</a> no <a href="https://www.facebook.com/velhobit/">Facebook ou em nossa página</a>. Acompanhe-nos no <a href="https://twitter.com/velhobit/">Twitter </a>e <a href="https://instagram.com/velhobit/">Instagram</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Gráfico / Loader Radial com CSS e Javascript Puro</title>
		<link>https://velhobit.com.br/tutoriais/grafico-loader-radial-com-css-e-javascript-puro.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Tue, 01 May 2018 17:24:17 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[chart]]></category>
		<category><![CDATA[cheat]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[graphic]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[loader]]></category>
		<category><![CDATA[loading]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1251</guid>

					<description><![CDATA[Chart (ou loader) usando CSS3 e algumas pequenas linhas de Javascript puro. Talvez não seja a melhor solução, mas é um bom exercício de lógica e o resultado é leve e responsivo.]]></description>
										<content:encoded><![CDATA[<p><span style="color: #ff9900;"><em>Disclaimer: If you are coming from an english or international chat/group, please roll to jsfiddle at the end of this post and get all comments and explanations in english or access <a style="color: #ff9900;" href="https://jsfiddle.net/velhobit/oxeynj3t/" target="_blank" rel="noopener">jsfiddle link</a>.</em></span></p>
<p>Bibliotecas de gráficos existem aos montes. A maioria pesada e com poucas (ou complexas) opções de personalização. De modo que, pensei, será que é possível usar a animação do CSS para criar um gráfico leve? Como exercício, talvez eu pudesse desenvolver uma solução de gráfico radial que pudesse funcionar bem. Esse questionamento veio a partir da pergunta de uma pessoa, em um grupo, que queria criar um loading infinito com CSS.</p>
<h2>Criando o CSS</h2>
<p>Para poder criar a animação do load, pensei em diversas formas que já são usadas como solução, como o gradient ou gambiarras com contornos, mas eles não usam realmente o conceito da animação do raio a partir do centro. Para resolver, pensei em apelar para a trigonometria. Dividi então o círculo em 4 triângulos retângulos.</p>
<p><center><br />
<img loading="lazy" decoding="async" width="700" height="700" class="aligncenter size-full wp-image-1253" style="max-width: 300px; height: auto;" src="https://velhobit.com.br/wp-content/uploads/2018/05/triangulo-circulos.png" alt="" srcset="https://velhobit.com.br/wp-content/uploads/2018/05/triangulo-circulos.png 700w, https://velhobit.com.br/wp-content/uploads/2018/05/triangulo-circulos-400x400.png 400w, https://velhobit.com.br/wp-content/uploads/2018/05/triangulo-circulos-600x600.png 600w, https://velhobit.com.br/wp-content/uploads/2018/05/triangulo-circulos-110x110.png 110w" sizes="auto, (max-width: 700px) 100vw, 700px" /></center>A partir daí podemos considerar a animação a partir de cada dos vértices da hipotenusa, se abrindo do raio, formando o triângulo retângulo, como no exemplo abaixo:</p>
<div class="triangulo"></div>
<pre class="prettyprint">&lt;style&gt;
 .triangulo{
    width: 200px;
    height: 200px;
    background-color: #c1f347;
    margin:0 auto;
    animation: triangle 3s infinite  alternate;
}

@keyframes triangle {
    from   {
        clip-path: polygon(50% 0%, 0% 100%, 0 100%);
    }
    to {
        clip-path: polygon(50% 0%, 0% 100%, 100% 100%);
    }
}
&lt;style&gt;</pre>
<p>OK, conseguimos criar os triângulos com o <em><strong>clip-path</strong></em> do CSS. Graças ao ele podemos colocar caminhos de uma imagem a partir de vértices. Mas como colocar isso nos 4 triângulos? Não faria o menor sentido colocar os triângulos um do lado do outro. Como fazer então para utilizar um caminho completo para dar o efeito de transição radial?</p>
<p>Para isso, basta fazermos um cálculo simples. Quantos vértices seriam necessários para criar um polígono que dê a volta? Bem, basta contarmos o vértices do quadrado (4) mais um ao centro que define os triângulos e mais um para fechar a animação. Ou seja, precisamos de um hexagono.</p>
<div class="hexagono"></div>
<p><!--?prettify linenums=true?--></p>
<pre class="prettyprint">&lt;style&gt;
 .hexagono{
     width: 250px;
     height: 250px;
     background-color: #f98b2a;
     margin: 0 auto;
     animation: hexagon 3s infinite  alternate;
}

@keyframes hexagon {
     from   {
          clip-path: polygon(50% 0%, 90% 20%, 100% 60%, 75% 100%, 25% 100%, 0% 60%, 10% 20%);
          background-color: #2af9f7;
     }
    to {
          clip-path: polygon(50% 0%, 100% 0, 100% 60%, 100% 100%, 0 100%, 0% 60%, 0 0);
     }
}
&lt;style&gt;</pre>
<p>Agora basta manipular os vértices do hexagono para se comportar similar ao triângulo retângulo, levando os pontos do vértice, em fila, sempre ao próximo ponto do quadrado.</p>
<div class="quadrado"></div>
<pre class="prettyprint">&lt;style&gt;
 .quadrado{
    width: 250px;
    height: 250px;
    background-color: #f98b2a;
    margin:0 auto;
    animation: square 3s infinite  alternate;
}

@keyframes square {
    0%   {
        clip-path: polygon(100% 0, 100% 0%, 100% 0%, 100% 0%, 100% 0%, 50% 50%);
        background-color: #36ff9a;
    }
    25%  {
        clip-path: polygon(100% 0, 100% 100%, 100% 100%, 100% 100%, 100% 100%, 50% 50%);
        background-color: #fccf40;
    }
    50%{
        clip-path: polygon(100% 0, 100% 100%, 0% 100%, 0% 100%, 0 100%, 50% 50%);
        background-color: #f40696;
    }
    75%  {
        clip-path: polygon(100% 0, 100% 100%, 0 100%, 0 0%, 0 0, 50% 50%);
        background-color: #55aadd;
    }
    100% {
        clip-path: polygon(100% 0, 100% 100%, 0 100%, 0 0, 100% 0, 50% 50%);
        background-color: #36ff9a;
    }
}
&lt;style&gt;</pre>
<p>Basta colocar agora a animação como linear, para evitar as pausas (o padrão possui um ease) e adicionar um elemento acima com um <em><strong>overflow: false</strong></em> e um <em><strong>border-radius: 50%</strong></em>, de forma a ficar realmente circular:</p>
<div class="circulo"></div>
<h2>Controlando com Javascript</h2>
<p>Podemos fazer um jeitinho para que o Javascript controle a animação. Para isso, podemos usar algumas propriedades que controlam a animação. Em especial, vamos poder pausar e continuar a animação, através do parâmetro <em><strong>animationPlayState</strong></em>.</p>
<p>O código completo está disponível pelo jsFiddle. O código está todo comentado e pode ser testado diretamente abaixo:</p>
<div class="area">
<p><!--This is the Structure of your chart--></p>
<div class="chart">
<div id="radioChartContent" class="radio_chart"></div>
<div class="cap"></div>
<div id="percentValue" class="value">0%</div>
</div>
</div>
<p><!--This is just the example buttons--></p>
<div class="area"><button onclick="goTo(80)">Go To 80%</button><br />
<button onclick="goTo(20)">Go To 20%</button><br />
<button onclick="goTo(100)">Full</button><br />
<button onclick="reset()">Reset</button></div>
<p><span style="color: #ff0000;"><em><strong>Obs. Não use filtro blur ou muitas sombras se quiser compatibilidade com o Safari iOS.</strong></em></span></p>
<p><script async src="//jsfiddle.net/velhobit/ruhqy9L0/embed/result,js,html,css/dark/"></script></p>
<p>Provavelmente, esta não é a melhor solução para criação de um gráfico radial. Mas é interessante vermos que podemos desenvolver novas soluções, e mais leves, a partir de tecnologias mais recentes. Se você gostou, compartilhe, se tem alguma dúvida, comente. Aproveite para curtir nossa página do Facebook e entrar no grupo, através do link abaixo.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>CSS &#8211; Como usar transition com display:block?</title>
		<link>https://velhobit.com.br/tutoriais/css-como-usar-transition-com-displayblock.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Tue, 24 Apr 2018 19:17:00 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[animação]]></category>
		<category><![CDATA[cheats]]></category>
		<category><![CDATA[código]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[dicas]]></category>
		<category><![CDATA[fiddle]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[site]]></category>
		<category><![CDATA[transição]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[webdesign]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=1230</guid>

					<description><![CDATA[Uma dica sobre como ocultar e mostrar de forma suave um elemento HTML usando CSS3. Use transitions para melhorar a interação de seu front-end e torná-lo mais agradável ao usuário.]]></description>
										<content:encoded><![CDATA[<p>Todos sabemos que transições são importantes para diminuir a sensação de repentinidade para o usuário e preparar o cérebro para, aos poucos, compreender a nova informação.</p>
<p>Porém, o <strong><i> transition</i></strong> do <strong>CSS3</strong> não funciona uniformemente com todos os parâmetros. Quem nunca quis que um elemento <strong>HTML</strong> em tela sumisse aos poucos?</p>
<p>O mais comum é utilizar o bom e velho <strong>display: none;</strong>, porém este simplesmente não funciona ao aplicar um transition. Usemos a lógica de que a passagem de um bloco para um nada não é uma transição. <strong>No CSS, uma transição inicialmente precisa ser um comando baseado em números</strong>.</p>
<h2>Como usar o CSS para fazer a transição de um objeto sumir?</h2>
<p>Para realizar esta ação, vamos usar um pequeno truque. Ao invés de simplesmente não mostrar o objeto, vamos desativar sua propriedade de ser manipulável com o mouse ou toque. Para isso podemos usar a propriedade pointer-events, ficando:</p>
<pre class="prettyprint">div{
    opacity: 1;
    transition: opacity .5s linear;
}

div.hide{
    opacity: 0;
    pointer-events: none;
}</pre>
<p>Para fazer o objeto desaparecer vamos usar um pouco de JavaScript apenas para adicionar ou remover a classe CSS da div:</p>
<pre class="prettyprint">function ocultar(){
    var element = document.getElementById("idDaDiv");
          element.classList.add("hide");
}
function mostrar(){
    var element = document.getElementById("idDaDiv");
          element.classList.remove("hide");
}</pre>
<p><strong>Vamos testar?</strong></p>
<p><script async src="//jsfiddle.net/velhobit/x6gy874d/embed/result,js,html,css/dark/"></script></p>
<p>Mas e se você quiser que ele também não ocupe um espaço? Pois pode ficar um buraco perturbador. Nesse caso você pode modificar a altura do elemento para poder aproveitar melhor esse espaço. Todavia, a propriedade <em><strong>height</strong></em> não é animável (<em>talvez por possuir uma propriedade auto</em>). Para esse caso, você precisa usar o <em><strong>max-height</strong> </em>para realizar esta animação.</p>
<pre class="prettyprint">div {
  overflow:hidden;
  max-height: 200px;
  transition: max-height 1s ease-in-out;
}

div.hide {
  max-height: 0;
  pointer-events: none;
}</pre>
<p>Lembre-se que para evitar que o conteúdo seja mostrado independente da <em><strong>div</strong></em> que você vai aplicar a transição, será necessário colocar a propriedade <em><strong>overflow</strong> </em>como <em><strong>hidden</strong></em>. Também é importante salientar que a propriedade <em><strong>max-height</strong></em> só é animável caso você use as medidas fixas em pixels. Como ele determina apenas o tamanho máximo, não vai influenciar se você colocar um tamanho maior que o esperado, o que se torna funcional também para responsividade.</p>
<p><strong>Vamos Testar?</strong></p>
<p><script async src="//jsfiddle.net/velhobit/v4cmyaLw/embed/result,js,html,css/light/"></script></p>
<p>Se acredita que essa dica de CSS é útil para mais alguém, compartilhe e curta esta página!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Efeito Neon com CSS 3, SVG e um tiquinho de Javascript (Texto e Imagem)</title>
		<link>https://velhobit.com.br/tutoriais/efeito-neon-com-css-3-svg-e-um-tiquinho-de-javascript-texto-e-imagem.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sun, 24 Dec 2017 17:03:07 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[ano novo]]></category>
		<category><![CDATA[cores]]></category>
		<category><![CDATA[css]]></category>
		<category><![CDATA[css3]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[efeitos]]></category>
		<category><![CDATA[estilo]]></category>
		<category><![CDATA[fontes]]></category>
		<category><![CDATA[iluminação]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[luminosidade]]></category>
		<category><![CDATA[luz]]></category>
		<category><![CDATA[neon]]></category>
		<category><![CDATA[sabre]]></category>
		<category><![CDATA[starwars]]></category>
		<category><![CDATA[tipografia]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[webdesign]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=915</guid>

					<description><![CDATA[Já pensou como seria legal fazer um efeito neon com CSS e um pouquinho de Javascript puro? E que tal colocar sua logo, uma mensagem de ano novo ou até mesmo um Sabre de Luz, de StarWars?]]></description>
										<content:encoded><![CDATA[<p>O final do ano é o momento perfeito para aprender CSS com efeitos divertidos para o Ano Novo. Graças aos navegadores modernos, podemos fazer animações e efeitos interessantes e divertidos de forma leve e funcional. Que tal fazer um efeito neon divertido e interessante sem nenhum framework?</p>
<p><b><span style="color:red;">ATENÇÃO:</span> Devido a quantidade de código e efeitos nesta página, pode apresentar lentidão se você for testar os exemplos abaixo em dispositivos móveis mais antigos (e até alguns mais recentes). Se você fizer o uso comedido, você não encontrará esse tipo de problemas.</b></p>
<h2>Adicionando a Logo SVG</h2>
<p>Para poder funcionar de forma leve, precisamos que a imagem que vamos adicionar seja em SVG. Dessa forma podemos manipular seus parâmetros de forma simples e adicionar efeitos.</p>
<p>Vários programas permitem exportar os objetos em SVG. Inkscape (que é de código aberto e gratuito), Illustrator ou CorelDRAW, todos eles possuem uma área de exportação específica.</p>
<p>No Illustrator, você pode usar a opção <em><strong>Exportar para Telas</strong></em>. Importante salientar que, para ficar com um melhor acabamento, coloque apenas contornos, sem preenchimento no objeto.</p>
<p><figure id="attachment_916" aria-describedby="caption-attachment-916" style="width: 842px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-916" src="https://velhobit.com.br/wp-content/uploads/2017/12/exportar-para-telas.jpg" alt="Opção de Exportar para Telas, no Adobe Illustrator CC" width="842" height="552" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/exportar-para-telas.jpg 842w, https://velhobit.com.br/wp-content/uploads/2017/12/exportar-para-telas-400x262.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/exportar-para-telas-768x503.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/12/exportar-para-telas-600x393.jpg 600w" sizes="auto, (max-width: 842px) 100vw, 842px" /><figcaption id="caption-attachment-916" class="wp-caption-text">Opção de Exportar para Telas, no Adobe Illustrator CC</figcaption></figure></p>
<p>O resultado será um arquivo de extensão SVG. O interessante é que você pode abrir esse arquivo em qualquer editor de texto e ver os detalhes. Você deverá guardar esse arquivo para uso posterior no HTML.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-917" src="https://velhobit.com.br/wp-content/uploads/2017/12/svg-img.jpg" alt="" width="745" height="670" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/svg-img.jpg 745w, https://velhobit.com.br/wp-content/uploads/2017/12/svg-img-400x360.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/svg-img-600x540.jpg 600w" sizes="auto, (max-width: 745px) 100vw, 745px" /></p>
<h2>Montando o HTML</h2>
<p>Uma vez criado o SVG, precisamos montar o HTML. Para isso, basta criar a área e organizar as classes e ids de forma apropriada, ficando:</p>
<pre class="prettyprint">&lt;div class="area_neon"&gt;
	&lt;center&gt;
		&lt;h1 id="texto_neon" class="neon"&gt;Bit Color | Velho Bit&lt;/h1&gt;
	&lt;/center&gt;
&lt;/div&gt;</pre>
<p>Apenas isso.</p>
<p>Em seguida, vamos colocar o SVG acima do <em><strong>h1</strong></em>. Para isso, basta copiar o código gerado acima do SVG. Em seguida, adicione a classe específica que vamos usar no CSS e mude (caso necessário) para uma <strong><em>id</em></strong> mais fácil de compreender.</p>
<p>Ficando algo similar a:</p>
<pre class="prettyprint">&lt;div class="area_neon"&gt;
	&lt;center&gt;
		&lt;svg class="neon_img" id="img_neon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 232.06 238.87"&gt;&lt;path d="M189.39,53.25c9.32,0,16.87,7.85,16.87,17.54s-7.55,17.54-16.87,17.54-16.86-7.85-16.86-17.54,7.55-17.54,16.86-17.54m7.9,20.35a4.71,4.71,0,1,0-4.53-4.71,4.62,4.62,0,0,0,4.53,4.71m-7.9-26.35c-12.6,0-22.86,10.56-22.86,23.54s10.26,23.54,22.86,23.54,22.87-10.56,22.87-23.54S202,47.25,189.39,47.25Z"/&gt;&lt;path d="M127,11.43c1.35,0,2.77,0,4.26,0,35.29.62,54.9,18.2,66,28.77,13.49,12.84,20.56,33,20.59,48.14,0,10.68-42.82,16-64.66,17.32-3.78.23-6.93.35-9.12.35-.59,0-1.1,0-1.55,0h-.41c-2.07,0-8.64.48-10.44,6.46-.32,1-1.23,6.3,2.46,6.3,1.3,0,3.17-.65,5.85-2.37a4.89,4.89,0,0,1,2.68-.89c4.62,0,6.69,8.54,5.11,9.14a2,2,0,0,1-.66.14c-1.25,0-1.54-1.8-1.56-4.17,0-1.4-1.78-2.23-3.59-2.23s-3.53.77-3.87,2.52c7.15,4.17,4.93,14.15,3.6,16.46-.3.53-.65.74-1,.74-1.14,0-2.18-2.4-1.19-3.17,1.29-1,3.47-3.36,2.28-6.13-1.09-2.52-2.4-3.86-4-3.86s-3.46,1.36-5.63,4.24c-1.56,2.05-2.59,2.81-3.86,2.81-2.26,0-5.25-2.45-13.19-4.32a20.2,20.2,0,0,0-4.66-.49,39.34,39.34,0,0,0-10.77,1.7c-19.4,5.66-43.45,25.47-33,59.46,5,16.33,16.27,22.2,27.42,22.2s22.05-5.79,26.72-12.88a15.84,15.84,0,0,0,1.65-3.22,31.73,31.73,0,0,0,1-3.51c1.78-7.59-.07-13.52-2.9-17.44-2.35-3.28-5.38-5.16-7.54-5.44,3.93,4.38-1.27,18.71-9.88,18.71a8.68,8.68,0,0,1-1-.06c-14-1.8-17-17.39-8.69-26.5a19.81,19.81,0,0,1,15-6.62,26.8,26.8,0,0,1,9.65,1.91,30.65,30.65,0,0,1,4.2,2c.41.24.8.49,1.19.76,11.21,7.84,13.5,30.64,3.89,47.88-6.57,11.8-18.72,21-37.41,21a63.65,63.65,0,0,1-7.51-.46c-1.1-.14-2.22-.3-3.36-.5-.51-.08-1-.16-1.55-.26A74.23,74.23,0,0,1,31.3,196.3C18.35,178.52,12.6,155,17.19,130.83,25.76,85.85,50.4,61,72.53,46.29a201.71,201.71,0,0,1,28.21-15.2c3.29-1.51-2.65-9.48-1.51-12.25,1.41-3.43,3.85-7.41,27.8-7.41m60.5,81.15c11.57,0,20.95-9.75,20.95-21.79S199.1,49,187.53,49s-20.95,9.75-20.95,21.79S176,92.58,187.53,92.58M127,5.43c-24.18,0-30.38,3.91-33.35,11.12-1.39,3.39-.07,6.87,1.1,10l.24.63A195.09,195.09,0,0,0,69.21,41.29C38,62,18.54,91.71,11.3,129.71c-4.73,24.85.79,50.41,15.15,70.13a80.46,80.46,0,0,0,50.06,32l1.27.22.4.07c1.32.22,2.51.4,3.64.53a68.58,68.58,0,0,0,8.23.51c18.86,0,34-8.54,42.66-24.06,11-19.83,8.39-45.86-5.7-55.71-.58-.41-1.12-.75-1.64-1.05a38.22,38.22,0,0,0-5-2.4,32.54,32.54,0,0,0-11.84-2.32,25.73,25.73,0,0,0-19.44,8.57,23.09,23.09,0,0,0-4.88,23.24c2.7,7.36,9,12.2,17.22,13.26a13.29,13.29,0,0,0,1.78.11c6,0,11.55-4,14.77-10.52a17.89,17.89,0,0,1-.29,7.33,24.29,24.29,0,0,1-.84,2.83,9.16,9.16,0,0,1-1,2c-3.25,4.94-12,10.18-21.71,10.18-7.38,0-17.13-3.12-21.69-18-3.56-11.62-2.91-22.08,1.94-31.08,5.2-9.64,15.3-17.44,27-20.86a33.17,33.17,0,0,1,9.09-1.46,14.3,14.3,0,0,1,3.28.33,47.43,47.43,0,0,1,8.41,2.82,15.44,15.44,0,0,0,6.16,1.66,8.84,8.84,0,0,0,4.83-1.44,8.36,8.36,0,0,0,.44,2.05,7.74,7.74,0,0,0,7.12,5.5,7.18,7.18,0,0,0,6.19-3.74,20.89,20.89,0,0,0,2.22-9.85,7.92,7.92,0,0,0,.78-.26c2.66-1,5.16-4,4.18-9.35a15.67,15.67,0,0,0-4.95-9c1.37,0,2.86-.13,4.43-.23,5.4-.33,24.35-1.68,41.4-5.27,13.47-2.84,28.92-7.45,28.9-18,0-15.51-7-37.75-22.46-52.48-10.14-9.65-31.24-29.74-70-30.42-1.5,0-3,0-4.36,0Zm60.5,81.15c-8.24,0-14.95-7.08-14.95-15.79S179.29,55,187.53,55s14.95,7.08,14.95,15.79-6.71,15.79-14.95,15.79Z"/&gt;&lt;/svg&gt;
		&lt;h1 id="texto_neon" class="neon"&gt;Bit Color | Velho Bit&lt;/h1&gt;
	&lt;/center&gt;
&lt;/div&gt;</pre>
<p>Porém, para ficar mais legal, devemos usar uma tipografia mais apropriada. No <a href="https://fonts.google.com/" target="_blank" rel="noopener">Google Fonts</a> podemos encontrar tipografias interessantes, com cantos arredondados, que nos darão resultados mais interessantes.</p>
<p>Uma vez escolhida a fonte, clique no <em>Select this Font</em> (no Google Fonts) e ele vai dar um código similar a este abaixo, que você deverá colocar dentro do <strong><em>header</em></strong> do seu HTML.</p>
<pre class="prettyprint">&lt;link href="https://fonts.googleapis.com/css?family=Nunito:400" rel="stylesheet"&gt;</pre>
<h2>Trabalhando com o CSS</h2>
<p>Neste momento precisamos pensar em instâncias. O Neon pode estar ligado ou desligado. Por isso, precisamos pensar nos objetos das duas formas.</p>
<p>Leia os comentários no código para entender o seu funcionamento.<!--?prettify linenums=true?--></p>
<pre class="prettyprint">&lt;style&gt;
		/*
		Configuração do container
		onde ficará os Neons
		*/
		.area_neon{
			background-color: #0F0F0F;
			font-family: 'Nunito', sans-serif;
			
			left: 0;
			right: 0;
			bottom: 0;
			top: 0;
			padding: 20px;
			padding-top: 40px;
			position: absolute;
		}
		
		/*
		Base do Neon apagado (TEXTO).
		Iremos simular um efeito as lâmpadas
		de neon apagadas.
		*/
		.area_neon h1.neon{
			font-weight: 400;
			font-size: 7em;
			
			/**
			O filtro BLUR deve ser mantido em 0, porque 
			iremos usa-lo quando ligado.
			Para a animação de transição funcionar
			corretamente, ele precisa ser declarado
			mesmo desligado.
			**/
			filter: blur(0);
			
			/**
			Para simular a lâmpada, colocaremos um
			contorno bem suave, para delimitar o
			objeto, porém com o fundo
			quase transparente
			**/
			-webkit-text-stroke: 1px rgba(255,255,255,0.1);
			color: rgba(255,255,255,0.1);
			
			/**
			O TextShadow e o BackgroundClip
			irá servir para colocar um efeito de 
			profundidade no objeto
			**/
			text-shadow: -5px 5px 5px black;
  			-webkit-background-clip: text;
			
			/**
			O Transition é responsável por
			adicionar uma sensação de animação
			entre os eventos.
			**/
			transition: all ease 1s;
		}
		
		/**Texto com o Neon Ligado**/
		.area_neon h1.neon.on{
			/**
			Será fundametal o desfoque para dar
			a sensação de luminosidade.
			**/
			filter: blur(1px);
			
			/**
			Um objeto com luz precisa possuir seu 
			centro branco, caso contrário, vai dar
			a sensação de que está apenas com um
			sombreamento e não com luz.
			
			Por isso, devemos manter a cor branca,
			que vai representar o centro luminoso,
			e a borda da cor que desejamos usar.
			
			O TextShadow será a luminosidade do
			ambiente vinda da luz do Neon.
			
			O contorno e a sombra deverão ser
			da cor que você escolher para o neon,
			mas a cor do texto deverá ser sempre
			branca.
			**/
			color: white;
			-webkit-text-stroke: 1px #00FFB3;
			text-shadow: 0 0 5px #CCFFF7, 0 0 200px #00FFDB;
			-webkit-background-clip: none;
		}
		
		/**
		O neon para a imagem SVG terá que ser
		um pouco diferente, mas podemos
		manter a mesma lógica.
		**/
		.area_neon svg.neon_img{
			width: 50%;
			margin: 0 auto;
			
			/**
			Ao invés de usarmos color, usaremos 
			o parâmetro FILL para poder determinar a cor
			do objeto e o STROKE para a borda.
			
			Porém usaremos as mesmas lógicas
			usadas no Texto
			**/
			fill: rgba(255,255,255,0.1);
			stroke: rgba(255,255,255,0.1);
			
			filter: blur(0) drop-shadow(-5px 5px 5px black);
 			/**
			Usaremos o drop-shadow aplicado no filter,
			para poder ter o efeito similar ao do texto.
			**/
			
			transition: all ease 1s;
		}
		/**SVG com o neon Ligado**/
		.area_neon svg.neon_img.on{
			/**
			Aqui aplicamos a mesma lógica usada
			no texto, porém adaptada para o tipo de objeto.
			**/
			fill: white;
			stroke: #F0FF00;
			filter: blur(1px) drop-shadow(0 0 10px #F0FF00)  drop-shadow(0 0 200px #F0FF00) ;
		}
	&lt;/style&gt;</pre>
<h2>Ligando o Neon</h2>
<p>Vamos usar o Javascript puro para ligarmos a luz. Tudo o que precisamos é adicionar <strong>on</strong> ao parâmetro classe das tags HTML correspondentes.</p>
<p>Para isso vamos criar a função <em><strong>turnOn()</strong></em>:</p>
<pre class="prettyprint">&lt;script&gt;
function turnOn(){
	var texto = document.getElementById("texto_neon");
	texto.className = texto.className.concat(" on");

	var imagem = document.getElementById("img_neon");
	imagem.setAttribute("class", imagem.getAttribute("class").concat(" on"));
	//Repare que temos que usar setAttribute no SVG. Isso porque o SVG não possui o mesmo comportamento de uma tag HTML comum
}
&lt;/script&gt;</pre>
<p>Agora vamos testar?<br />
<iframe src="/css_neon/tutorial.html" border="0" style="border:0;min-height:600px;width:100%;height:auto;"></iframe><br />
<center><a href="/css_neon/tutorial.html" target="_blank">Clique aqui para ver em uma nova aba</a></center></p>
<p>Você pode pegar o Código Completo deste tutorial diretamente no GitHub.</p>
<p style="text-align: center;"><!-- Place this tag where you want the button to render. --> <a class="github-button" href="https://github.com/portillodesign/Neon-CSS-Examples/archive/master.zip" data-size="large" aria-label="Download portillodesign/Neon-CSS-Examples on GitHub">Download</a></p>
<p>Todavia, também podemos ter outros efeitos interessantes seguindo essa mesma lógica.</p>
<h2>Feliz ano novo com Contagem Regressiva</h2>
<p><iframe src="/css_neon/feliz_ano_novo.html" border="0" style="border:0;min-height:600px;width:100%;height:auto;"></iframe><br />
<center><a href="/css_neon/feliz_ano_novo.html" target="_blank">Clique aqui para ver em uma nova aba</a></center></p>
<h2>Sabre Jedi (liga/desliga) com Som</h2>
<p><iframe src="/css_neon/sabre_jedi.html" border="0" style="border:0;min-height:800px;width:100%;height:auto;"></iframe><br />
<center><a href="/css_neon/sabre_jedi.html" target="_blank">Clique aqui para ver em uma nova aba</a></center></p>
<h3>Lembrando que todos os códigos demonstrados aqui podem ser baixados pelo GitHub.</h3>
<p style="text-align: center;"><!-- Place this tag where you want the button to render. --><br />
<a class="github-button" href="https://github.com/portillodesign/Neon-CSS-Examples" data-size="large" data-show-count="true" aria-label="Star portillodesign/Neon-CSS-Examples on GitHub">Star</a></p>
<p>Deixe seu comentário e compartilhe este post. Curta a página do <a href="https://www.facebook.com/velhobit/" target="_blank">VelhoBit no Facebook</a>! e entre para o grupo <a href="https://www.facebook.com/groups/designdesenvolvimento/" target="_blank">Design e Desenvolvimento</a>. </p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Borda Branca no Contorno Preto do Illustrator &#8211; Como Resolver?</title>
		<link>https://velhobit.com.br/tutoriais/borda-branca-no-contorno-preto-do-illustrator-como-resolver.html</link>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Sat, 09 Dec 2017 16:50:06 +0000</pubDate>
				<category><![CDATA[Design]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[aditivas]]></category>
		<category><![CDATA[adobe]]></category>
		<category><![CDATA[adobe cloud]]></category>
		<category><![CDATA[cc]]></category>
		<category><![CDATA[cmyk]]></category>
		<category><![CDATA[cores]]></category>
		<category><![CDATA[creative cloud]]></category>
		<category><![CDATA[cuidados]]></category>
		<category><![CDATA[illustrator]]></category>
		<category><![CDATA[ilustração]]></category>
		<category><![CDATA[impressão]]></category>
		<category><![CDATA[impressos]]></category>
		<category><![CDATA[publicações]]></category>
		<category><![CDATA[rgb]]></category>
		<category><![CDATA[subtrativas]]></category>
		<category><![CDATA[suite]]></category>
		<guid isPermaLink="false">https://velhobit.com.br/?p=887</guid>

					<description><![CDATA[Borda branca ao redor de elementos pretos no Illustrator? Aqui você vai entender como resolver e ainda aprender um pouco mais sobre fidelidade cores.]]></description>
										<content:encoded><![CDATA[<p>Muitas pessoas, principalmente os menos experiêntes, da área de design não conseguem imaginar o mundo antes da editoração eletrônica. E, realmente, quem não acompanhou sua evolução, pode acreditar que o WYSIWYG (<em>What You See Is What You Get</em>) é algo absoluto. Mas a verdade é que há limitações técnicas que impedem que o que seja mostrado no monitor seja exatamente o que vai ser impresso.</p>
<p>Apesar dessas limitações, os softwares de ilustração e editoração tentam simular situações referentes a cores, formas e até possíveis erros. <a href="https://velhobit.com.br/design/fidelizando-as-cores-de-impressao.html" target="_blank" rel="noopener">Já falamos, inclusive, sobre cores e como manter a fidelidade</a> aqui mesmo no site. Porém, nem sempre essa simulação é perfeita, mas faz-se necessário indicar ao profissional possíveis erros. Por isso, o Illustrator pode apresentar comportamentos que podem parecer bugs, mas que na verdade são apenas alertas e devem ser interpretados como tal.</p>
<p>Um dos casos mais comuns e extremamente discutido nos sites de tecnologia é o caso de uma<em><strong> &#8220;borda branca&#8221;</strong></em> que fica ao redor de alguns elementos mais escuros ou pretos.</p>
<p><figure id="attachment_889" aria-describedby="caption-attachment-889" style="width: 773px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-889" src="https://velhobit.com.br/wp-content/uploads/2017/12/borda-branca.jpg" alt="Detalhe de Borda Esbranquiçada que fica ao redor de objetos pretos" width="773" height="439" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/borda-branca.jpg 773w, https://velhobit.com.br/wp-content/uploads/2017/12/borda-branca-400x227.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/borda-branca-768x436.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/12/borda-branca-600x341.jpg 600w" sizes="auto, (max-width: 773px) 100vw, 773px" /><figcaption id="caption-attachment-889" class="wp-caption-text">Detalhe de Borda Esbranquiçada que fica ao redor de objetos pretos</figcaption></figure></p>
<h2>Diferentes tipos de preto</h2>
<p>Primeiro precisamos reforçar: <strong>isso não é um bug</strong>. É um alerta do comportamento esperado para um determinado tipo de preto.</p>
<p>Na impressão existem diferentes tipos de preto. Os mais conhecidos são referenciados como <strong>preto simples</strong>, <strong>preto composto</strong> e <strong>preto absoluto</strong>.</p>
<p>Como já sabemos, quem trabalha com impressão costuma trabalhar no modo CMYK (ou outro modo subtrativo), onde temos a cor aplicada a partir de quantidade de pigmento no papel. <strong>O preto simples é aquele que possui apenas o pigmento preto em sua composição</strong>. Porém, o tom desse preto pode variar de acordo com a marca do pigmento, papel onde vai ser aplicado e da calibração da impressora. Todas essas variações acabam por causar uma sensação diferente de preto em cada impresso. Com o tempo, técnicas de calibração e padronizações, essa diferença tem diminuído, mas ainda existe. Nos softwares de edição, esse preto geralmente é representado por um cinza muito escuro. Apesar  disso não ser uma simulação absoluta, essa técnica é usada para que o profissional saiba onde está sendo utilizado o preto simples.</p>
<p>Por outro lado, as vezes a densidade do preto não é apropriada para o projeto, ou um erro de registro pode fazer com que fique uma borda branca ao redor do elemento. Existe várias formas para evitar erros visíveis de registro, como trapping ou, neste caso, sobreposição. Então <strong>o preto composto é uma técnica usada para diminuir erros de registro ou intensificar o tom do preto, onde é adicionado uma quantidade razoável de outros pigmentos nos elementos desejados da imagem</strong>.</p>
<p>Porém, há pessoas que exageram, aplicando o preto absoluto. <strong>O preto absoluto nada mais é do que aplicar 100% de todos os pigmentos disponíveis</strong>. Não é uma técnica recomendada, principalmente em alguns tipos de papeis, por poder causar borrões, relevo ou outros problemas que variam de acordo com a técnica de impressão usada.</p>
<p><figure id="attachment_888" aria-describedby="caption-attachment-888" style="width: 911px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-888 size-full" src="https://velhobit.com.br/wp-content/uploads/2017/12/pretos-variacoes.jpg" alt="Variações de Pretos" width="911" height="518" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/pretos-variacoes.jpg 911w, https://velhobit.com.br/wp-content/uploads/2017/12/pretos-variacoes-400x227.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/pretos-variacoes-768x437.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/12/pretos-variacoes-600x341.jpg 600w" sizes="auto, (max-width: 911px) 100vw, 911px" /><figcaption id="caption-attachment-888" class="wp-caption-text">Variações de Tipos de Pretos</figcaption></figure></p>
<h2>Como Corrigir Esse &#8220;Problema&#8221;?</h2>
<p>Isso na verdade não é um problema do Illustrator, é apenas um indicador. É a forma do Illustrator alertar o usuário que a impressão desse elemento pode causar erros de registro. Ou seja, não significa que essa borda vai aparecer, mas há boas chances de que, se ocorrer um erro na impressão, esse problema aparecerá.</p>
<p><figure id="attachment_890" aria-describedby="caption-attachment-890" style="width: 879px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="size-full wp-image-890" src="https://velhobit.com.br/wp-content/uploads/2017/12/erro-registro.jpg" alt="Erros de registro ocorrem quando, por algum motivo, as chapas de impressão não estão bem alinhadas, causando um posicionamento errado do local onde a cor foi originalmente planejada." width="879" height="540" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/erro-registro.jpg 879w, https://velhobit.com.br/wp-content/uploads/2017/12/erro-registro-400x246.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/erro-registro-768x472.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/12/erro-registro-600x369.jpg 600w" sizes="auto, (max-width: 879px) 100vw, 879px" /><figcaption id="caption-attachment-890" class="wp-caption-text">Erros de registro ocorrem quando, por algum motivo, as chapas de impressão não estão bem alinhadas, causando um posicionamento errado do local onde a cor foi originalmente planejada.</figcaption></figure></p>
<p>Primeiro vale lembrar que isso só acontece em documentos abertos no modo CMYK. Então<strong> se você não está fazendo um documento para impressão, troque para o modo RGB</strong> e você não vai ter esse problema (<em>Arquivo &gt; Modo de Cor de Documento &gt; RGB</em>).</p>
<p>Porém, a forma ideal de resolver esse problema, é você aplicar uma quantidade razoável de outros pigmentos ao preto que você está utilizando. Por exemplo, se você está usando o preto para contornar algo magenta, acrescente cerca de 20% a 50% de magenta para esse objeto, o mesmo pode ser feito para outras cores.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-891" src="https://velhobit.com.br/wp-content/uploads/2017/12/detalhe.jpg" alt="" width="956" height="409" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/detalhe.jpg 956w, https://velhobit.com.br/wp-content/uploads/2017/12/detalhe-400x171.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/detalhe-768x329.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/12/detalhe-600x257.jpg 600w" sizes="auto, (max-width: 956px) 100vw, 956px" /></p>
<p>Apesar de ser uma solução rápida para diversos casos, principalmente onde há muitas cores próximas, uma terceira possibilidade, porém não muito ideal, devido aos problemas já supracitados, é usar o preto absoluto, onde simplesmente é colocado C=100, M=100, Y=100, K=100 ao preto que deseja aplicar.</p>
<h2>Melhorando a Qualidade da Compreensão de Cores</h2>
<p>Se por um lado pode parecer incômodo esse alerta, por outro é ainda mais interessante que você busque uma visualização melhor do material que vai ser impresso.</p>
<p>Para isso, o Illustrator nos trás algumas configurações referentes a forma como o preto é demonstrado.</p>
<p>Para acessar essas configurações, vá ao meno <strong><em>Editar (ou Illustrator, no MacOS) &gt; Preferências &gt; Aparência do Preto</em></strong>. Nessa tela, você pode especificar como vai ser o comportamento do preto na impressão ou exibição. É extremamente recomendado que, se você vai trabalhar com algo que vai ser impresso, marque as opções como <em><strong>Exibir Todos os Pretos Com Precisão</strong></em>. O resultado vai ser uma emulação da diferenciação dos tipos de pretos, de acordo com a porcentagem de pigmentos que você aplicar.</p>
<p><img loading="lazy" decoding="async" class="aligncenter size-full wp-image-892" src="https://velhobit.com.br/wp-content/uploads/2017/12/preto.jpg" alt="Tipos de Pretos Compostos" width="622" height="537" srcset="https://velhobit.com.br/wp-content/uploads/2017/12/preto.jpg 622w, https://velhobit.com.br/wp-content/uploads/2017/12/preto-400x345.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/12/preto-600x518.jpg 600w" sizes="auto, (max-width: 622px) 100vw, 622px" /></p>
<p>Com tudo isso, podemos concluir que o caso da borda, queixa muito comum de usuários do Illustrator, nada mais é do que o indicador de comportamento de preto para impressão. É um caso específico do uso em modo CMYK e é bem-vindo para uma melhor qualidade do material final impresso. É interessante usar a visualização de preto composto, unido a visualização de cores de prova (<em><strong>Visualizar&gt;Cores de Prova</strong></em>), para garantir um controle mais ideal e fidelidade.</p>
<p><span style="color: #008080;"><strong>Compartilhe este post com todos da comunidade de Illustrator ou com aqueles que você imagine que vai tirar um bom proveito das informações aqui passadas.</strong></span></p>
<p><span style="color: #008080;"><strong>Obrigado pelo seu tempo.</strong></span></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>IBM Watson &#8211; Como Criar um Chatbot (com PHP e jQuery)</title>
		<link>https://velhobit.com.br/programacao/ibm-watson-como-criar-um-chatbot-com-php-e-jquery.html</link>
					<comments>https://velhobit.com.br/programacao/ibm-watson-como-criar-um-chatbot-com-php-e-jquery.html#comments</comments>
		
		<dc:creator><![CDATA[Rodrigo Portillo]]></dc:creator>
		<pubDate>Wed, 09 Aug 2017 05:59:09 +0000</pubDate>
				<category><![CDATA[Desenvolvimento]]></category>
		<category><![CDATA[Programação]]></category>
		<category><![CDATA[Tutoriais]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[back-end]]></category>
		<category><![CDATA[bluemix]]></category>
		<category><![CDATA[chat]]></category>
		<category><![CDATA[chatbot]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[design]]></category>
		<category><![CDATA[experiência do usuário]]></category>
		<category><![CDATA[front-end]]></category>
		<category><![CDATA[ibm]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[json]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[user experience]]></category>
		<category><![CDATA[UX]]></category>
		<category><![CDATA[watson]]></category>
		<guid isPermaLink="false">https://bitcolor.com.br/?p=721</guid>

					<description><![CDATA[Este tutorial mostra a base para compreensão do uso da API de conversação do IBM Watson para criação de chatbot. Desde o começo até um exemplo prático.]]></description>
										<content:encoded><![CDATA[<p>Inteligência artificial é um tema que está em discussão constante no novo milênio. O uso de chatbots tem sido cada vez mais utilizado em diversos ambientes, seja para atendimento, monitoramento, suporte ou outras aplicações diversas. <a href="https://velhobit.com.br/design/o-que-e-design.html" target="_blank" rel="noopener">Designers de Interação</a> e <a href="https://velhobit.com.br/programacao/quanto-custa-ser-programador.html" target="_blank" rel="noopener">Programadores </a>tem usado cada vez mais essas tecnologias para poder criar uma experiência melhor e mais dinâmica para o usuário.</p>
<p>Dentro da área da computação cognitiva, uma das empresas que está em muita evidência no mercado é a IBM, com sua tecnologia Watson.</p>
<p>A tecnologia Watson é uma amálgama de serviços de inteligência artificial que permite ao desenvolvedor criar plataformas de comunicação automatas com seus usuários. Para isso, a IBM disponibiliza diversas APIs de comunicação com determinados serviços. Para nosso exemplo de chatbot usaremos o serviço de Conversação do Watson.</p>
<p>Criar um chatbot com o Watson é bem mais simples do que parece. Porém, devemos deixar claro que <strong>a proposta deste tutorial é ser básico, ser um ambiente de entrada, simplificado porém funcional para o desenvolvedor ou designer interessado nesse tipo de tecnologia</strong>.</p>
<p><strong>Atenção, você precisa de um servidor que possa ser autenticado na internet. Ou seja, não adianta testar de Xampp ou Wampp, você precisa testar ao menos de uma hospedagem compartilhada.</strong></p>
<h2>Preparando o Ambiente</h2>
<p>Primeiramente você vai precisar de uma conta na Bluemix. A Bluemix é uma plataforma em nuvem de projetos da Big Blue (apelido dado a IBM pelo mercado). Para isso, basta entrar no <a href="https://www.ibm.com/br-pt/marketplace/cloud-platform" target="_blank" rel="noopener">site da empresa e clicar em Teste Gratuito 30 Dias.</a></p>
<p><a href="https://www.ibm.com/br-pt/marketplace/cloud-platform" target="_blank" rel="noopener"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-722" src="https://velhobit.com.br/wp-content/uploads/2017/08/bluemix.jpg" alt="" width="1396" height="669" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/bluemix.jpg 1396w, https://velhobit.com.br/wp-content/uploads/2017/08/bluemix-400x192.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/bluemix-768x368.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/bluemix-1024x491.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/bluemix-600x288.jpg 600w" sizes="auto, (max-width: 1396px) 100vw, 1396px" /></a></p>
<p>Depois disso, siga as instruções para você preencher os seus dados básicos.</p>
<p>Após o preenchimento de seus dados, será pedido para você criar uma organização. Por algum motivo, você não verá a opção de América do Sul referente ao local, todavia você pode continuar selecionando SUL DOS EUA que não vai impedir o funcionamento do chatbot. Simplesmente siga as demais opções até chegar ao final.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-723" src="https://velhobit.com.br/wp-content/uploads/2017/08/organização-bluemix.jpg" alt="" width="646" height="600" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/organização-bluemix.jpg 646w, https://velhobit.com.br/wp-content/uploads/2017/08/organização-bluemix-400x372.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/organização-bluemix-600x557.jpg 600w" sizes="auto, (max-width: 646px) 100vw, 646px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone wp-image-724 size-full" src="https://velhobit.com.br/wp-content/uploads/2017/08/ready-bluemix.jpg" alt="Cadastro no Bluemix" width="651" height="571" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/ready-bluemix.jpg 651w, https://velhobit.com.br/wp-content/uploads/2017/08/ready-bluemix-400x351.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/ready-bluemix-600x526.jpg 600w" sizes="auto, (max-width: 651px) 100vw, 651px" /></p>
<p>Assim que você finalizar, é possível ver uma área para criar Apps. Por hora você pode ignorar completamente isso. À primeira vista, o Bluemix parece ser um pouco difícil de navegar e encontrar algo por conta da diversidade de opções e APIs disponíveis.</p>
<p>No canto superior esquerdo você vai ver um menu hambúrguer. Clique nesse menu e selecione a opção <strong>Serviços</strong>. Lá, você vai ver a opção <strong>Watson</strong>.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-726" src="https://velhobit.com.br/wp-content/uploads/2017/08/watson-servicos.jpg" alt="" width="526" height="613" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/watson-servicos.jpg 526w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-servicos-343x400.jpg 343w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-servicos-515x600.jpg 515w" sizes="auto, (max-width: 526px) 100vw, 526px" /></p>
<p>Como nosso tutorial é sobre chatbot, devemos criar um serviço do tipo <strong>Conversação</strong>. Clique no botão <strong>Criar serviço Watson</strong> e, na página que se abrirá, selecione a opção <strong>Conversation</strong>. A configuração do serviço é bem similar ao cadastro do próprio Bluemix.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-728" src="https://velhobit.com.br/wp-content/uploads/2017/08/criar-serviço-watson.jpg" alt="" width="1259" height="646" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/criar-serviço-watson.jpg 1259w, https://velhobit.com.br/wp-content/uploads/2017/08/criar-serviço-watson-400x205.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/criar-serviço-watson-768x394.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/criar-serviço-watson-1024x525.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/criar-serviço-watson-600x308.jpg 600w" sizes="auto, (max-width: 1259px) 100vw, 1259px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-727" src="https://velhobit.com.br/wp-content/uploads/2017/08/opcoes-watson.jpg" alt="Criar serviço de conversação Watson" width="1226" height="730" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/opcoes-watson.jpg 1226w, https://velhobit.com.br/wp-content/uploads/2017/08/opcoes-watson-400x238.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/opcoes-watson-768x457.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/opcoes-watson-1024x610.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/opcoes-watson-600x357.jpg 600w" sizes="auto, (max-width: 1226px) 100vw, 1226px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-729" src="https://velhobit.com.br/wp-content/uploads/2017/08/configure-bluemix-watson.jpg" alt="Configuração Bluemix" width="883" height="418" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/configure-bluemix-watson.jpg 883w, https://velhobit.com.br/wp-content/uploads/2017/08/configure-bluemix-watson-400x189.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/configure-bluemix-watson-768x364.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/configure-bluemix-watson-600x284.jpg 600w" sizes="auto, (max-width: 883px) 100vw, 883px" /></p>
<p>Esse serviço possui versões Lite (que é gratuita), Padrão e Premium (que precisa de consulta). Na versão Lite, que estamos usando para este tutorial, você possui até 10 mil requisições por mês e não poderá salvar os logs dos chats. Porém a versão padrão não é cara, cada requisição é uma fração inferior a metade de um centavo, o que é um valor aceitável para um sistema corporativo.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-730" src="https://velhobit.com.br/wp-content/uploads/2017/08/preço-watson.jpg" alt="Preço Conversação Watson" width="818" height="565" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/preço-watson.jpg 818w, https://velhobit.com.br/wp-content/uploads/2017/08/preço-watson-400x276.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/preço-watson-768x530.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/preço-watson-600x414.jpg 600w" sizes="auto, (max-width: 818px) 100vw, 818px" /></p>
<p>Agora é necessário &#8220;ensinar&#8221; ao Watson o que você quer que ele responda. Apesar dele já possuir uma inteligência base interna, que reconhece erros e contextos, você precisa treina-lo para que ele dê as respostas corretas para determinadas perguntas.</p>
<p>Para iniciar, você precisa criar um novo <em><strong>Workspace</strong> </em>(por enquanto, pode ignorar o espaço de trabalho de exemplo).</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-731" src="https://velhobit.com.br/wp-content/uploads/2017/08/conversation-watson.jpg" alt="" width="1150" height="465" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/conversation-watson.jpg 1150w, https://velhobit.com.br/wp-content/uploads/2017/08/conversation-watson-400x162.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/conversation-watson-768x311.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/conversation-watson-1024x414.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/conversation-watson-600x243.jpg 600w" sizes="auto, (max-width: 1150px) 100vw, 1150px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-733" src="https://velhobit.com.br/wp-content/uploads/2017/08/watson-workspace.jpg" alt="" width="870" height="399" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/watson-workspace.jpg 870w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-workspace-400x183.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-workspace-768x352.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-workspace-600x275.jpg 600w" sizes="auto, (max-width: 870px) 100vw, 870px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-734" src="https://velhobit.com.br/wp-content/uploads/2017/08/workspace-watson.jpg" alt="Criar espaço de trabalho" width="1008" height="515" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/workspace-watson.jpg 1008w, https://velhobit.com.br/wp-content/uploads/2017/08/workspace-watson-400x204.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/workspace-watson-768x392.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/workspace-watson-600x307.jpg 600w" sizes="auto, (max-width: 1008px) 100vw, 1008px" /></p>
<p><strong>Atenção ao idioma do espaço de trabalho que você está criando.</strong></p>
<h3>Treinando o Watson</h3>
<p>Uma vez criado o espaço de trabalho (<em>Workspace</em>), iniciaremos o processo de treinamento do Watson. Para isso, você deve primeiro criar um <em><strong>intent</strong></em>. Um <em>intent</em> é uma intenção de comunicação, ou seja, é um conjunto de interações padronizadas que o usuário poderá fazer com o chatbot.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-735" src="https://velhobit.com.br/wp-content/uploads/2017/08/intents.jpg" alt="" width="1573" height="572" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/intents.jpg 1573w, https://velhobit.com.br/wp-content/uploads/2017/08/intents-400x145.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/intents-768x279.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/intents-1024x372.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/intents-600x218.jpg 600w" sizes="auto, (max-width: 1573px) 100vw, 1573px" /></p>
<p>Cada intenção que for criada precisa ter pelo menos <strong>5</strong> exemplos de interações para poder funcionar. A partir daí o Watson também irá entender perguntas similares. Não é necessário se preocupar com muitas variações. A tecnologia é inteligente o suficiente para trabalhar com diferenças básicas, erros de digitação e compreender contextos. Em nosso exemplo, vamos criar uma intenção com o nome de <strong>#Saudações</strong> e preencher com algumas interações básicas de saudações.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-736" src="https://velhobit.com.br/wp-content/uploads/2017/08/watson-criar-perguntas.jpg" alt="" width="1008" height="710" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/watson-criar-perguntas.jpg 1008w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-criar-perguntas-400x282.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-criar-perguntas-768x541.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-criar-perguntas-600x423.jpg 600w" sizes="auto, (max-width: 1008px) 100vw, 1008px" /></p>
<p>Uma vez criada as intenções desejadas (em nosso exemplo criamos apenas uma), você deverá criar as possíveis respostas para essas intenções e suas variações. Para isso, você deve ir na área de <strong>Dialog</strong>.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-737" src="https://velhobit.com.br/wp-content/uploads/2017/08/dialog-watson.jpg" alt="" width="995" height="495" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/dialog-watson.jpg 995w, https://velhobit.com.br/wp-content/uploads/2017/08/dialog-watson-400x199.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/dialog-watson-768x382.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/dialog-watson-600x298.jpg 600w" sizes="auto, (max-width: 995px) 100vw, 995px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-738" src="https://velhobit.com.br/wp-content/uploads/2017/08/watson-nodes.jpg" alt="" width="552" height="419" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/watson-nodes.jpg 552w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-nodes-400x304.jpg 400w" sizes="auto, (max-width: 552px) 100vw, 552px" /></p>
<p>Um diálogo (Dialog), como o nome já diz, consiste em um conjunto de interações e condições dessas interações, com uma resposta, que pode ou não resultar em um feedback para encerrar um processo de comunicação.</p>
<p>No Watson, o diálogo é organizado em um sistema de árvores, que possui uma lógica de nós e subnós. Para nosso exemplo, vamos criar um novo nó para responder a intenção de saudação que criamos anteriormente. Clique em <strong>Add node</strong>.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-739" src="https://velhobit.com.br/wp-content/uploads/2017/08/watson-resposta.jpg" alt="" width="798" height="623" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/watson-resposta.jpg 798w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-resposta-400x312.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-resposta-768x600.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-resposta-600x468.jpg 600w" sizes="auto, (max-width: 798px) 100vw, 798px" /></p>
<p>Após dar um nome ao nó, você deve colocar o que o bot irá reconhecer. A intenção é representada pelo símbolo de hash (#). Então, basicamente diz:<em> Se o bot reconhecer a intenção <strong>#Saudação</strong>, então responda com</em>:</p>
<p>Você pode colocar quantas respostas você quiser. Quanto mais respostas você colocar, maior a quantidade de diálogo possível, deixando o ambiente de comunicação mais natural e otimizando o aprendizado.</p>
<p>Como opções adicionais você pode colocar as respostas em forma sequencial ou aleatória. Ainda é possível criar condições específicas de contextos ou aguardar por respostas específicas à retóricas do chatbot.</p>
<p>Com tudo isso preenchido, você já pode testar o chatbot. O próprio ambiente do bluemix possui uma área para testes. Clique no ícone com o balãozinho no canto superior direito e experimente o diálogo que você acabou de criar.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-740" src="https://velhobit.com.br/wp-content/uploads/2017/08/watson-test.jpg" alt="" width="899" height="702" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/watson-test.jpg 899w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-test-400x312.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-test-768x600.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/watson-test-600x469.jpg 600w" sizes="auto, (max-width: 899px) 100vw, 899px" /></p>
<h2>Implementando o Back-end</h2>
<p>A API do Bluemix funciona através de comunicação cURL Essa comunicação é feita a partir de envios de informações via método POST e mediante autorização de acesso. Por isso, vamos precisar de algumas informações básicas do serviço de comunicação que criamos.</p>
<p>Caso você queira ver outros exemplos que usam cURL, acesse nosso tutorial sobre <a href="https://velhobit.com.br/programacao/carregando-dinamicamente-dados-empresa-cnpj-php-jquery.html" target="_blank" rel="noopener">preenchimento automático de formulário com o CNPJ</a> ou o tutorial sobre <a href="https://velhobit.com.br/programacao/carregando-cep-cidades-dinamicamente.html" target="_blank" rel="noopener">preenchimento automático de endereço a partir do CEP</a>.</p>
<p>Então, antes de criamos o código, você vai precisar das seguintes informações:</p>
<ul>
<li>Workspace ID</li>
<li>Username</li>
<li>Password</li>
</ul>
<p>O Workspace ID pode ser adquirido lá naquela tela de criação/seleção de ambientes de trabalho (Workspaces). Basta clicar no botão de menu, no canto superior direito do cartão referente ao workspace que criamos, em seguida clicando em <strong>View Details</strong>.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-742" src="https://velhobit.com.br/wp-content/uploads/2017/08/workspaces-1.jpg" alt="Pegar Código do Workspace no Watson" width="1234" height="619" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/workspaces-1.jpg 1234w, https://velhobit.com.br/wp-content/uploads/2017/08/workspaces-1-400x201.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/workspaces-1-768x385.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/workspaces-1-1024x514.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/workspaces-1-600x301.jpg 600w" sizes="auto, (max-width: 1234px) 100vw, 1234px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-743" src="https://velhobit.com.br/wp-content/uploads/2017/08/workspace-view-details.jpg" alt="" width="437" height="419" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/workspace-view-details.jpg 437w, https://velhobit.com.br/wp-content/uploads/2017/08/workspace-view-details-400x384.jpg 400w" sizes="auto, (max-width: 437px) 100vw, 437px" /></p>
<p>Para conseguir o login e senha do serviço de conversação, volte a tela onde você cria os serviços e vá na opção <strong>Credenciais de Serviço</strong>. Nessa área você pode visualizar ou criar novas credenciais, conseguindo assim o <em>username</em> e <em>password</em> que vamos precisar mais adiante.</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-744" src="https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-serviço.jpg" alt="" width="812" height="420" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-serviço.jpg 812w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-serviço-400x207.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-serviço-768x397.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-serviço-600x310.jpg 600w" sizes="auto, (max-width: 812px) 100vw, 812px" /></p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-746" src="https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-pagina.jpg" alt="" width="1074" height="774" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-pagina.jpg 1074w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-pagina-400x288.jpg 400w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-pagina-768x553.jpg 768w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-pagina-1024x738.jpg 1024w, https://velhobit.com.br/wp-content/uploads/2017/08/credenciais-pagina-600x432.jpg 600w" sizes="auto, (max-width: 1074px) 100vw, 1074px" /></p>
<p><span style="color: #ff0000;"><strong>ATENÇÃO<br />
A IBM mudou a forma de autenticação. Agora, ao invés de você ter acesso ao username e password, as novas conexões usarão a autenticação AIM e não mais a autenticação por username  password. Mais detalhes, veja a documentação: <a style="color: #ff0000;" href="https://console.bluemix.net/apidocs/assistant">https://console.bluemix.net/apidocs/assistant</a>.</strong></span></p>
<p>Agora vamos ao código.</p>
<p>A API REST do Watson, como dito acima, funciona a partir de comunicação cURL e vai retornar um json completo com todas as informações para a comunicação. Para criarmos uma conversa simples, precisamos definir o código. Fique atento ao que precisa ser preenchido.</p>
<h3>Exemplo usando PHP</h3>
<p><strong>conversa.php</strong></p>
<p>Como o retorno é json, precisamos definir a página como text/plain, para evitar qualquer renderização incorreta.</p>
<pre class="prettyprint">header("Content-Type: text/plain");</pre>
<p>Iremos definir então as informações que pegamos acima através das configurações do serviço de conversação. Lembre-se de substituir o código abaixo por seus dados.</p>
<pre class="prettyprint">$workspace = "d5b7e381-xxxx-xxxx-xxxx-xxxxxxxxxxxx";

$apikey = "xxxxxxxxxxxxxxxxx";

/*Antiga autenticação
$username = "cd27b34f-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
$password = "Klxxxxxxxx";
*/</pre>
<p>Precisamos agora capturar o texto que será enviado para o servidor do Watson. Para testes usaremos o $_REQUEST, do PHP. Por segurança, quando for trabalhar em modo de produção, troque para $_POST.</p>
<pre class="prettyprint">$texto = $_REQUEST["texto"];</pre>
<p>Agora é necessário definir um identificador. Para manter o contexto de conversa, e o Watson saber que está conversando ainda com a mesma pessoa, é necessário passar um identificador. Esse identificador deverá ser único por conversa. Caso você esteja implementando em um sistema de gestão, por exemplo, você pode usar o nome de usuário, id, e-mail, ou algum outro tipo de identificação única.</p>
<p>No nosso teste criaremos uma hash única md5 e a armazenaremos em uma sessão. Dessa forma, garantimos a criação temporária de um identificador único funcional. Nosso bloco então ficará:</p>
<pre class="prettyprint">if (session_status() == PHP_SESSION_NONE) {
    session_start();
}
if(isset($_SESSION["identificador"])){
	$identificador = $_SESSION["identificador"];
}else{
	$identificador = md5(uniqid(rand(), true));
	$_SESSION["identificador"] = $identificador;
}</pre>
<p>A URL da API REST deverá ser concatenada com o Workspace e o método que você está chamando. Dentro do gateway de conversação há vários métodos, desde status a tratamento de workspaces e diálogos. Através da documentação, você poderá explorar todos os métodos acessíveis para o Watson:<a href="https://www.ibm.com/watson/developercloud/conversation/api/v1/" target="_blank" rel="noopener"> https://www.ibm.com/watson/developercloud/conversation/api/v1/</a>.</p>
<p>Em nosso exemplo básico, entretanto, iremos utilizar apenas o método <em><strong>message</strong></em>. É importante lembrar que é necessário adicionar a data da versão da API como parâmetro para que possa funcionar.</p>
<pre class="prettyprint">$url = "https://gateway.watsonplatform.net/conversation/api/v1/workspaces/" . $workspace;
$urlMessage = $url . "/message?version=2017-05-26";</pre>
<p>Para enviar os dados para o Watson, precisamos criar uma pequena string json. Como em nosso exemplo só precisamos enviar o texto e o identificador, podemos simplesmente concatenar o texto, deixando-o pronto para envio.</p>
<pre class="prettyprint">$dados  = "{";
$dados .= "\"input\": ";
$dados .= "{\"text\": \"" . $texto . "\"},";
$dados .= "\"context\": {\"conversation_id\": \"" . $identificador . "\",";
$dados .= "\"system\": {\"dialog_stack\":[{\"dialog_node\":\"root\"}], \"dialog_turn_counter\": 1, \"dialog_request_counter\": 1}}";
$dados .= "}";</pre>
<p>Como estamos tratando de json, devemos especificar o cabeçalho do tipo de dados que estamos enviando.</p>
<pre class="prettyprint">$headers = array('Content-Type:application/json');</pre>
<p>Agora começa a comunicação. Para acessar a API, algumas exigências são feitas. É necessário ser enviado em método POST um json e ser uma comunicação segura, com identificação de usuário e senha. O bloco referente a comunicação ficará então:</p>
<pre class="prettyprint">$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $urlMessage);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $dados);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); Autenticação antiga
curl_setopt($ch, CURLOPT_USERPWD, "apikey:$apikey")
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
$retorno = curl_exec($ch);
curl_close($ch);</pre>
<p>Por fim, para facilitar a leitura, vamos imprimir o json na tela com uma organização mais legível para um ser-humano.</p>
<pre class="prettyprint">$retorno = json_decode($retorno);
echo json_encode($retorno, JSON_PRETTY_PRINT);</pre>
<p>Com isso já poderemos ter uma resposta json, que, ao passar o texto, retornará algo similar como na imagem abaixo:</p>
<p><img loading="lazy" decoding="async" class="alignnone size-full wp-image-749" src="https://velhobit.com.br/wp-content/uploads/2017/08/exemplo-json.jpg" alt="" width="599" height="875" srcset="https://velhobit.com.br/wp-content/uploads/2017/08/exemplo-json.jpg 599w, https://velhobit.com.br/wp-content/uploads/2017/08/exemplo-json-274x400.jpg 274w, https://velhobit.com.br/wp-content/uploads/2017/08/exemplo-json-411x600.jpg 411w" sizes="auto, (max-width: 599px) 100vw, 599px" /></p>
<p><strong>O código back-end completo fica (com comentários para ajudar a compreensão):</strong></p>
<pre class="prettyprint">&lt;?php
//Garantir que seja lido sem problemas
header("Content-Type: text/plain");

//Worskspace
$workspace = "d5b7e381-XXXX-XXXX-XXXX-XXXXXXXXXXXX";

/**
Antiga Autenticação
//Dados de Login
$username = "cd27b34f-XXXX-XXXX-XXXX-XXXXXXXXXXXX";
$password = "Kl8XXXXXXXXX";
**/
$apikey = "xxxxxxxxxxxxxxxxx";
//Capturar Texto
//Use $_POST em produção, por segurança
$texto = $_REQUEST["texto"];

//Verifica se existe identificador
//Caso não haja, crie um
if (session_status() == PHP_SESSION_NONE) {
    session_start();
}
if(isset($_SESSION["identificador"])){
	$identificador = $_SESSION["identificador"];
}else{
	//Você pode usar qualquer identificador
	//Você pode usar ID do usuário ou similar
	$identificador = md5(uniqid(rand(), true));
	$_SESSION["identificador"] = $identificador;
}

//URL da API
//(deve ser passado o método e a versão da API em GET)
$url = "https://gateway.watsonplatform.net/conversation/api/v1/workspaces/" . $workspace;
$urlMessage = $url . "/message?version=2017-05-26";

//Dados
$dados  = "{";
$dados .= "\"input\": ";
$dados .= "{\"text\": \"" . $texto . "\"},";
$dados .= "\"context\": {\"conversation_id\": \"" . $identificador . "\",";
$dados .= "\"system\": {\"dialog_stack\":[{\"dialog_node\":\"root\"}], \"dialog_turn_counter\": 1, \"dialog_request_counter\": 1}}";
$dados .= "}";

//Cabeçalho que leva tipo de Dados
$headers = array('Content-Type:application/json');

//Iniciando Comunicação cURL
$ch = curl_init();
//Selecionando URL
curl_setopt($ch, CURLOPT_URL, $urlMessage);
//O cabeçalho é importante para definir tipo de arquivo enviado
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
//Habilitar método POST
curl_setopt($ch, CURLOPT_POST, 1);
//Enviar os dados
curl_setopt($ch, CURLOPT_POSTFIELDS, $dados);
//Capturar Retorno
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
//Autenticação
//curl_setopt($ch, CURLOPT_USERPWD, "$username:$password"); Autenticação antiga
curl_setopt($ch, CURLOPT_USERPWD, "apikey:$apikey")
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
//Executar
$retorno = curl_exec($ch);
//Fechar Conexão
curl_close($ch);

//Imprimir com leitura fácil para humanos
$retorno = json_decode($retorno);
echo json_encode($retorno, JSON_PRETTY_PRINT);

?&gt;</pre>
<h2>Código do Front-End</h2>
<p>Agora precisamos fazer a interação do usuário com o chatbot. Para isso, precisamos criar uma área do chat e o formulário que enviará os dados.</p>
<pre class="prettyprint">&lt;div id="watson" class="watson"&gt;
	&lt;div class="mensagens"&gt;
		&lt;div class="area" id="chat"&gt;
		&lt;/div&gt;
	&lt;/div&gt;
	&lt;form id="mensagem" class="mensagem"&gt;
		&lt;input type="text" id="texto" name="texto" placeholder="Digite sua mensagem"/&gt;
		&lt;button type="submit"&gt;Enviar&lt;/button&gt;
	&lt;/form&gt;
&lt;/div&gt;</pre>
<p>Com a área de chat criada, está na hora de adicionarmos os scripts necessários para fazer a comunicação com o back-end. Para facilitar, usaremos o método ajax do jQuery. Atenção aos comentários no código abaixo, pois eles explicam para quê serve cada linha.</p>
<pre class="prettyprint">&lt;!--Importar jQuery. Retire caso sua página já faça a importação. --&gt;
&lt;script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"&gt;&lt;/script&gt;
&lt;script type="text/javascript"&gt;
//Submeter Formulário
$("#mensagem").submit(function(){
	//Caso o usuário envie uma mensagem vazia
	if($("#mensagem #texto").val() === ""){
		//Adiciona na área de Chat a mensagem enviada pelo usuário
		$("#chat").append("&lt;div class=\"texto usuario\"&gt;...&lt;/div&gt;");
		
		//Faz um scroll para a mensagem mais recente, caso necessário
		$(".mensagens").animate({scrollTop: $("#chat").height()});
		setTimeout(function(){
			//Adiciona uma resposta padrão afirmando que o usuário deixou o campo vazio
			$("#chat").append("&lt;div class=\"texto chatbot\"&gt;Você precisa digitar alguma coisa para prosseguir.&lt;/div&gt;");
			//Faz um scroll para a mensagem mais recente, caso necessário
			$(".mensagens").animate({scrollTop: $("#chat").height()});
		},1000);
		return false;
	}
	
	//Inicia método AJAX
	$.ajax({
		//Substitua o caminho da URL pelo que você salvou o arquivo de backend
		url: "/pasta/conversa.php?texto=" + $("#mensagem #texto").val(),
		dataType: 'json', // Determina o tipo de retorno
		beforeSend: function(){
			//Adiciona a mensagem de usuário à lista de mensagens.
			$("#chat").append("&lt;div class=\"texto usuario\"&gt;" + $("#mensagem #texto").val() + "&lt;/div&gt;");	
		},
		success: function(resposta){
			//Limpa o que o usuário digitou e foca no input para próxima interação.
			$("#mensagem #texto").val("");
			$("#mensagem #texto").focus();
			
			//Caso haja um erro, o Watson retornará a mensagem de erro ao usuário
			//Basta ler o objeto error para o usuário.
			if(resposta.error){
				$("#chat").append("&lt;div class=\"texto chatbot\"&gt;" + resposta.error + "&lt;/div&gt;");
				return false;
			}
			
			//Colocar a resposta do Watson para o usuário ler
			//A mensagem de texto pode ser lida a partir da lógica
			//do json de exemplo da imagem no post
			var mensagemChatbot  = "&lt;div class=\"texto chatbot\"&gt;";
			mensagemChatbot		+= resposta.output.text[0];
			mensagemChatbot		+= "&lt;/div&gt;";
			setTimeout(function(){
				$("#chat").append(mensagemChatbot);
				$(".mensagens").animate({scrollTop: $("#chat").height()});
			},1000);
		}
	});

	return false;
});
&lt;/script&gt;</pre>
<p>Observe que no código acima existe um método setTimeOut que ocorre sempre antes de adicionar a resposta do Watson. Isso é feito por uma decisão de experiência do usuário.</p>
<p>Uma resposta muito rápida pode causar uma confusão de interpretação e estranhamento.</p>
<p>Quando você está conversando com alguém, a tendência é, ao enviar uma mensagem, esperar que a pessoa ao menos pense na resposta e digite antes de responder. Um pequeno atraso de um segundo na resposta é um tempo mínimo esperado para dar uma maior naturalidade a conversa e ainda permitir que o usuário se prepare para receber uma mensagem. Essa é uma decisão puramente de UX. Caso queira, você pode retirar o setTimeout e irá funcionar normalmente, mas ao testar você poderá sentir que esse tempo de resposta faz falta.</p>
<p>Para finalizar, vamos colocar um estilo CSS para ficar mais agradável ao usuário.</p>
<pre class="prettyprint">&lt;style&gt;
	.watson{
		border: 1px solid #B0BEC5;
		border-radius: 3px;
		height: 50em;
		max-height: 500px;
		padding: 1em;
		
		max-width: 500px;
		margin: 0 auto;
		
		display: flex;
		flex-direction: column;
		justify-content: space-between;
	}
	
	.watson .mensagens{
		box-sizing: border-box;
		overflow: hidden;
		overflow-y: auto;
		height: 100%;
	}
	
	.watson .mensagens .area{
		display: flex;
		justify-content: flex-end;
		flex-direction: column;
		min-height: 100%;
	}
	
	.watson .mensagens .texto{
		border-radius: 2px;
		box-sizing: border-box;
		padding: .65em;
		margin-top: .5em;
		
		animation: popupmensagem linear .2s;
		animation-iteration-count: 1;
		-webkit-animation: popupmensagem linear .2s;
		-webkit-animation-iteration-count: 1;
		-moz-animation: popupmensagem linear .2s;
		-moz-animation-iteration-count: 1;
		-o-animation: popupmensagem linear .2s;
		-o-animation-iteration-count: 1;
		-ms-animation: popupmensagem linear .2s;
		-ms-animation-iteration-count: 1;
	}
	
	.watson .mensagens .texto:first-child{
		margin-top: 0;
	}
	
	.watson .mensagens .texto.usuario{
		background-color: #ECEFF1;
		color: #1A237E;
		margin-right: 30%;
		
		transform-origin: 0% 100%;
		-webkit-transform-origin: 0% 100%;
		-moz-transform-origin: 0% 100%;
		-o-transform-origin: 0% 100%;
		-ms-transform-origin: 0% 100%;
	}
	
	.watson .mensagens .texto.chatbot{
		background-color: #FF5722;
		color: white;
		font-weight: bold;
		margin-left: 30%;
		
		transform-origin: 100% 100%;
		-webkit-transform-origin: 100% 100%;
		-moz-transform-origin: 100% 100%;
		-o-transform-origin: 100% 100%;
		-ms-transform-origin: 100% 100%;
	}
	
	.watson form.mensagem{
		padding: 0;
		margin-top: 1em;
	}
	
	.watson form.mensagem input{
		border: 2px solid #476A7B;
		border-radius: 3px;
		padding: .5em .8em;
		font-size: 16px;
		display: block;
		box-sizing: border-box;
		width: 100%;
	}
	
	.watson form.mensagem input:focus{
		border: 2px solid #1A237E;
		outline: none;
	}
	
	.watson form.mensagem button{
		background-color: #3F51B5;
		border: none;
		border-radius: 3px;
		display: block;
		padding: .5em 1em;
		width: 100%;
		font-size: 16px;
		color: white;
		margin-top: .5em;
	}
	
	
	/**Animação de Mensagem**/
	
	@keyframes popupmensagem{
	  0% {
		transform:  scaleX(0.30) scaleY(0.30) ;
	  }
	  100% {
		transform:  scaleX(1.00) scaleY(1.00) ;
	  }
	}

	@-moz-keyframes popupmensagem{
	  0% {
		-moz-transform:  scaleX(0.30) scaleY(0.30) ;
	  }
	  100% {
		-moz-transform:  scaleX(1.00) scaleY(1.00) ;
	  }
	}

	@-webkit-keyframes popupmensagem {
	  0% {
		-webkit-transform:  scaleX(0.30) scaleY(0.30) ;
	  }
	  100% {
		-webkit-transform:  scaleX(1.00) scaleY(1.00) ;
	  }
	}

	@-o-keyframes popupmensagem {
	  0% {
		-o-transform:  scaleX(0.30) scaleY(0.30) ;
	  }
	  100% {
		-o-transform:  scaleX(1.00) scaleY(1.00) ;
	  }
	}

	@-ms-keyframes popupmensagem {
	  0% {
		-ms-transform:  scaleX(0.30) scaleY(0.30) ;
	  }
	  100% {
		-ms-transform:  scaleX(1.00) scaleY(1.00) ;
	  }
	}
&lt;/style&gt;
</pre>
<p>E agora? Funciona mesmo?</p>
<p>Veja o exemplo abaixo, utilizamos exatamente o mesmo código. Lembre-se que há apenas poucas interações e respostas criadas para este tutorial, então não espere ter uma conversa muito avançada com este chatbot.</p>
<p><strong>Obs. Está sendo utilizada no exemplo uma conta Lite, então é possível que quando você testar já tenha acabado o limite mensal.</strong></p>
<div id="watson" class="watson">
<div class="mensagens">
<div id="chat" class="area"></div>
</div>
<form id="mensagem" class="mensagem"><input id="texto" name="texto" type="text" placeholder="Digite sua mensagem" /><button type="submit">Enviar</button></form>
</div>
<p>Caso você deseje um pouco mais de segurança, recomendamos que você utilize um arquivo .htdocs na pasta em que está o conversa.php, com o conteúdo abaixo. Evitando, assim, acesso externo.</p>
<pre class="prettyprint">#Evitar Acesso Externo
Order Deny,Allow
Deny from all
Allow from 127.           # localhost</pre>
<h3>Faça o Download do Código no Github, se preferir:</h3>
<p><center><br />
<!-- Place this tag where you want the button to render. --><br />
<a class="github-button" href="https://github.com/velhobit/Watson-Example-PHP-Chatbot/archive/master.zip" data-icon="octicon-cloud-download" data-size="large" aria-label="Download velhobit/Watson-Example-PHP-Chatbot on GitHub">Download</a></center>Implementar um chatbot do IBM Watson é mais simples do que você pensava, não é? Mas lembre-se que esse é só um tutorial básico para demonstrar como usar a API REST. Você pode, verificar todos os métodos e parâmetros que podem ser utilizados diretamente pela <a href="https://www.ibm.com/watson/developercloud/conversation/api/v1/" target="_blank" rel="noopener">documentação</a>.</p>
<p>Caso tenha apreciado este conteúdo, dê uma passada lá na <a href="https://www.facebook.com/velhobit/" target="_blank" rel="noopener">página da VelhoBit no Facebook</a> e deixe seu like. Compartilhe este post com colegas e interessados na área de tecnologia e não deixe de conferir o restante dos artigos no blog.</p>
<p>Até o próximo tutorial.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://velhobit.com.br/programacao/ibm-watson-como-criar-um-chatbot-com-php-e-jquery.html/feed</wfw:commentRss>
			<slash:comments>12</slash:comments>
		
		
			</item>
	</channel>
</rss>
