Как нарисовать фигуру, используя фрагмент изображения в php
Мне нужно создать изображение кадра, используя фрагмент изображения.
Например:
Пользователь загрузит фрагмент изображения с серверной части:
Теперь мне нужно создать рамку на интерфейсе в соответствии с требованиями пользователя (пользователь выберет высоту и ширину рамки, затем он выберет этот фрагмент изображения) следующим образом:
У меня нет никакого способа сделать это, я пытался сделать это с помощью css и html-холст, но безуспешно.
Может ли кто-нибудь, пожалуйста, подсказать мне, как я могу добиться этого с помощью PHP или CSS, HTML или JavaScript или любым другим способом.
Вы можете увидеть здесь рабочий пример, что на самом деле мне нужно сделать.
5 answers
Предварительная обработка изображения жизненно важна
Независимо от того, сделано ли это вами вручную или каким-то образом на лету через библиотеку GD, вам, по крайней мере, абсолютно необходимо сделать снимок, который, по вашему утверждению, вы получаете...
...и обрезайте и затяните его, чтобы сделать его таким чистым (без пробелов по краям и без вырезов/вырезов):
Тогда у вас есть изображение, с которым вы действительно можете работать.
В противном случае, ЧИСТЫЙ CSS / JAVASCRIPT
ПРИМЕЧАНИЕ: Я здесь не использую javascript. Он будет использоваться для динамической настройки размера элемента, как показано в html.
Обычно я бы использовал разумное количество :before
и ':после' псевдоэлементов, чтобы html был менее загроможден, но так как вам нужен динамический размер рамки, то нам нужно использовать ряд вложенных элементов div для установки динамических стилей для ширины и высоты, которые важны для некоторых элементов div
(некоторые из которых все равно будут псевдо-элементами). элементы, если javascript мог получить к ним доступ или если динамическое изменение размеров не требовалось).
ПРИМЕЧАНИЕ: До сих пор я тестировал это только в Chrome и Firefox. Действительно старые браузеры наверняка с треском провалятся.
/* implementation of framing */
.frameit {
/* width and height must be set dynamically by javascript see html */
position: relative;
box-sizing: border-box;
overflow: hidden;
padding: 20px; /* at least border size */
}
.frameit:before,
.frameit:after,
.frameit .sides > div,
.frameit .corner > div {
position: absolute;
background-image: url(http://i.stack.imgur.com/vAgqj.jpg);
background-size: 100% 20px; /* 100% and border size */
height: 20px; /* equal to border width of frameit div */
}
.frameit:before {
content: '';
top: 0;
left: 0;
right: 0;
}
.frameit:after {
content: '';
bottom: 0;
left: 0;
right: 0;
}
.frameit .sides {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
z-index: 1;
}
.frameit .sides > div {
/* width must be set dynamically by javascript see html */
height: 20px;
}
.frameit .sides > div:first-child {
top: 0;
left: 20px; /* border width */
transform-origin: 0 0;
transform: rotate(90deg);
}
.frameit .sides > div:last-child {
bottom: 0;
right: 20px; /* border width */
transform-origin: 100% 100%;
transform: rotate(90deg);
}
.frameit .sides ~ .corner { /* all corners */
position: absolute;
z-index: 2;
width: 29px; /* square root of ((border-width squared) x 2) round up */
height: 29px; /* match width */
overflow: hidden;
}
.frameit .TL {
top: 0;
left: 0;
transform-origin: 0 0;
transform: rotate(-45deg);
}
.frameit .TL > div {
top: inherit;
left: inherit;
transform-origin: inherit;
transform: rotate(45deg);
}
.frameit .TR {
top: 0;
right: 0;
transform-origin: 100% 0;
transform: rotate(45deg);
}
.frameit .TR > div {
top: 0;
right: 0;
transform-origin: 100% 0;
transform: rotate(-45deg);
}
.frameit .BR {
bottom: 0;
right: 0;
transform-origin: 100% 100%;
transform: rotate(-45deg);
}
.frameit .BR > div {
bottom: inherit;
right: inherit;
transform-origin: inherit;
transform: rotate(45deg);
}
.frameit .BL {
bottom: 0;
left: 0;
transform-origin: 0 100%;
transform: rotate(45deg);
}
.frameit .BL > div {
bottom: inherit;
left: inherit;
transform-origin: inherit;
transform: rotate(-45deg);
}
/* Optional shading to help define the joint */
.frameit .sides > div:first-child:before,
.frameit .sides > div:last-child:before {
content: '';
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
background-color: rgba(0,0,0,.07);
}
<div class="frameit" style="width: 200px; height: 300px;">
<!-- top and bottom and overall container
width and height assumed to be set by javacript by user
-->
<div class="sides">
<!-- left and right sides
widths of the children are equal to HEIGHT of container and are
assumed to be set by javacript by user
-->
<div style="width: 300px;"></div>
<div style="width: 300px;"></div>
</div>
<div class="TL corner"><!-- top left bevel --><div style="width: 200px;"></div></div>
<div class="TR corner"><!-- top right bevel --><div style="width: 200px;"></div></div>
<div class="BR corner"><!-- bottom right bevel --><div style="width: 200px;"></div></div>
<div class="BL corner"><!-- bottom left bevel --><div style="width: 200px;"></div></div>
</div>
Образец изображения, который вы опубликовали в своем ответе, может быть не лучшим для использования при создании кадра. Вы должны получить 2 разных изображения для горизонтальной и вертикальной сторон рамки. Скос и края также могут быть разными изображениями, которые можно расположить соответствующим образом.
.frame {
position: relative;
width: 500px;
/*width of the frame*/
}
.horizontal-side {
/*use a horizontal background that can repeat properly*/
background: url(http://i.stack.imgur.com/high1.jpg) repeat;
}
.horizontal-side {
width: 500px;
/*width of the frame*/
height: 20px;
}
.vertical-side {
/*use a vertical background that can repeat properly*/
background: url(http://i.stack.imgur.com/high1.jpg) repeat;
width: 20px;
height: 400px;
/*height of the frame*/
}
.vertical-side.right {
position: absolute;
right: 0;
top: 20px;
/*same as the horizontal side's hight*/
}
<div class="frame">
<div class="horizontal-side top">
</div>
<div class="vertical-side left">
</div>
<div class="vertical-side right">
</div>
<div class="horizontal-side bottom">
</div>
</div>
Я много пытался создать рамку, используя одно изображение с помощью php, но не нашел никакого решения в php.
С помощью двух ответов (ответ Лаки Сони и ответ Скоттса) Я создал сценарий, чтобы полностью выполнить свои требования (большое спасибо обоим).
First I have created 4 images from single image while uploading:
$file = Input::file('image');
$destinationPath = 'test/';
$filename = time() . $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$upload_success = $file->move($destinationPath, $filename);
// This will create image for upper horizontal part
$im = new imagick(public_path().'/test/'.$filename);
$im->setImageFormat( "jpg" );
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/20*20/'.$topUperName;
$im->resizeImage(20,20,Imagick::FILTER_LANCZOS,1);
$im->writeImage($img_name);
// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/20*20/'.$vrtRght;
$im->rotateimage('', '90');
$im->writeImage($img_name);
// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/20*20/'.$topUperBtm;
$im->rotateimage('', '90');
$im->writeImage($img_name);
// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/20*20/'.$vrtlft;
$im->rotateimage('', '90');
$im->writeImage($img_name);
$im->clear();
$im->destroy();
unlink(public_path() . '/' . $filename);
HTML layout:
<div class="frame">
<div class="horizontal-side top"></div>
<div class="vertical-side left"></div>
<div class="vertical-side right"></div>
<div class="horizontal-side bottom"></div>
<div class="right-top-corner corner-holder">
<img class="right-top corner" src="<?php echo url(); ?>/20*20/hr-uper-1448949720a.jpg">
</div>
<div class="right-btm-corner corner-holder">
<img class="right-btm" corner src="<?php echo url(); ?>/20*20/hr-btm-1448949720a.jpg">
</div>
<div class="left-top-corner corner-holder">
<img class="left-top corner" src="<?php echo url(); ?>/20*20/hr-uper-1448949720a.jpg">
</div>
<div class="left-btm-corner corner-holder">
<img class="left-btm corner" src="<?php echo url(); ?>/20*20/hr-btm-1448949720a.jpg">
</div>
</div>
Styling
:
.frame {
position: relative;
width: 500px; /* dynamic*/
height: 500px; /* dynamic*/
}
.horizontal-side {
width: 100%;
height: 100px; /* height of image*/
position: absolute;
}
.horizontal-side.top {
background: url('<?php echo url(); ?>/20*20/hr-uper-1448949720a.jpg') repeat !important;
}
.horizontal-side.bottom {
background: url('<?php echo url(); ?>/20*20/hr-btm-1448949720a.jpg') repeat !important;
}
.horizontal-side.top {
top: 0 !important;
}
.horizontal-side.bottom {
bottom: 0 !important;
}
.vertical-side {
width: 100px !important; /* width of image*/
height: 100% !important;
z-index: 9 !important;
position: absolute !important;
}
.vertical-side.left {
left: 0 !important;
background: url('<?php echo url(); ?>/20*20/vrt-left-1448949720a.jpg') repeat !important;
}
.vertical-side.right {
right: 0;
background: url('<?php echo url(); ?>/20*20/vrt-right-1448949720a.jpg') repeat !important;
}
.corner-holder {
position: absolute !important;
z-index: 9 !important;
}
.right-top-corner{
right: 0px !important;
}
.right-btm-corner {
bottom: 0 !important;
}
.left-top-corner{
left: 0 !important;
}
.left-btm-corner{
bottom: 0 !important;
left: 0 !important;
}
.corner {
height: 100px !important; /* corner height (size of image)*/
width: 100px !important; /* corner width (size of image)*/
}
.right-top {
clip: polygon(100% 0, 0% 100%, 0 0) !important;
-webkit-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
-moz-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
-ms-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
-o-clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
clip-path: polygon(100% 0, 0% 100%, 0 0) !important;
}
.right-btm{
clip: polygon(0 100%, 0 0, 100% 100%) !important;
-webkit-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
-moz-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
-ms-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
-o-clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
clip-path: polygon(0 100%, 0 0, 100% 100%) !important;
}
.left-top{
clip: polygon(100% 0, 0 0, 100% 100%) !important;
-webkit-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;
-moz-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;
-ms-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;
-o-clip-path: polygon(100% 0, 0 0, 100% 100%) !important;
clip-path: polygon(100% 0, 0 0, 100% 100%) !important;
}
.left-btm{
clip: polygon(100% 0, 0 100%, 100% 100%) !important;
-webkit-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;
-moz-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;
-ms-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;
-o-clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;
clip-path: polygon(100% 0, 0 100%, 100% 100%) !important;
}
Теперь я могу создать правильный кадр из любого типа изображения
<?php
header('Content-type: image/png');
$png_image = imagecreate(300, 300);
$grey = imagecolorallocate($png_image, 229, 229, 229);
$green = imagecolorallocate($png_image, 128, 204, 204);
imagefilltoborder($png_image, 0, 0, $grey, $grey);
imagefilledrectangle ($png_image, 20, 20, 80, 80, $green); // SQUARE
imagefilledrectangle ($png_image, 100, 20, 280, 80, $green); // RECTANGLE
imagefilledellipse ($png_image, 50, 150, 75, 75, $green); // CIRCLE
imagefilledellipse ($png_image, 200, 150, 150, 75, $green); // ELLIPSE
$poly_points = array(150, 200, 100, 280, 200, 280);
imagefilledpolygon ($png_image, $poly_points, 3, $green); // POLYGON
imagepng($png_image);
imagedestroy($png_image);
Попробуйте это
Фрагмент взят из: http://www.phpforkids.com/php/php-gd-library-drawing-shapes.php
Я посмотрел на ваше решение, этого достаточно. Но я заметил несколько вещей, когда я попытался увеличить высоту и ширину, это не дало соответствующего результата.
Я попытался решить эту проблему, используя изображения разных размеров.
$file = Input::file('image');
$destinationPath = 'test/';
$filename = time() . $file->getClientOriginalName();
$extension = $file->getClientOriginalExtension();
$upload_success = $file->move($destinationPath, $filename);
// This will create image for upper horizontal part
$im = new imagick(public_path().'/test/'.$filename);
$im->setImageFormat( "jpg" );
/** Here I have created 4 side images of 20*20 **/
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/20*20/'.$topUperName;
$im->resizeImage(20,20,Imagick::FILTER_LANCZOS,1);
$im->writeImage($img_name);
// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/20*20/'.$vrtRght;
$im->rotateimage('', '90');
$im->writeImage($img_name);
// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/20*20/'.$topUperBtm;
$im->rotateimage('', '90');
$im->writeImage($img_name);
// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/20*20/'.$vrtlft;
$im->rotateimage('', '90');
$im->writeImage($img_name);
$im->clear();
$im->destroy();
/** Here I have created 4 side images of 30*30 **/
// This will create image for upper horizontal part
$im2 = new imagick(public_path().'/test/'.$filename);
$im2->setImageFormat( "jpg" );
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/30*30/'.$topUperName;
$im2->resizeImage(30,30,Imagick::FILTER_LANCZOS,1);
$im2->writeImage($img_name);
// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/30*30/'.$vrtRght;
$im2->rotateimage('', '90');
$im2->writeImage($img_name);
// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/30*30/'.$topUperBtm;
$im2->rotateimage('', '90');
$im2->writeImage($img_name);
// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/30*30/'.$vrtlft;
$im2->rotateimage('', '90');
$im2->writeImage($img_name);
$im2->clear();
$im2->destroy();
/** Here I have created 4 side images of 40*40 **/
// This will create image for upper horizontal part
$im3 = new imagick(public_path().'/test/'.$filename);
$im3->setImageFormat( "jpg" );
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/40*40/'.$topUperName;
$im3->resizeImage(40,40,Imagick::FILTER_LANCZOS,1);
$im3->writeImage($img_name);
// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/40*40/'.$vrtRght;
$im3->rotateimage('', '90');
$im3->writeImage($img_name);
// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/40*40/'.$topUperBtm;
$im3->rotateimage('', '90');
$im3->writeImage($img_name);
// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/40*40/'.$vrtlft;
$im3->rotateimage('', '90');
$im3->writeImage($img_name);
$im3->clear();
$im3->destroy();
/** Here I have created 4 side images of 50*50 **/
// This will create image for upper horizontal part
$im4 = new imagick(public_path().'/test/'.$filename);
$im4->setImageFormat( "jpg" );
$topUperName = 'hr-uper-'.$filename;
$img_name = public_path().'/50*50/'.$topUperName;
$im4->resizeImage(50,50,Imagick::FILTER_LANCZOS,1);
$im4->writeImage($img_name);
// This will create image for vertical right part
$vrtRght = 'vrt-right-'.$filename;
$img_name = public_path().'/50*50/'.$vrtRght;
$im4->rotateimage('', '90');
$im4->writeImage($img_name);
// This will create image for bottom horizontal part
$topUperBtm = 'hr-btm-'.$filename;
$img_name = public_path().'/50*50/'.$topUperBtm;
$im4->rotateimage('', '90');
$im4->writeImage($img_name);
// This will create image for vertical left part
$vrtlft = 'vrt-left-'.$filename;
$img_name = public_path().'/50*50/'.$vrtlft;
$im4->rotateimage('', '90');
$im4->writeImage($img_name);
$im4->clear();
$im4->destroy();
unlink(public_path() . '/' . $filename);
Я обрезал эту часть изображения в 4 размерах, чтобы мы могли использовать эти размеры при создании рамки в другом соотношении.
For example if I am going to create a frame 1000*200, then it was breaking the css, because you were using a image of only 20*20 thick image in all sizes of frame.
Теперь вам просто нужно установить соотношение для всех размеров изображений, например:
//you will get this from your ajax call
$width = $_GET['width'];
$width = $_GET['height'];
if($width <= 200){
$frameImage = 'path-of-your-20*20-image';
}
if($width > 200 && $width <= 500){
$frameImage = 'path-of-your-30*30-image';
}
if($width > 500 && $width <= 700){
$frameImage = 'path-of-your-40*40-image';
}
if($width > 700){
$frameImage = 'path-of-your-50*50-image';
}
// you can set these variable as per your requirement. And then use this image path to create the html of your frame. If you need a big range of your frame then you can also crop and save image in more sizes while uploading.
Надеюсь, это будет полезно для вас