fede-green
10/4/2017 - 5:27 AM

Module creating a field formatter

How to create a custom formatter for fields. This example can be used as is for a hover effect as the one you can see on siili.com for cases in homepage.

the ImageOverlayFieldFormatter class goes to the src/Plugin/Field/FieldFormatter folder, the css and svg file in a folder called svg.

.overlay-image > svg {
  display: block;
  position: absolute;
  top: 50%;
  left: 50%;
  -webkit-transform: translate(-50%, -50%);
          transform: translate(-50%, -50%);
  min-width: 100%;
  height: 100%;
  width: auto;
  z-index: 0;
}
.overlay-image > svg image {
  -webkit-transition: all 0.5s ease-in-out;
    -moz-transition: all 0.5s ease-in-out;
    -o-transition: all 0.5s ease-in-out;
  transition: all 0.5s ease-in-out;
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  -webkit-filter: url(#filter-orange);
          filter: url(#filter-orange);
}
.overlay-image > svg .is-inactive {
  -webkit-filter: url(#filter-gray);
          filter: url(#filter-gray);
}
.filter-only {
  position: absolute;
  height: 0;
  width: 0;
}
overlay-image:
  css:
    theme:
      css/overlay-image.css: { preprocess: false }
/**
 * Implements hook_theme().
 */
function my_module_theme() {
  return [
    'image_overlay_formatter' => [
      'variables' => [
        'item' => NULL,
        'item_attributes' => NULL,
        'url' => NULL,
        'image_style' => NULL
      ],
      'template' => 'image-overlay-formatter',
    ],
  ];
}

/**
 * Prepares variables for image style templates.
 *
 * Default template: image-style.html.twig.
 *
 * @param array $variables
 *   An array containing info about the image.
 */
function template_preprocess_image_overlay_formatter(&$variables) {
  if ($variables['image_style']) {
    $variables['image'] = [
      '#theme' => 'image_style',
      '#style_name' => $variables['image_style'],
    ];
  }
  else {
    $variables['image'] = [
      '#theme' => 'image',
    ];
  }
  $variables['image']['#attributes'] = $variables['item_attributes'];

  $item = $variables['item'];

  // Do not output an empty 'title' attribute.
  if (Unicode::strlen($item->title) != 0) {
    $variables['image']['#title'] = $item->title;
  }

  // Use File entity's method if we have such,
  // check for FileInterface to be sure.
  if (($entity = $item->entity) && $entity instanceof \Drupal\file\FileInterface && empty($item->uri)) {
    $variables['image']['#uri'] = $entity->getFileUri();
  }
  else {
    $variables['image']['#uri'] = $item->uri;
  }

  $variables['image']['#url'] = file_create_url($variables['image']['#uri']);

  foreach (['width', 'height', 'alt'] as $key) {
    $variables['image']["#$key"] = $item->$key;
  }
  $module_handler = \Drupal::service('module_handler');
  $module_path = $module_handler->getModule('my_module')->getPath();
  $variables['image']['svg'] = include_once $module_path . '/templates/background-opacity.svg';
}
<?php

namespace Drupal\my_module\Plugin\Field\FieldFormatter;

use Drupal\image\Plugin\Field\FieldFormatter\ImageFormatter;
use Drupal\Core\Field\FieldItemListInterface;

/**
 * Plugin implementation of the 'my_module image' formatter.
 *
 * @FieldFormatter(
 *   id = "my_module_image",
 *   label = @Translation("my_module image overlay"),
 *   description = @Translation("my_module image overlay."),
 *   field_types = {
 *     "image"
 *   }
 * )
 */
class ImageOverlayFieldFormatter extends ImageFormatter {

  /**
   * {@inheritdoc}
   */
  public function viewElements(FieldItemListInterface $items, $langcode) {
    $elements = parent::viewElements($items, $langcode);
    foreach ($elements as &$element) {
      $element['#theme'] = 'image_overlay_formatter';
    }
    return $elements;
  }

}