You are here

public function BlazyManager::buildDataBlazy in Blazy 8

Builds breakpoints suitable for top-level [data-blazy] wrapper attributes.

The hustle is because we need to define dimensions once, if applicable, and let all images inherit. Each breakpoint image may be cropped, or scaled without a crop. To set dimensions once requires all breakpoint images uniformly cropped. But that is not always the case.

@todo: Refine this like everything else.

Parameters

array $settings: The settings being modified.

object|mixed $item: The \Drupal\image\Plugin\Field\FieldType\ImageItem item, or array when dealing with Video Embed Field.

2 calls to BlazyManager::buildDataBlazy()
BlazyManager::isBlazy in src/BlazyManager.php
Checks for Blazy formatter such as from within a Views style plugin.
BlazyManager::setDimensionsOnce in src/BlazyManager.php
Sets dimensions once to reduce method calls, if image style contains crop.

File

src/BlazyManager.php, line 155

Class

BlazyManager
Implements a public facing blazy manager.

Namespace

Drupal\blazy

Code

public function buildDataBlazy(array &$settings, $item = NULL) {

  // Early opt-out if blazy_data has already been defined.
  // Blazy doesn't always deal with image directly.
  if (!empty($settings['blazy_data'])) {
    return;
  }
  if (empty($settings['original_width'])) {
    $settings['original_width'] = isset($item->width) ? $item->width : NULL;
    $settings['original_height'] = isset($item->height) ? $item->height : NULL;
  }
  $json = $sources = [];
  $end = end($settings['breakpoints']);
  foreach ($settings['breakpoints'] as $key => $breakpoint) {
    if (empty($breakpoint['image_style']) || empty($breakpoint['width'])) {
      continue;
    }
    if ($width = Blazy::widthFromDescriptors($breakpoint['width'])) {

      // If contains crop, sets dimension once, and let all images inherit.
      if (!empty($settings['uri']) && !empty($settings['ratio'])) {
        $dimensions['width'] = $settings['original_width'];
        $dimensions['height'] = $settings['original_height'];
        if (!empty($breakpoint['image_style']) && ($style = $this
          ->entityLoad($breakpoint['image_style']))) {
          if ($this
            ->isCrop($style)) {
            $style
              ->transformDimensions($dimensions, $settings['uri']);
            $padding = round($dimensions['height'] / $dimensions['width'] * 100, 2);
            $json['dimensions'][$width] = $padding;

            // Only set padding-bottom for the last breakpoint to avoid FOUC.
            if ($end['width'] == $breakpoint['width']) {
              $settings['padding_bottom'] = $padding;
            }
          }
        }
      }

      // If BG, provide [data-src-BREAKPOINT].
      if (!empty($settings['background'])) {
        $sources[] = [
          'width' => (int) $width,
          'src' => 'data-src-' . $key,
        ];
      }
    }
  }

  // As of Blazy v1.6.0 applied to BG only.
  if ($sources) {
    $json['breakpoints'] = $sources;
  }

  // @todo: A more efficient way not to do this in the first place.
  // ATM, this is okay as this method is run once on the top-level container.
  if (isset($json['dimensions']) && count($settings['breakpoints']) != count($json['dimensions'])) {
    unset($json['dimensions'], $settings['padding_bottom']);
  }

  // Supported modules can add blazy_data as [data-blazy] to the container.
  // This also informs individual images to not work with dimensions any more
  // if the image style contains 'crop'.
  if ($json) {
    $settings['blazy_data'] = $json;
  }

  // Identify that Blazy can be activated only by breakpoints.
  $settings['blazy'] = TRUE;
}