Inscrições abertas para nosso Webinar anual Adianti Framework 2024!
Clique aqui para saber mais
Componente de upload de imagens, com crop e rotação de imagem Componente de upload de imagens, com cropp e rotação de imagem. Bom dia a todos, no desenvolvimento de um novo projeto, me deparei com a necessidade de realizar o upload e manipulação de imagens, e por várias vezes tentei adaptar soluções expostas nos exemplos do framework, mas precisava de mais opções de configurações, como o crop, o giro e marca dágua, etc.....
MC
Componente de upload de imagens, com crop e rotação de imagem  
Componente de upload de imagens, com cropp e rotação de imagem.

Bom dia a todos, no desenvolvimento de um novo projeto, me deparei com a necessidade de realizar o upload e manipulação de imagens, e por várias vezes tentei adaptar soluções expostas nos exemplos do framework, mas precisava de mais opções de configurações, como o crop, o giro e marca dágua, etc..., sem falar que os celulares de hoje em dia tem alta definição de imagens, e isso com o tempo poderia se tornar um problema salvar imagens "tão grandes". pesquisando na internet, efetuei a compra do plugin "Slim Image Cropper", por cerca de 17 dólares, e com a ajuda do Nataniel, experiente programador e membro da adianti, que adaptou o mesmo, venho até vocês compartilhar e tentar de alguma forma contribuir nesse meio tão importante de comunicação.

Primeiramente quero deixar claro que o plugin é pago, e comercializado pela empresa codecanyon, deixo apenas nesse artigo, o link de compra, as instruções para configuração no frame, e os fontes de demonstração de uso.


1- primeiro passo, Efetuar a compra do plugin em https://pqina.nl/slim/.

2- Após a compra e download do plugin, descompactar o conteúdo em app/lib/slim

3- Copiar o arquivo TSlim.class.php para a pasta app/lib/widget/ (em anexo )

3- Em app/templates/theme4/libraries.html adicionar a linha <link href="app/lib/slim/css/slim.min.css?appver=400" rel="stylesheet" type="text/css" media="screen"><!--componente slim-->
(observar o template de uso)

4 - Os fontes de demostração de uso está nos 3 arquivos postados abaixo, Imagem.class.php(colocar em app/model), ImagemList.class.php(colocar em app/control), ImagemForm.class.php(colocar em app/control) , ( em anexo as instruções de uso )

5 - Criar a pasta images, na raiz do projeto ( onde serão salvas as imagens )

Para demostrar o uso do plugin, no banco de dados permission.db, crie uma tabela com o nome "imagem" com o campo chamado nome, que armazenará o caminho da imagem após o upload.

CREATE TABLE imagem ( id INTEGER PRIMARY KEY NOT NULL, nome varchar(100));



Abaixo a classe adaptada pelo Nataniel para o frame , que deverá ser copiada para app/lib/widget/


  1. <?php
  2. class TSlim extends TField implements AdiantiWidgetInterface
  3. {
  4.     protected $value;
  5.     public $container;
  6.     public function __construct($name)
  7.     {
  8.         parent::__construct($name);
  9.         //$this->id = 'slim_' . uniqid();        
  10.         $this->tag->type 'file';        
  11.         $this->container = new TElement('div');
  12.         $this->container->class 'slim';        
  13.         $this->setDataProperties(['size'=>'640,640','label'=>'Upload imagem','button-confirm-label'=>'Confirmar',
  14.                                   'button-confirm-title'=>'Confirmar','button-cancel-label'=>'Cancelar',
  15.                                   'button-cancel-title'=>'Cancelar','button-edit-label'=>'Editar',
  16.                                   'button-edit-title'=>'Editar','button-remove-label'=>'Remover',
  17.                                   'button-remove-title'=>'Remover','button-rotate-label'=>'Girar',
  18.                                   'button-rotate-title'=>'Girar']);
  19.     }
  20.     
  21.     
  22.     public function setDataProperties($props)
  23.     {
  24.         foreach ($props as $prop => $val)
  25.         {
  26.             $this->container->{"data-{$prop}"} = $val;
  27.         }
  28.     }
  29.     
  30.     public function show()
  31.     {
  32.         $this->container->add($this->tag);
  33.         
  34.         if ($this->value)
  35.             $this->container->add(new TImage($this->value));        
  36.         $js TScript::create('',false);
  37.         $js->src 'app/lib/slim/js/slim.kickstart.min.js';
  38.         $this->container->add($js);        
  39.         $this->container->show();
  40.     }
  41. }
  42. ?>


Abaixo a classe de modelo, que deverá ser salva em app/model/

  1. <?php
  2.     class Imagem extends TRecord
  3.     {
  4.         const TABLENAME 'imagem';
  5.         const PRIMARYKEY'id';
  6.         const IDPOLICY =  'max'// {max, serial}
  7.         public function __construct($id NULL$callObjectLoad TRUE)
  8.         {
  9.             parent::__construct($id$callObjectLoad);
  10.             parent::addAttribute('nome');
  11.         }
  12. }?>



Abaixo a classe ImagemForm, que deverá ser salva na pasta app/control/.

  1. <?php
  2. class ImagemForm extends TPage
  3. {
  4.     protected $form// form
  5.     public function __construct$param )
  6.     {
  7.         parent::__construct();
  8.         
  9.         // creates the form
  10.         $this->form = new TQuickForm('form_Imagem');
  11.         $this->form->class 'tform'// change CSS class
  12.         $this->form = new BootstrapFormWrapper($this->form);
  13.         $this->form->style 'display: table;width:100%'// change style
  14.         
  15.         // define the form title
  16.         $this->form->setFormTitle('Imagem');        
  17.         // create the form fields
  18.         $id = new TEntry('id');
  19.         $nome = new TSlim('nome');
  20.         $nome->container->style 'width:100%;height:240px;border:2px solid black';//tamanho do container do plugin no form
  21.         $nome->setDataProperties(['label'=>'Upload imagem']);//aqui eu seto o nome do label
  22.         //tamanho final no máximo 1500x1500 e proporção de 4:3 na janela de visualização
  23.         $nome->setDataProperties(['size'=>'1500,1500','ratio'=>'4:3']);
  24.        
  25.         
  26.         // add the fields
  27.         $this->form->addQuickField('Id'$id,  '100%' );
  28.         $this->form->addQuickField('Nome'$nome,  '100%' );
  29.         if (!empty($id))
  30.         {
  31.             $id->setEditable(FALSE);
  32.         }        
  33.         $nome->setDataProperties(['will-transform'=>'addWatermark']);        
  34.         
  35.         //abaixo o código para inserir marca dágua
  36.         $script = new TElement('script'); 
  37.         $script->type 'text/javascript';
  38.         $javascript "
  39.         
  40.             function addWatermark(data, ready) {
  41.             // get the drawing context for the output image
  42.             var ctx = data.output.image.getContext('2d');
  43.         
  44.             // draw our watermark on the center of the image
  45.             var size = data.output.width / 40
  46.             ctx.font = size + 'px sans-serif';        
  47.             var x = data.output.width * .5;
  48.             var y = data.output.height * .9;
  49.             var text = ctx.measureText('nome: nome que você escolher');
  50.             var w = text.width * 1.15;
  51.             var h = size * 1.75;
  52.         
  53.             ctx.fillStyle = 'rgba(0,0,0,.75)';
  54.             ctx.fillRect(
  55.                 x - (w * .5),
  56.                 y - (h * .5),
  57.                 w, h
  58.             );
  59.             ctx.fillStyle = 'rgba(255,255,255,.9)';
  60.             ctx.fillText(
  61.                 'nome: nome que você escolher',
  62.                 x - (text.width * .5),
  63.                 y + (size * .35)
  64.             );
  65.         
  66.             // continue saving the data
  67.             ready(data);
  68.         
  69.             }    
  70.         ";
  71.         $script->add($javascript); 
  72.         parent::add($script);          
  73.                      
  74.         // create the form actions
  75.         $btn  $this->form->addQuickAction(_t('Save'), new TAction(array($this'onSave')), 'fa:floppy-o');
  76.         $btn->class 'btn btn-sm btn-primary';
  77.         $btn2 $this->form->addQuickAction(_t('New'),  new TAction(array($this'onClear')), 'bs:plus-sign green');
  78.         $btn3 $this->form->addQuickAction'List'  , new TAction(array('ImagemList''onClear')), 'fa:table blue' );
  79.                 
  80.         // vertical box container
  81.         $container = new TVBox;
  82.         $container->style 'width: 90%';
  83.         // $container->add(new TXMLBreadCrumb('menu.xml', __CLASS__));
  84.         $container->add(TPanelGroup::pack('Title'$this->form));
  85.         
  86.         parent::add($container);
  87.     }
  88.     public function onSave$param )
  89.     {
  90.         try
  91.         {
  92.             TTransaction::open('permission'); // open a transaction            
  93. /**         
  94.             if (empty($object->nome))
  95.             {
  96.                 throw new Exception( 'O campo IMAGEM é obrigatório');
  97.             }
  98. **/
  99.             
  100.             $this->form->validate(); // validate form data            
  101.             $object = new Imagem;  // create an empty object
  102.             $data $this->form->getData(); // get form data as array
  103.             $object->fromArray( (array) $data); // load the object with data           
  104.            
  105.             $object2 = new Imagem($data->id); //objeto criado para testar se imagem foi repetida
  106.                         
  107.             $images Slim::getImages();
  108.             
  109.             // No image found under the supplied input name
  110.             if ($images)
  111.             {            
  112.                $image $images[0];
  113.                // save output data if set
  114.                if (isset($image['output']['data']))
  115.                {
  116.                   // Save the file
  117.                   $name $image['output']['name'];
  118.         
  119.                   // We'll use the output crop data
  120.                   
  121.                   $data $image['output']['data'];   
  122.                    //salva o arquivo na pasta images/ com o nome concatenado com o tempo       
  123.                   $output Slim::saveFile($datatime().'-'.$name'images/'false);
  124.                   //var_dump( $output );
  125.                     
  126.                   if( $object2->nome !=  $output )//teste de imagem repetida
  127.                   {
  128.                      if( file_exists ($object2->nome))// se existir apaga o anterior
  129.                      {
  130.                         unlink$object2->nome ); //apaga
  131.                      }                   
  132.                   }  
  133.                   $object->nome $output['path'];//recebe o caminho para salvar
  134.                }
  135.             }
  136.             else
  137.             { 
  138.                $object2 = new Imagem($data->id); 
  139.                $object->nome =  $object2->nome;
  140.             }  
  141.             $object->store(); // save the object                      
  142.             $this->form->setData($data); // fill form data
  143.             TTransaction::close(); // close the transaction
  144.             new TMessage('info'TAdiantiCoreTranslator::translate('Record saved'), new TAction(array('ImagemList''onClear')) );
  145.         
  146.         }
  147.         catch (Exception $e// in case of exception
  148.         {
  149.             new TMessage('error'$e->getMessage()); // shows the exception error message
  150.             $this->form->setData$this->form->getData() ); // keep form data
  151.             TTransaction::rollback(); // undo all pending operations
  152.         }
  153.     }
  154.     
  155.     public function onClear$param )
  156.     {
  157.         $this->form->clear(TRUE);
  158.     }
  159.     
  160.     public function onEdit$param )
  161.     {
  162.         try
  163.         {
  164.             if (isset($param['key']))
  165.             {
  166.                 $key $param['key'];  // get the parameter $key
  167.                 TTransaction::open('permission'); // open a transaction
  168.                 $object = new Imagem($key); // instantiates the Active Record
  169.                 $this->form->setData($object); // fill the form
  170.                 TTransaction::close(); // close the transaction
  171.             }
  172.             else
  173.             {
  174.                 $this->form->clear(TRUE);
  175.             }
  176.         }
  177.         catch (Exception $e// in case of exception
  178.         {
  179.             new TMessage('error'$e->getMessage()); // shows the exception error message
  180.             TTransaction::rollback(); // undo all pending operations
  181.         }
  182.     }
  183. }       
  184. ?>



Abaixo a grid de listagem, que deverá ser salva na pasta app/control

  1. <?php
  2. class ImagemList extends TStandardList
  3. {
  4.     protected $form;     // registration form
  5.     protected $datagrid// listing
  6.     protected $pageNavigation;
  7.     protected $formgrid;
  8.     protected $deleteButton;
  9.     protected $transformCallback;
  10.     public function __construct()
  11.     {
  12.         parent::__construct();
  13.         
  14.         parent::setDatabase('permission');            // defines the database
  15.         parent::setActiveRecord('Imagem');   // defines the active record
  16.         parent::setDefaultOrder('id''asc');         // defines the default order
  17.         // parent::setCriteria($criteria) // define a standard filter
  18.         parent::addFilterField('id''like''id'); // filterField, operator, formField
  19.         parent::addFilterField('nome''like''nome'); // filterField, operator, formField
  20.         
  21.         // creates the form
  22.         $this->form = new TQuickForm('form_search_Imagem');
  23.         $this->form->class 'tform'// change CSS class
  24.         $this->form = new BootstrapFormWrapper($this->form);
  25.         $this->form->style 'display: table;width:100%'// change style
  26.         $this->form->setFormTitle('Imagem');        
  27.         // create the form fields
  28.         $id = new TEntry('id');
  29.         $nome = new TEntry('nome');
  30.         // add the fields
  31.         //$this->form->addQuickField('Id', $id,  '100%' );
  32.         $this->form->addQuickField('Nome'$nome,  '100%' );
  33.         
  34.         // keep the form filled during navigation with session data
  35.         $this->form->setDataTSession::getValue('Imagem_filter_data') );
  36.         
  37.         // add the search form actions
  38.         $btn $this->form->addQuickAction(_t('Find'), new TAction(array($this'onSearch')), 'fa:search');
  39.         $btn->class 'btn btn-sm btn-primary';
  40.         $this->form->addQuickAction(_t('New'),  new TAction(array('ImagemForm''onEdit')), 'bs:plus-sign green');
  41.         
  42.         // creates a DataGrid
  43.         $this->datagrid = new TDataGrid;
  44.         $this->datagrid = new BootstrapDatagridWrapper($this->datagrid);
  45.         $this->datagrid->style 'width: 100%';
  46.         $this->datagrid->datatable 'true';
  47.         // creates the datagrid columns
  48.         $column_id = new TDataGridColumn('id''Id''left');
  49.         $column_nome = new TDataGridColumn('nome''Nome''left');
  50.         // define the transformer method over image 
  51.         //função para mostrar a imagem no grid
  52.         $column_nome->setTransformer( function($image) { 
  53.             $imagem= new TImage($image); 
  54.             $imagem->style='width:100px';//tamanho da imagem no grid
  55.             return $imagem
  56.         });        
  57.         // add the columns to the DataGrid
  58.         $this->datagrid->addColumn($column_id);
  59.         $this->datagrid->addColumn($column_nome);
  60.         
  61.         // create EDIT action
  62.         $action_edit = new TDataGridAction(array('ImagemForm''onEdit'));
  63.         //$action_edit->setUseButton(TRUE);
  64.         //$action_edit->setButtonClass('btn btn-default');
  65.         $action_edit->setLabel(_t('Edit'));
  66.         $action_edit->setImage('fa:pencil-square-o blue fa-lg');
  67.         $action_edit->setField('id');
  68.         $this->datagrid->addAction($action_edit);        
  69.         
  70.         // create the datagrid model
  71.         $this->datagrid->createModel();
  72.         
  73.         // create the page navigation
  74.         $this->pageNavigation = new TPageNavigation;
  75.         $this->pageNavigation->setAction(new TAction(array($this'onReload')));
  76.         $this->pageNavigation->setWidth($this->datagrid->getWidth());        
  77.         // vertical box container
  78.         $container = new TVBox;
  79.         $container->style 'width: 90%';
  80.         // $container->add(new TXMLBreadCrumb('menu.xml', __CLASS__));
  81.         $container->add(TPanelGroup::pack('Imagem'$this->form));
  82.         $container->add(TPanelGroup::pack(''$this->datagrid$this->pageNavigation));
  83.         
  84.         parent::add($container);
  85.     }
  86.      public function onClear$param )
  87.     {
  88.          $this->form->clear(TRUE);
  89.     }  
  90. }
  91. ?>




No exemplo acima, utilizei o template 4

Os arquivos podem ser baixados no formato .zip no link em anexo, eles contem as classes citadas acima, e as instruções de uso;

Podem também ser visualizados nos links abaixo:

https://ibb.co/fCVNST
imagizer.imageshack.us/a/img923/3059/WHqFqZ.gif
https://i.imgur.com/ewxHm4C.gifv
https://uploaddeimagens.com.br/imagens/amostra-gif-33f5ddd4-ed6f-463a-8dfb-f79263717155

Espero de alguma forma estar contribuindo com todos que gostarem deste componente, fiquem a vontade em postarem perguntas, boa sorte a todos.


Pacotão Dominando o Adianti Framework 7
O material mais completo de treinamento do Framework.
Curso em vídeo aulas + Livro completo + Códigos fontes do projeto ERPHouse.
Conteúdo Atualizado! Versão 7.4


Dominando o Adianti 7 Quero me inscrever agora!

Comentários (7)


MC

Para quem quiser testar o componente, segue o link:

miullerfc.acessotemporario.net/index.php?class=ImagemList&method
DS

parabéns !!!

LJ

Muito Legal, vou experimentar !!!
MZ

Boa noite.
Estou tentando usar este componente porem algumas duvidas surgem. 1 Tem como forçar o redimensionamento da imagem no tamanho que preciso?
2 O mesmo também esta a gerar um erro.

Fatal error: Uncaught Error: Class 'Slim' not found in C:wamp64wwwRealEstate2admappcontrolCorretoresForm.class.php on line 102
( ! ) Error: Class 'Slim' not found in C:wamp64wwwRealEstate2admappcontrolCorretoresForm.class.php on line 102

Não sei porque raios ele faz isso.
a linha 102 do código se refere há $images = Slim::getImages(); como tem no exemplo original
Segue código completo abaixo.
  1. <?php
  2. /**
  3.  * CorretoresForm Registration
  4.  * @author  <your name here>
  5.  */
  6. class CorretoresForm extends TPage
  7. {
  8.     protected $form// form
  9.     
  10.     use Adianti\Base\AdiantiStandardFormTrait// Standard form methods
  11.     
  12.     /**
  13.      * Class constructor
  14.      * Creates the page and the registration form
  15.      */
  16.     function __construct()
  17.     {
  18.         parent::__construct();
  19.         
  20.         $this->setDatabase('RealState2');              // defines the database
  21.         $this->setActiveRecord('Corretores');     // defines the active record
  22.         
  23.         // creates the form
  24.         $this->form = new BootstrapFormBuilder('form_Corretores');
  25.         $this->form->setFormTitle('Corretores');
  26.         
  27.         // create the form fields
  28.         $ID = new TEntry('ID');
  29.         $Foto_Corretor = new TSlim('Foto_Corretor');
  30.         $Foto_Corretor->container->style 'width:100%;height:440px;border:2px solid black';//tamanho do container do plugin no form
  31.         $Foto_Corretor->setDataProperties(['label'=>'Upload imagem']);//aqui eu seto o nome do label
  32.         //tamanho final no máximo 1500x1500 e proporção de 4:3 na janela de visualização
  33.         $Foto_Corretor->setDataProperties(['size'=>'190,190','ratio'=>'4:3']);
  34.         $Nome_Corretor = new TEntry('Nome_Corretor');
  35.         $Descricao = new TText('Descricao');
  36.         $email = new TEntry('email');
  37.         $Telefone = new TEntry('Telefone');
  38.         // add the fields
  39.         $this->form->addFields( [ new TLabel('Id') ], [ $ID ] );
  40.         $this->form->addFields( [ new TLabel('Foto Corretor') ], [ $Foto_Corretor ] );
  41.         $this->form->addFields( [ new TLabel('Nome Corretor') ], [ $Nome_Corretor ] );
  42.         $this->form->addFields( [ new TLabel('Descricao') ], [ $Descricao ] );
  43.         $this->form->addFields( [ new TLabel('Email') ], [ $email ] );
  44.         $this->form->addFields( [ new TLabel('Telefone') ], [ $Telefone ] );
  45.         // set sizes
  46.         $ID->setSize('100%');
  47.         $Foto_Corretor->setSize('100%');
  48.         $Nome_Corretor->setSize('100%');
  49.         $Descricao->setSize('100%');
  50.         $email->setSize('100%');
  51.         $Telefone->setSize('100%');
  52.         
  53.         if (!empty($ID))
  54.         {
  55.             $ID->setEditable(FALSE);
  56.         }
  57.         
  58.         /** samples
  59.          $fieldX->addValidation( 'Field X', new TRequiredValidator ); // add validation
  60.          $fieldX->setSize( '100%' ); // set size
  61.          **/
  62.          
  63.         // create the form actions
  64.         $btn $this->form->addAction(_t('Save'), new TAction([$this'onSave']), 'fa:floppy-o');
  65.         $btn->class 'btn btn-sm btn-primary';
  66.         $this->form->addAction(_t('New'),  new TAction([$this'onEdit']), 'fa:eraser red');
  67.         
  68.         // vertical box container
  69.         $container = new TVBox;
  70.         $container->style 'width: 90%';
  71.         // $container->add(new TXMLBreadCrumb('menu.xml', __CLASS__));
  72.         $container->add($this->form);
  73.         
  74.         parent::add($container);
  75.     }
  76.         public function onSave$param )
  77.     {
  78.         try
  79.         {
  80.             TTransaction::open('RealState2'); // open a transaction            
  81. /**         
  82.             if (empty($object->nome))
  83.             {
  84.                 throw new Exception( 'O campo IMAGEM é obrigatório');
  85.             }
  86. **/
  87.             
  88.             $this->form->validate(); // validate form data            
  89.             $object = new Corretores;  // create an empty object
  90.             $data $this->form->getData(); // get form data as array
  91.             $object->fromArray( (array) $data); // load the object with data           
  92.                  
  93.                         
  94.             $images Slim::getImages();
  95.             
  96.             // No image found under the supplied input name
  97.             if ($images)
  98.             {            
  99.                $image $images[0];
  100.                // save output data if set
  101.                if (isset($image['output']['data']))
  102.                {
  103.                   // Save the file
  104.                   $name $image['output']['name'];
  105.         
  106.                   // We'll use the output crop data
  107.                   
  108.                   $data $image['output']['data'];   
  109.                    //salva o arquivo na pasta images/ com o nome concatenado com o tempo       
  110.                   $output Slim::saveFile($datatime().'-'.$name'images/'false);
  111.                   //var_dump( $output );
  112.                     
  113.                   if( $object2->nome !=  $output )//teste de imagem repetida
  114.                   {
  115.                      if( file_exists ($object2->nome))// se existir apaga o anterior
  116.                      {
  117.                         unlink$object2->nome ); //apaga
  118.                      }                   
  119.                   }  
  120.                   $object->nome $output['path'];//recebe o caminho para salvar
  121.                }
  122.             }
  123.             else
  124.             { 
  125.                $object2 = new Imagem($data->id); 
  126.                $object->nome =  $object2->nome;
  127.             }  
  128.             $object->store(); // save the object                      
  129.             $this->form->setData($data); // fill form data
  130.             TTransaction::close(); // close the transaction
  131.             new TMessage('info'TAdiantiCoreTranslator::translate('Record saved'), new TAction(array('ImagemList''onClear')) );
  132.         
  133.         }
  134.         catch (Exception $e// in case of exception
  135.         {
  136.             new TMessage('error'$e->getMessage()); // shows the exception error message
  137.             $this->form->setData$this->form->getData() ); // keep form data
  138.             TTransaction::rollback(); // undo all pending operations
  139.         }
  140.     }
  141. }
  142. </your>
AG

Ola amigo comprei este componente slim mas estou com problemas em salvar no servidor já fiz vários teste permissão de pasta etc. Se puder me ajudar por favor com este erro: error: connection falied. Este erro ocorro quando estou tentando salvar o arquivo com slim. Obrigado Anderson
WS

Para corrigir o erro

Fatal error: Uncaught Error: Class 'Slim' not found in C:wamp64wwwRealEstate2admappcontrolCorretoresForm.class.php on line 102
( ! ) Error: Class 'Slim' not found in C:wamp64wwwRealEstate2admappcontrolCorretoresForm.class.php on line 102

Renomeie o arquivo da pasta
app\lib\slim\slim.php
para
app\lib\slim\Slim.php


O slim está com "s" minusculo.
MC

Caso alguém tenha alguma dúvida, deixe seu email de contato.