分析 wp_get_attachment_image 如何选择不同尺寸的图片

WordPress wp_get_attachment_image 函数的尺寸选择机制剖析

大家好,今天我们深入探讨 WordPress 中一个非常常用的函数:wp_get_attachment_image。 这个函数负责生成附件(通常是图片)的 HTML <img> 标签,并可以灵活地选择不同尺寸的图片。理解其尺寸选择机制对于优化网站性能、确保图片质量以及实现响应式设计至关重要。

函数原型和参数

首先,我们来看一下 wp_get_attachment_image 函数的原型:

wp_get_attachment_image( int $attachment_id, string|array $size = 'thumbnail', bool $icon = false, string|array $attr = '' ): string|false

各个参数的含义如下:

  • $attachment_id (int, required): 附件的 ID。这是必填参数,指定要获取图像的附件。
  • $size (string|array, optional): 请求的图像尺寸。 默认值是 'thumbnail'。 这是我们今天讨论的重点。它可以是字符串(预定义的尺寸名称)或数组(自定义尺寸)。
  • $icon (bool, optional): 是否显示图标。 如果设置为 true,且附件是文档类型,则显示相应的图标。 默认为 false
  • $attr (string|array, optional): 附加的 HTML 属性。 可以是字符串或关联数组,用于设置 <img> 标签的属性,例如 classalttitle 等。

返回值是 HTML <img> 标签字符串,如果发生错误则返回 false

$size 参数详解

$size 参数是控制图片尺寸的关键。 WordPress 提供了多种预定义的尺寸,也允许我们自定义尺寸。

预定义尺寸

WordPress 默认提供以下预定义尺寸:

尺寸名称 描述
thumbnail 缩略图尺寸。默认情况下,缩略图尺寸是 150×150 像素,但可以在后台的“设置” -> “媒体” 中进行配置。
medium 中等尺寸。默认情况下,中等尺寸是 300×300 像素,同样可以在后台进行配置。
large 大尺寸。默认情况下,大尺寸是 1024×1024 像素,可以在后台进行配置。
full 完整尺寸。使用上传的原始图片。
medium_large 中等大尺寸。 默认情况下是 768×0 像素,通常用于响应式设计,在较小的屏幕上显示比 large 更小的图片。 注意:此尺寸在 WordPress 4.4 版本中引入。 如果在较早的版本中使用,需要手动添加。

使用预定义尺寸非常简单:

$attachment_id = 123; // 假设附件 ID 是 123
$thumbnail_image = wp_get_attachment_image( $attachment_id, 'thumbnail' );
$medium_image = wp_get_attachment_image( $attachment_id, 'medium' );
$large_image = wp_get_attachment_image( $attachment_id, 'large' );
$full_image = wp_get_attachment_image( $attachment_id, 'full' );

echo $thumbnail_image; // 输出缩略图的 HTML 标签
echo $medium_image;    // 输出中等尺寸图片的 HTML 标签
echo $large_image;     // 输出大尺寸图片的 HTML 标签
echo $full_image;      // 输出完整尺寸图片的 HTML 标签

自定义尺寸

除了预定义尺寸,我们还可以自定义尺寸。 这需要在 functions.php 文件或自定义插件中,使用 add_image_size() 函数来注册新的尺寸。

add_image_size( string $name, int $width, int $height, bool|array $crop = false )
  • $name (string, required): 尺寸名称。 这是我们将在 wp_get_attachment_image() 函数中使用的名称。
  • $width (int, required): 图片宽度。
  • $height (int, required): 图片高度。
  • $crop (bool|array, optional): 是否裁剪图片。 默认为 false。 如果设置为 true,则裁剪图片以完全符合指定的宽度和高度。 也可以是一个数组,用于指定裁剪的位置,例如 array( 'center', 'center' )

例如,我们可以添加一个名为 my_custom_size 的尺寸:

add_image_size( 'my_custom_size', 600, 400, true ); // 宽度 600 像素,高度 400 像素,裁剪

注册自定义尺寸后,就可以在 wp_get_attachment_image() 函数中使用它了:

$attachment_id = 123;
$custom_image = wp_get_attachment_image( $attachment_id, 'my_custom_size' );

echo $custom_image; // 输出自定义尺寸图片的 HTML 标签

使用数组定义尺寸

$size 参数也可以是一个数组,包含宽度和高度:

$attachment_id = 123;
$image_array = wp_get_attachment_image( $attachment_id, array( 300, 200 ) ); // 宽度 300 像素,高度 200 像素

echo $image_array; // 输出指定尺寸图片的 HTML 标签

当使用数组时,WordPress 会尝试找到最接近指定尺寸的现有图片。 如果找不到完全匹配的尺寸,它会选择大于指定尺寸的最小图片,然后缩放到指定尺寸。 注意:使用数组方式不会进行裁剪,只会进行缩放。

尺寸选择的内部逻辑

现在我们深入了解 wp_get_attachment_image 函数内部的尺寸选择逻辑。 为了简化说明,我们忽略一些边缘情况和错误处理,专注于核心的尺寸选择机制。

以下是一个简化的流程描述:

  1. 获取附件元数据: 首先,函数会通过 $attachment_id 获取附件的元数据,其中包括上传的原始图片的路径、尺寸等信息。

  2. 检查 $size 参数类型: 函数会检查 $size 参数的类型。

    • 如果是字符串: 它会被视为预定义或自定义的尺寸名称。 函数会检查该尺寸是否已注册(例如,是否通过 add_image_size() 函数添加)。
    • 如果是数组: 它会被视为宽度和高度的数组。
  3. 确定要使用的文件路径: 根据 $size 参数,函数会尝试找到最合适的图片文件。

    • 预定义或自定义尺寸: 函数会查找与指定尺寸名称关联的图片文件。 这些文件通常存储在 wp-content/uploads 目录下,并以原始文件名加上尺寸后缀命名(例如,image-150x150.jpg)。
    • 数组尺寸: 函数会遍历所有可用的图片尺寸(包括原始图片),找到最接近指定宽度和高度的图片。 这里"最接近"通常指的是大于或等于指定尺寸的最小尺寸。
    • 'full' 尺寸: 直接使用原始图片文件。
  4. 生成 HTML <img> 标签: 找到合适的图片文件后,函数会生成包含 src 属性的 HTML <img> 标签。 如果提供了 $attr 参数,还会将这些属性添加到标签中。

  5. 返回 HTML 标签: 函数返回生成的 HTML <img> 标签字符串。

以下是一个更详细的伪代码描述:

function wp_get_attachment_image( $attachment_id, $size, $icon, $attr ) {
  // 1. 获取附件元数据 (包括原始图片路径和尺寸)
  $metadata = wp_get_attachment_metadata( $attachment_id );
  $original_image_path = $metadata['file']; // 相对路径
  $original_image_url = wp_get_upload_dir()['baseurl'] . '/' . $original_image_path; // 完整 URL
  $original_width  = $metadata['width'];
  $original_height = $metadata['height'];

  // 2. 检查 $size 参数类型
  if ( is_string( $size ) ) {
    // 字符串: 预定义或自定义尺寸
    if ( $size === 'full' ) {
      // 使用原始图片
      $src = $original_image_url;
      $width  = $original_width;
      $height = $original_height;

    } else {
      // 查找指定尺寸的图片
      $resized_image = image_make_intermediate_size( $original_image_path, $size ); // 假设存在此函数,用于查找resized图片
      if ( $resized_image ) {
        $src = wp_get_upload_dir()['baseurl'] . '/' . dirname($original_image_path) . '/' . $resized_image['file'];
        $width  = $resized_image['width'];
        $height = $resized_image['height'];
      } else {
        // 如果找不到指定尺寸的图片,则使用原始图片 (Fallback)
        $src = $original_image_url;
        $width  = $original_width;
        $height = $original_height;
      }
    }

  } elseif ( is_array( $size ) && count( $size ) === 2 ) {
    // 数组: 宽度和高度
    $target_width  = (int) $size[0];
    $target_height = (int) $size[1];

    // 遍历所有可用的图片尺寸,找到最接近的尺寸
    $best_fit_image = find_best_fit_image( $metadata, $target_width, $target_height ); // 假设存在此函数

    if($best_fit_image){
      $src = wp_get_upload_dir()['baseurl'] . '/' . dirname($original_image_path) . '/' . $best_fit_image['file'];
      $width  = $best_fit_image['width'];
      $height = $best_fit_image['height'];
    } else {
      // 如果找不到合适的尺寸,则使用原始图片 (Fallback)
      $src = $original_image_url;
      $width  = $original_width;
      $height = $original_height;
    }

  } else {
    //  无效的 $size 参数,使用默认尺寸 'thumbnail' 或返回错误
    $src = wp_get_attachment_image( $attachment_id, 'thumbnail', $icon, $attr ); //递归调用,使用默认尺寸
    return $src;
  }

  // 3. 生成 HTML <img> 标签
  $attributes = array(
    'src'    => $src,
    'width'  => $width,
    'height' => $height,
  );

  // 合并 $attr 参数
  if ( is_array( $attr ) ) {
    $attributes = array_merge( $attributes, $attr );
  } elseif ( is_string( $attr ) ) {
    // 解析字符串属性 (例如: 'class="my-image" alt="My Image"')
    // 这里省略具体解析逻辑
  }

  $html = '<img';
  foreach ( $attributes as $key => $value ) {
    $html .= ' ' . esc_attr( $key ) . '="' . esc_attr( $value ) . '"';
  }
  $html .= ' />';

  // 4. 返回 HTML 标签
  return $html;
}

//  辅助函数 (假设存在)
function image_make_intermediate_size( $file, $size ) {
  //  根据 $file (原始图片路径) 和 $size (尺寸名称),查找对应的 resized 图片文件
  //  返回包含文件路径、宽度和高度的数组,如果找不到则返回 false
  //  例如: array( 'file' => 'image-150x150.jpg', 'width' => 150, 'height' => 150 )
}

function find_best_fit_image( $metadata, $target_width, $target_height ) {
  // 遍历 $metadata 中包含的所有图片尺寸信息
  // 找到大于或等于 $target_width 和 $target_height 的最小尺寸
  // 返回包含文件路径、宽度和高度的数组,如果找不到则返回 false
  // 例如: array( 'file' => 'image-600x400.jpg', 'width' => 600, 'height' => 400 )
}

关键点:

  • 如果找不到指定尺寸的图片,wp_get_attachment_image 函数通常会回退到原始图片。
  • 使用数组尺寸时,WordPress 会尝试找到最接近的现有尺寸,而不是动态生成新的尺寸(除非主题或插件有额外的处理)。
  • image_make_intermediate_sizefind_best_fit_image 是为了说明逻辑而假设存在的函数,实际代码会更复杂,并且可能涉及到 WordPress 的图像处理类(例如 WP_Image_Editor)。

优化建议

  • 合理使用预定义尺寸: WordPress 的预定义尺寸经过优化,通常能满足大部分需求。
  • 根据需求自定义尺寸: 如果预定义尺寸不满足需求,可以自定义尺寸,但要避免过度创建尺寸,以免增加存储空间和服务器负载。
  • 懒加载图片: 使用 loading="lazy" 属性或 JavaScript 库来实现图片懒加载,提高页面加载速度。
  • 使用 CDN: 将图片存储在 CDN 上,可以加速图片的访问速度。
  • 优化图片格式: 使用 WebP 等现代图片格式,可以获得更好的压缩效果和图像质量。
  • 响应式图片: 使用 <picture> 元素或 srcset 属性,根据不同的屏幕尺寸加载不同的图片,提高用户体验。

响应式图片的实现

wp_get_attachment_image 函数本身并不直接支持生成响应式图片所需的 srcsetsizes 属性,但我们可以通过一些技巧来实现。

使用 wp_get_attachment_image_srcset() 函数

WordPress 4.4 引入了 wp_get_attachment_image_srcset() 函数,专门用于生成 srcset 属性。 我们可以结合 wp_get_attachment_image() 函数和 wp_get_attachment_image_srcset() 函数来实现响应式图片。

$attachment_id = 123;
$image_size = 'medium'; // 基础尺寸

$image_src = wp_get_attachment_image_src( $attachment_id, $image_size )[0]; // 获取基础尺寸的 URL
$image_srcset = wp_get_attachment_image_srcset( $attachment_id, $image_size ); // 获取 srcset 属性

echo '<img src="' . esc_url( $image_src ) . '" srcset="' . esc_attr( $image_srcset ) . '" sizes="(max-width: 600px) 100vw, 50vw" alt="My Image" />';

在这个例子中:

  • wp_get_attachment_image_src() 函数用于获取基础尺寸的 URL。
  • wp_get_attachment_image_srcset() 函数用于生成 srcset 属性,它会根据可用的图片尺寸自动生成不同分辨率的图片列表。
  • sizes 属性用于指定在不同屏幕尺寸下使用的图片尺寸。 在这个例子中,当屏幕宽度小于 600 像素时,使用 100% 的屏幕宽度;否则,使用 50% 的屏幕宽度。

手动生成 srcset 属性

如果需要更精细的控制,可以手动生成 srcset 属性。 这需要获取所有可用的图片尺寸,并根据屏幕尺寸和像素密度生成相应的 URL 列表。

$attachment_id = 123;
$available_sizes = array( 'thumbnail', 'medium', 'large', 'full' ); // 可用的图片尺寸
$srcset = '';

foreach ( $available_sizes as $size ) {
  $image_src = wp_get_attachment_image_src( $attachment_id, $size );
  if ( $image_src ) {
    $srcset .= $image_src[0] . ' ' . $image_src[1] . 'w, '; // URL + 宽度
  }
}

$srcset = rtrim( $srcset, ', ' ); // 移除末尾的逗号和空格

echo '<img src="' . esc_url( wp_get_attachment_image_src( $attachment_id, 'medium' )[0] ) . '" srcset="' . esc_attr( $srcset ) . '" sizes="(max-width: 600px) 100vw, 50vw" alt="My Image" />';

总结:合理选择图片尺寸,优化网站性能

wp_get_attachment_image 函数是 WordPress 中处理图片的核心函数之一。 掌握其尺寸选择机制,可以帮助我们更好地控制图片的显示效果,优化网站性能,并实现响应式设计。 合理利用预定义尺寸、自定义尺寸、srcset 属性和 sizes 属性,可以为用户提供更好的视觉体验。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注