HUFERSIL.WEBDEVELOPER

Geração de imagem com JQuery/JQueryUI e PHP

Ajudando uma pessoa no fórum do iMasters, fiz um exemplo bem bacana de como gerar imagens com feedback visual de Drag-Drop.

Assim, a pessoa monta uma imagem composta por outas imagens. Bem simples porém bem divertido e fácil de fazer.

Vamos ver como fazê-lo!

Iremos criar apenas dois arquivos e duas pastas para esta tarefa. As pastas são:

  • imagens – coloque suas imagens originais aqui
  • geradas – pasta onde as imagens geradas serão salvas. Não esqueça de alterar o permissionamento para escrita.

Depois de criar as pastas, vamos criar os arquivos. Os arquivos devem estar no mesmo nível das pastas.

Arquivo de entrada e composição das imagens (index.php).

 
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Imagens</title>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
	<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.17/jquery-ui.min.js"></script>
	<script type="text/javascript">
	// quando terminar de carregar o script
	$(function(){
		// fazemos com que todas as imagens da lista possam ser arrastadas
		$('.available li img').draggable({
			helper: 'clone'
		});

		// a área do "papel" será onde os itens podem ser soltos
		$('#area-itens').droppable({
			// quando soltar um item no "papel"...
			drop: function(evt, ui){
				// se o pai do item já for o "papel"
				if(ui.draggable.parent()[0] == this){
					// nao faz nada
					return;
				}

				// referencia ao "papel", mais curta
				var t = $(this);
				// copia do elemento arrastado
				var e = ui.draggable;
				// diferenca entre a posicao do mouse e a posicao do elemento quando for solto
				var diff = {x: evt.pageX - ui.position.left, y: evt.pageY - ui.position.top};
				// tiramos o "helper" do elemento ao ser arrastado
				e.draggable('option','helper','');
				// pegamos o elemento pai do elemento arrastado (a "li")
				var parent = e.parent();
				// colocamos o elemento arrastado no papel
				e.appendTo(t);
				// removemos o elemento pai anterior do elemento arrastado (a "li")
				parent.remove();

				// calculando novo posicionamento dentro do papel
				e.css({
					position: 'absolute',
					left: evt.pageX - t.offset().left - diff.x,
					top: evt.pageY - t.offset().top - diff.y
				});
			}
		});

		// ao clicar no botao de salvar a imagem
		$('#btnSalvar').click(function(evt){
			// elemento contendo o status
			var s = $('.status'),
				// dados a serem enviados para o servidor
				data={},
				// area dos itens
				area = $('#area-itens'),
				// tamanho da pagina
				pageSize = {width:area.width(),height:area.height()},
				// elementos escolhidos pelo usuario
				itens=[];

			// para cada elemento dentro da pagina
			area.find('.itens').each(function(){
				// referencia ao elemento atual
				var t=$(this),
					// criamos um novo objeto com as propriedades desejadas
					// para geração do arquivo final
					item = {
						src: this.src,
						width: t.width(),
						height: t.height(),
						x: t.position().left,
						y: t.position().top
					};
				// colocamos na lista de itens que serão usados para compor
				// a nova imagem
				itens.push(item);
			});

			// colocamos os dados no objeto para
			// enviar para geração da imagem
			data.area = pageSize;
			data.itens = itens;

			// muda o status para aguardar
			s.html('Aguarde...');
			// envia para o PHP gerar a imagem final
			$.post('gerar.php', data, function(link){
				// quando receber a resposta, mostra o Link para baixar a imagem
				s.html('Imagem gerada: <a target="_blank" href="'+link+'">Clique aqui para baixar</a>');
			});
		});
	});

	</script>	

	<style type="text/css">
		#area-itens {
			position: relative;
			float: left;
			width: 300px;
			height: 450px;
			border: 1px solid black;
			overflow: hidden;
		}

		.available {
			float: right;
		}

		.buttons {
			clear: both;
		}

	</style>

</head>
<body>

	<p>Arraste as imagens da direita para a "área do papel" abaixo</p>

	<!--  area do "papel"  -->
	<div id="area-itens">
	</div>

	<!--  lista de elementos que servem para o usuario compor a nova imagem -->
	<ul	class="available">
		<li><img src="imagens/imagem1.jpg" class="itens" /></li>
		<li><img src="imagens/imagem2.jpg" class="itens" /></li>
		<li><img src="imagens/imagem3.jpg" class="itens" /></li>
		<li><img src="imagens/imagem4.jpg" class="itens" /></li>
	</ul>

	<div class="buttons">
		<input type="button" value="Salvar Imagem" id="btnSalvar" />
	</div>

	<div class="status"></div>

</body>
</html>

Como podemos ver, este arquivo é composto apenas de HTML, CSS e JavaScript. Simples e direto.

Agora, vamos criar o arquivo que gera as imagens compostas (gerar.php):

<?php

// mudamos o timezone para nao termos problema com datas
date_default_timezone_set('America/Sao_Paulo');

// pegamos a largura da pagina enviada via post,  ou usamos 300 como padrao
$width = empty($_POST['area']['width']) ? 300 : sprintf('%d', $_POST['area']['width']);
// pegamos a altura da pagina enviada via post,  ou usamos 450 como padrao
$height = empty($_POST['area']['height']) ? 450 : sprintf('%d', $_POST['area']['height']);

// criamos a imagem e colocamos um fundo branco
$img = imagecreatetruecolor($width, $height);
$white = imagecolorallocate($img, 255, 255, 255);
imagefilledrectangle($img, 0, 0, $width, $height, $white);

// se enviou imagens
if(!empty($_POST['itens'])){
	// para cada imagem enviada
	foreach($_POST['itens'] as $item){
		// se tem o elemento "src"
		if(!empty($item['src'])){
			// pegamos somente o nome do arquivo e ignoramos o restante
			// vamos procurar por ela dentro da pasta "imagens"
			$filename = 'imagens/' . pathinfo($item['src'], PATHINFO_BASENAME);
			//se existir
			if(file_exists($filename)){
				// pegamos o restante das informacoes enviadas
				// via post para esta imagem
				$w = sprintf('%d', $item['width']);
				$h = sprintf('%d', $item['height']);
				$x = sprintf('%d', $item['x']);
				$y = sprintf('%d', $item['y']);

				// criamos o elemento de imagem no PHP a partir do conteudo do arquivo
				$item = imagecreatefromstring(file_get_contents($filename));

				// copiamos a imagem informada na imagem final,
				// com as medidas e posições informadas
				imagecopy($img, $item, $x, $y, 0, 0, $w, $h);
			}
		}
	}
}

// geramos o arquivo final
$imageFileName = 'geradas/imagem-'.time().'.jpg';
imagejpeg($img, $imageFileName, 90);

// informamos o link
echo $imageFileName;

Como podemos ver, são dois arquivos simples e pequenos, fáceis de serem alterados para suas necessidades!

Você pode conferir um exemplo online ou baixar os arquivos do tutorial na seção de exemplos.

@braços e fiquem com Deus!

5 Responses to “Geração de imagem com JQuery/JQueryUI e PHP”

  • Fernando diz:

    Muito bom Hugo, parabéns, você respondeu uma pergunta minha no Fórum do Imasters e acabei chegando no seu site.

    Cara, uma dica, seria importante gerar a imagem dentro do

    if(!empty($_POST['itens'])){

    Pois se alguem simplesmente acessar remotamente o arquivo gera.php ele gera uma imagem em branco.

    No mais tudo certo, vai ser muito útil aqui na empresa.

    Até +

  • Valesy Moreira diz:

    Boa… Gostei do site e do post!!
    Queria saber uma coisa de você. Eu já me bati e não consegui achar algo que ma ajudasse em uma coisa. Preciso de um script que faça a seguinte coisa:
    Percorra todas as imagens de uma pasta e mostre no browser (a questão onde eu já fiz) sem ter necessidade de eu ter que setar a imagem na pagina html, ou seja, se a maneira que eu aumentar ou diminui as a quantidade de fotos, seja feito isso automaticamente.

    Espero que tenham me entendido. Aguardo reposta.

  • Samoel Bianeck diz:

    Voce é uma destas jóia raras na nossa área.
    Dá o peixe e ensina a pescar.
    Comentar mais seria extrapolar a sua sabedoria.
    Gostei do seu método e vou dar uma testada.
    Abraço Samoel

  • Luiz Bayeux diz:

    Cara muito bom esse post, parabéns!
    Tenho só uma dúvida: Como faria para tirar as imagens que soltei no papel, pois do modo que está eu não tenho como retorná-la para a lista né?
    Desde já obrigado pelo post!
    Abraço!

Deixar uma resposta

O seu endereço de email não será publicado. Campos obrigatórios marcados com *

*

Pode usar estas etiquetas HTML e atributos: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">