Jcrop – Plugin jQuery para recortar uma imagem
Recortar imagens para melhor se adequarem ao layout onde desejamos exibi-las é um tarefa bastante rotineira, é normal termos uma imagem com uma parte interessante e outra parte descartável ou indesejada. Então vem sempre a calhar ter o recurso de recortar uma parte de uma imagem em nosso site/sistema para que o usuário não tenha que abrir um editor de imagem para realizar o serviço.
Para facilitar esta operação temos o plugin jQuery Jcrop . Devemos lembrar que o plugin, sendo javascript no lado do cliente, não irá propriamente recortar a imagem e gerar uma nova, isso deve ser feito através de uma linguagem no lado do cliente como PHP, Java, etc(veremos como mais a frente).
Carregando o plugin JCrop
Primeiramente baixe o plugin do Jcrop, ele irá vir com duas pastas, uma css
e outra js
, inclua os arquivos js/jquery.Jcrop.min.js
e css/jquery.Jcrop.css
junto com a biblioteca do jQuery em seu documento HTML.
<link rel="stylesheet" href="css/jquery.Jcrop.css" type="text/css" />
<script src="https://code.jquery.com/jquery-3.4.1.min.js" integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo=" crossorigin="anonymous"></script>
<script src="js/jquery.Jcrop.min.js"></script>
Com as bibliotecas carregadas adicione uma imagem com algum id
:
<img src="knight.jpg" alt="Cavaleiro montado" id="imagem">
Agora inicializamos o plugin.
$(document).ready(function() {
$('#imagem').Jcrop();
});
Ele já deve estar funcionando. No meu exemplo eu queria que a imagem a ser recortada estivesse centralizada, para isso foi necessário adicionar uma classe CSS ao elemento que o plugin cria para conter a imagem a ser recortada.
/* CSS */
.jcrop-centered{
display: inline-block;
}
// JS
$(document).ready(function() {
$('#imagem').Jcrop({
addClass: 'jcrop-centered'
});
});
Agora sim podemos ver o exemplo.
O posicionamento
Até agora foi somente visual, mas o plugin possui dois eventos que nos permite capturar as posições da janela de seleção são eles onSelect
e onChange
.
$('#jcrop_target').Jcrop({
onChange: funcao_de_tratamento,
onSelect: funcao_de_tratamento
});
O onSelect
é chamado quando a seleção é finalizada, ou seja, quando o botão do mouse é solto. O onChange
é chamado toda vez que a janela de seleção tem suas dimensões ou posição alteradas. As duas funções recebem como parâmetro um objeto coord
, contendo as dimensões da janela de seleção.
coord.x
: Coordenada X do canto superior esquerdo da janela de seleção.coord.y
: Coordenada Y do canto superior esquerdo da janela de seleção.coord.x2
: Coordenada X do canto inferior direito da janela de seleção.coord.y2
: Coordenada Y do canto inferior direito da janela de seleção.coord.w
: Largura da janela de seleção.coord.h
: Altura da janela de seleção.
Vemos agora um código de exemplo que somente exibe as dimensões em caixas de texto na tela:
$(document).ready(function() {
$('#imagem').Jcrop({
addClass: 'jcrop-centered',
onSelect: mostrar_coordenadas,
onChange: mostrar_coordenadas
});
});
function mostrar_coordenadas( coord ){
$('#x1').html( coord.x );
$('#y1').html( coord.y );
$('#x2').html( coord.x2 );
$('#y2').html( coord.y2 );
$('#w').html( coord.w );
$('#h').html( coord.h );
}
Como podemos ver na linha 4 e 5 definimos que nos eventos de onSelect
e onChange
chamaremos a função mostrar_coordenadas
definida na linha 9, recebendo como parâmetro o objeto de coordenada, na função apenas colocamos os valores das dimensões em elementos HTML para exibição.
Veja um exemplo funcionando.
Com este valores poderiamos por exemplo colocá-los em campos ocultos de formulários e enviá-los para uma script de redimensionamento no lado do servido, ou mesmo realizar este procedimento via AJAX. Mas antes de mais nada vamos fazer um pouco de “firula”.
Criando uma janela de visualização do recorte
Um recurso interessante quando estamos fazendo a seleção é podermos visualizar separadamente como a imagem irá ficar após o recorte, pois a janela de seleção pode dar um aspecto diferente a imagem e enganar.
Para fazer isso precisaremos primeiro ter a imagem original e outra que será a preview.
<div id="preview">
<img src="knight.jpg" alt="Imagem de preview do recorte">
</div>
<img src="knight.jpg" alt="Cavaleiro montado" id="imagem">
A imagem de preview é a mesma imagem com o mesmo tamanho que deverá ficar dentro de um div
, o que será feito é redimensionar ela dentro deste div
, posicionando ela dentro dele(escondendo a sobra com a propriedade overflow
) para simular o recorte.
Vamos ao CSS inicial da área de preview.
#preview{
width:150px;
height:150px;
overflow:hidden;
display:inline-block;
}
A altura(width
) e largura(height
) deverão ter a mesma proporção do recorte que queremos, e estes valores serão utilizado na parte do script js. E por falar nele.
$('#imagem').Jcrop({
onSelect: show_preview,
onChange: mostrar_coordenadas,
aspectRatio: 150/150,
});
// mostrar_coordenadas omitido
function show_preview( coords ){
rx = 150 / coords.w;
ry = 150 / coords.h;
$('#preview img').css({
width: Math.round(rx * 640) + 'px',
height: Math.round(ry * 400) + 'px',
marginLeft: '-' + Math.round(rx * coords.x ) + 'px',
marginTop: '-' + Math.round(ry * coords.y ) + 'px',
});
}
Primeiro temos que conhecer uma configuração nova do Jcropt , o aspectRatio
, ele determina a proporção da janela de recorte, se utilizarmos no nosso exemplo 150/150, teremos uma quadrado, se utilizarmos 16/9 teremos uma proporção de um retângulo. Podemos utilizar o valor já divido como 150/150 = 1 ou 16/9 = 1.777, mas acredito que seja mais claro e natural definir como divisão mesmo, onde colocamos as dimensões do nosso preview.
Nas linhas 10 e 11 calculamos a razão que utilizaremos para redimensionar, como podemos fazer uma seleção maior que nosso preview teremos que diminuir a imagem para se ajustar corretamente nela, se fizermos uma seleção menor devemos aumentar a imagem. Para isso dividimos a largura/altura(width/height) da nossa área de preview pela largura/altura(coords.w
/coords.h
) da área de seleção obtendo assim a razão.
Com a razão em mãos podemos redimensionar a imagem, então selecionamos a imagem com um seletor jQuery na linha 13 e alterar as dimensões utilizando a função css()
. Para a largura(linha 14) multiplicamos o valor de razão previamente calculado(rx
) pela largura original da imagem a ser recortada, nosso caso 640, não esquecendo que este valor deve ser arrendondado(com a função Math.round()
), pois não existe meio pixel, ah, também não se esqueça de concatenar o ‘px
‘ para formar o valor correto da propriedade. Na linha 15 fazemos o mesmo só agora para a altura.
Nas linhas 16 e 17 vamos calcular o quanto devemos retirar de margem da imagem de preview para que o ponto superior esquerdo dela coincida com o ponto superior esquerdo da janela de seleção. Para isso calculamos a distância proporcional multiplicando o valor das coordenadas coords.x
e coords.y
pela razão calculada, com isso sabemos o quanto devemos mover para a esquerda e para cima a imagem dentro do div
de preview, para isso adicionamos uma margin
negativa nestas direções.
Veja um exemplo funcionando.
Recortando a imagem com PHP
Como falamos mais acima, o plugin somente nos ajuda a encontrar as dimensões de recorte, para efetivamente recortar a imagem iremos utilizar um script do lado do servido, no caso PHP. No nosso exemplo vamos colocar todas as coordenadas dentro de um formulário e enviar para o o nosso script realizar o recorte.
<div id="preview">
<img src="knight.jpg" alt="Imagem de preview do recorte">
</div>
<img src="knight.jpg" alt="Cavaleiro montado" id="imagem">
<form method="POST" action="exibir.php">
<input type="hidden" name="input_x1" id="input_x1">
<input type="hidden" name="input_y1" id="input_y1">
<input type="hidden" name="input_x2" id="input_x2">
<input type="hidden" name="input_y2" id="input_y2">
<input type="hidden" name="input_w" id="input_w">
<input type="hidden" name="input_h" id="input_h">
<input type="submit" value="recortar" class="btn btn-primary">
</form>
O código acima é bastante simples, inclusive no nosso exemplo não precisaria dos pontos x2 e y2, mas vamos mandar assim mesmo. Vamos ao código PHP.
header('content-type: image/jpg');
$x1 = $_POST['input_x1'];
$y1 = $_POST['input_y1'];
$x2 = $_POST['input_x2'];
$y2 = $_POST['input_y2'];
$w = $_POST['input_w'];
$h = $_POST['input_h'];
$img = imagecreatefromjpeg('knight.jpg');
$novaImage = imagecreatetruecolor($w,$h);
imagecopyresampled($novaImage, $img, 0, 0, $x1, $y1, $w, $h , $w, $h);
imagejpeg($novaImage);
Na linha 1 mudamos o content-type
de retorno do nosso arquivo para image/jpg
, já que é este o tipo de imagem que iremos retornar. Da linha 3 até a linha 8 colocamos os dados que vieram do formulário em variáveis mais fáceis de lidar.
Na linha 10 carregamos a imagem que iremos redimensionar. Na linha 11 criamos uma nova imagem em branco através da da função imagecreatetruecolor
com as dimensões da área de seleção do Jcrop que recebemos via formulário.
Na linha 13 é que realmente recortamos a imagem através da função imagecopyresampled
que copia uma parte de uma imagem para outra, no nosso caso uma parte da original para a nova que criamos, que será a imagem recortada. Vejamos um pouco melhor esta função.
imagecopyresampled ( $dst_image , $src_image , $dst_x , $dst_y , $src_x , $src_y , $dst_w , $dst_h , $src_w , $src_h )
$dst_image
: imagem destino.$src_image
: imagem origem.$dst_x
: coordenada X da imagem de destino(ponto superior esquerdo).$dst_y
: coordenada Y da imagem de destino(ponto superior esquerdo).$src_x
: coordenada X da imagem de origem(ponto superior esquerdo).$src_y
: coordenada Y da imagem de destino(ponto superior esquerdo).$dst_w
: largura do destino.$dst_h
: altura do destino.$src_w
: largura da origem.$src_h
: altura da origem.
Como estes parâmetros são muitos podem ser um pouco confusos talvez a imagem abaixo deixe um pouco mais claro.
E para finalizar é só exibir a imagem redimensionada através do função imagejpeg($novaImage);
que retorna para o cliente o binário da imagem. Lembrando que esta função também aceita como segundo parâmetro um caminho para salvar a imagem em vez de retorná-la.
Veja um exemplo parecido.
Para quem quiser pode baixar um exemplo que permite o upload de uma imagem e salvá-la(não se esqueça da permissão de escrita na pasta uploads).
Era isso, até a próxima.