8

So thanks to 4k4 I finally managed to get my original image URI in a field template via

item.content['#item'].entity.uri.value

and with

{{ file_url(item.content['#item'].entity.uri.value) }}

I would get the url of the original file.

I have the image style information via

item.content['#item']['#image-style']

that 'medium' is requested

A PHP solution is already available here, but how do I do this in TWIG?

There are some attempts on creating a filter for 8.1 here - but that doesn't help me currently.

  • Where do you want to use the image as background, exactly, a node or a page? – kiamlaluno Jul 17 '16 at 6:25
3

You could put the php code in the preprocess function of the field template. You have all information you need in your question.

But then you would do coding, that is already in drupal. If you have #image-style set in the image render element, then the image field should be configured for the preprocess functions that come later in the image-formatter and image-style templates to put the right src attribute in the variables for image-style.html.twig. So you can use the code that is already there by overriding this template.

See the code in /core/module/image/image.module:

function template_preprocess_image_style(&$variables) {
  $style = ImageStyle::load($variables['style_name']);

  // Determine the dimensions of the styled image.
  $dimensions = array(
    'width' => $variables['width'],
    'height' => $variables['height'],
  );

  $style->transformDimensions($dimensions, $variables['uri']);

  $variables['image'] = array(
    '#theme' => 'image',
    '#width' => $dimensions['width'],
    '#height' => $dimensions['height'],
    '#attributes' => $variables['attributes'],
    '#uri' => $style->buildUrl($variables['uri']),
    '#style_name' => $variables['style_name'],
  );
  • 1
    Well the thing is, that I don't want the image to render as an <img> but as a background image inline-style. Currently I either get the correct image with style as an <img> or the original file path which is much to big to use on a non-broadband connection - so I just want to get the path to the down-sampled one. And I don't want to override all image renders, just the one field. Sure I could hardwire hack the path to the style, since I know the original filename - but that would be bad. – Jannis Hell Jan 3 '16 at 10:57
  • You don't have to override all images. You can target the one you want with theme name suggestion or you put a condition in the twig. I would choose the second, because twig debug doesn't make any suggestions for this template. So it would be easier without the need to investigate the right suggestion of this template. The hardwire hack is not advisable. You don't know wether the right image style size is in cache. – 4k4 Jan 3 '16 at 11:11
1

I just had a need to do this as well. The right approach here is to store the image URL of the styled image into a variable (through a preprocess function), and then that variable will be available in your twig file.

I've written a function that will get any field_image file and return the original file name, or if you specify a style name, it will return the URL of the styled image.

Inside my .theme file:

function MYTHEME_preprocess_node(&$vars) {
  //get thumbnail images from field_image
  $vars['field_image_url'] = _var_image_url($vars, 'field_image', 'thumbnail');
}

//pull image field URL (original or styled)
function _var_image_url($vars, $field, $style_name = '') {
  if (!empty($vars['elements'][$field]['#object'])) {
    $fields = $vars['elements'][$field]['#object']->getFields();
    $image = $fields[$field]->getValue();

    if (!empty($image[0]['target_id'])) {
      $file = \Drupal\file\Entity\File::load($image[0]['target_id']);
      $uri = $file->getFileUri();

     if(!empty($style_name)) {
        $url = \Drupal\image\Entity\ImageStyle::load($style_name)->buildUrl($uri);
        return $url; //the styled URL
     } else {
        return file_create_url($uri); //original
     }
   }
 }
 return false;
}

Now in my twig file (node.html.twig, since I used the preprocess_node function):

<div class="banner" style="background-image:url({{ field_image_url }}"></div>

This function _var_image_url() has to be called from the THEME_preprocess_node() function because it's expecting a certain set up in the first $vars argument. If you try calling it from preprocess_page, you would need to modify it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.