diff --git a/config/default/image.style.civictheme_banner_featured.yml b/config/default/image.style.civictheme_banner_featured.yml new file mode 100644 index 00000000..5c08854c --- /dev/null +++ b/config/default/image.style.civictheme_banner_featured.yml @@ -0,0 +1,23 @@ +uuid: 1ca889fe-b7a4-4fb9-922e-76e9463b280f +langcode: en +status: true +dependencies: + module: + - focal_point +name: civictheme_banner_featured +label: 'Banner Featured Image' +effects: + 00a742ba-c206-45ad-a0aa-3ec6424ab498: + uuid: 00a742ba-c206-45ad-a0aa-3ec6424ab498 + id: focal_point_scale_and_crop + weight: 1 + data: + width: 800 + height: 800 + crop_type: focal_point + de1c7da0-031e-4b2e-9dec-384198b5d6e3: + uuid: de1c7da0-031e-4b2e-9dec-384198b5d6e3 + id: image_convert + weight: 2 + data: + extension: webp diff --git a/web/themes/custom/drevops/includes/banner.inc b/web/themes/custom/drevops/includes/banner.inc index f64c02c6..a22d0fc1 100644 --- a/web/themes/custom/drevops/includes/banner.inc +++ b/web/themes/custom/drevops/includes/banner.inc @@ -10,6 +10,7 @@ declare(strict_types=1); use Drupal\civictheme\CivicthemeConstants; use Drupal\Component\Render\MarkupInterface; use Drupal\Core\Render\Markup; +use Drupal\media\MediaInterface; /** * Pre-process for Banner block. @@ -27,6 +28,8 @@ function _drevops_preprocess_block__civictheme_banner(array &$variables): void { return; } + _drevops_preprocess_block__civictheme_banner__featured_image($variables); + // Finds a banner type. $type = civictheme_get_field_value($block, 'field_c_b_banner_type', TRUE, CivicthemeConstants::BANNER_TYPE_DEFAULT); $route_match = \Drupal::routeMatch(); @@ -51,6 +54,40 @@ function _drevops_preprocess_block__civictheme_banner(array &$variables): void { } } +/** + * Apply a focal-point image style to the banner featured image. + * + * The base theme serves the original featured image file, leaving the browser + * to crop it with object-fit, which ignores the editor-defined focal point. + * Re-resolving the same media through a focal-point image style moves the crop + * server-side so the focal point is honoured. + * + * @see _civictheme_preprocess_block__civictheme_banner() + * @see _civictheme_preprocess_block__civictheme_banner__node() + */ +function _drevops_preprocess_block__civictheme_banner__featured_image(array &$variables): void { + $block = $variables['elements']['content']['#block_content'] ?? NULL; + + $route_match = \Drupal::routeMatch(); + $node = $route_match->getParameter('node_revision') ?: $route_match->getParameter('node'); + + // A per-node featured image overrides the block-level one, mirroring the base + // theme's resolution order. + $media = empty($node) ? NULL : civictheme_get_field_value($node, 'field_c_n_banner_featured_image', TRUE, build: $variables); + if (empty($media) && !empty($block)) { + $media = civictheme_get_field_value($block, 'field_c_b_featured_image', TRUE, build: $variables); + } + + if (!$media instanceof MediaInterface) { + return; + } + + $featured_image = civictheme_media_image_get_variables($media, 'civictheme_banner_featured'); + if (!empty($featured_image)) { + $variables['featured_image'] = $featured_image; + } +} + /** * Pre-process breadcrumb to fix double HTML escaping issue. *