php 使文本在图像中居中并圆角

o0lyfsai  于 2023-01-16  发布在  PHP
关注(0)|答案(1)|浏览(185)

我是一个php初学者,我找不到一个修复如何使圆角的动态图像或添加文本显示的IP在图像的中心

<?php
// Create the image
$image = imagecreatetruecolor(333, 33);

// Allocate colors for the image
$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);

// Fill the image with white
imagefill($image, 0, 0, $white);

// Calculate the center position of the image
$image_width = imagesx($image);
$image_height = imagesy($image);

// Get the client's IP address
// Use the IP Geolocation API to get the country of the IP address
// Decode the JSON response
// Get the country code and name from the response

// Get the flag image file
$flag_file = "images/flags/$country_code.png";

// Load the flag image
$flag_image = imagecreatefrompng($flag_file);

// Set the font size
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
  $font_size = 15;
} elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
  $font_size = 7;
}
$font_file = '/css/SatrevaNeue-lgJ6V.ttf';

// Add a border radius to the image
$radius = 10;

// Draw the four ellipses to the corners of the image
imagefilledellipse($image, $radius, $radius, $radius * 2, $radius * 2, $white);
imagefilledellipse($image, 333 - $radius, $radius, $radius * 2, $radius * 2, $white);
imagefilledellipse($image, $radius, 33 - $radius, $radius * 2, $radius * 2, $white);
imagefilledellipse($image, 333 - $radius, 33 - $radius, $radius * 2, $radius * 2, $white);

// Calculate the center position of the image
$text = "Your IP is $ip";
$text_box_width = imagefontwidth($font_size) * strlen($text);
$text_box_height = imagefontheight($font_size);
$x = ($image_width / 2) - ($text_box_width / 2);
$y = ($image_height / 2) - ($text_box_height / 2);

// Add the IP address to the image
imagettftext($image, $font_size, 0, $x, $y, $black, $font_file, $text);

// Calculate the position of the flag image
$flag_width = 20;
$flag_height = 20;
$flag_x = $x + $text_box_width + 10; // Add some spacing between the text and the flag image
$flag_y = ($image_height / 2) - ($flag_height / 2);

// Get the width and height of the flag image
$src_w = imagesx($flag_image);
$src_h = imagesy($flag_image);

// Resize and copy the flag image onto the canvas
imagecopyresampled($image, $flag_image, $flag_x, $flag_y, 0, 0, $flag_width, $flag_height, $src_w, $src_h);

// Set the content type header so the image is displayed properly
header('Content-Type: image/png');

// Output the image
imagepng($image);

// Free up memory
imagedestroy($image);

我尝试绘制多边形形状来切掉角imagefilledpolygon(),但这里的输出是它生成的图像:

t3psigkw

t3psigkw1#

在您提供的脚本中需要指出的几个问题:

  • 如果filter_var在两种情况下验证IP都失败,您将尝试在没有设置字体大小的情况下向图像添加文本。您应该将IP和国家逻辑移到顶部,并确保在继续生成图像之前正确设置它们。
  • 您正在计算文本的宽度和高度,而您应该计算边框文本框的宽度和高度。
  • 要在角上实现透明,您需要禁用alpha混合,并使用透明颜色填充图像
  • imagefilledellipse只是在角上添加圆圈,您将需要几个imagefilledrectangle来填充这些角之间的间隙。

文本居中

要确保文本正确垂直居中,请使用imagettfbbox方法来确定边框的大小,而不是依赖于其中的字体大小。这一点很重要,因为边框通常比字体高,这将导致更准确的垂直对齐。更改以下代码:

$text = "Your IP is $ip";
$text_box_width = imagefontwidth($font_size) * strlen($text);
$text_box_height = imagefontheight($font_size);
$x = ($image_width / 2) - ($text_box_width / 2);
$y = ($image_height / 2) - ($text_box_height / 2);

改为:

// $text = "Your IP is ".($_SERVER['REMOTE_ADDR'] ?? 'localhost');
$text = "Your IP is $ip";
$bbox = imagettfbbox($font_size, 0, $font_file, $text);
$x = ($image_width / 2) - (($bbox[2] - $bbox[0]) / 2);
$y = ($image_height / 2) - (($bbox[7] - $bbox[1]) / 2);

请注意,图像可能应该更宽,或者文本应该分成两行,因为这里生成的任何IPv6地址都太小,不容易阅读。
以上为我产生了以下结果:

圆角

圆角有点困难,首先你必须禁用alpha混合,然后用透明色填充图像:
注意:不要忘记重新启用alpha混合,否则当你想添加一些文字时,你的文字将不是很可读。

// Allocate colors
$black = imagecolorallocate($image, 0, 0, 0);
$white = imagecolorallocate($image, 255, 255, 255);
$transparency = imagecolorallocatealpha($image, 0, 0, 0, 127); // 127 indicates "completely transparent"

// Transparent Background
imagealphablending($image, false);
imagefill($image, 0, 0, $transparency);
imagesavealpha($image, true);
imagealphablending($image, true); // turn blending back on otherwise text will be ugly

// Create 4 circles in each corner, emulating our rounded corners
imagefilledellipse($image, 10, 10, 20, 20, $white);
imagefilledellipse($image, 323, 10, 20, 20, $white);
imagefilledellipse($image, 10, 23, 20, 20, $white);
imagefilledellipse($image, 323, 23, 20, 20, $white);

// Connect the circles with a couple of rectangles
imagefilledrectangle($image, 10, 0, 323, 33, $white);
imagefilledrectangle($image, 0, 10, 333, 23, $white);

// add your text etc...

如果不使用矩形填充放置在角上的圆之间的间隙,则结果将如下所示:

然而,对于矩形,它很好地福尔斯在一起,结果如下所示:

额外提示:在处理像素时,我一般喜欢避免使用偶数作为圆角的直径,因为偶数中没有完美的中心...
例如,在数字10中......中心数字是4、5和6。但是在数字11中,中心数字只是6)
我创建了这个GIF来帮助说明这里到底发生了什么:

相关问题