[Cross Browser Blur Effect AND Getting Image Info from Drupal Media Library Images]
Ok, the stuff in the twig template was almost directly copied from Cross-browser blur-effect (Chrome, Firefox, Safari, IE10+).
Note that the way to get the equivalent of object-fit: cover
with an image inside an svg is to make sure the svg viewbox matches the image dimensions, and that the svg has preserveAspectRatio="xMidYMid slice"
set.
The toughest part of implementing this was getting the image info from Drupal (url was tough enough, but width and height were super challenging!!!). Sad but true -- I pretty much spent a whole day on it. I finally found my breakthrough in the code for "d8-responsive-image-programmatically.php"
This could also be implemented in WordPress, by adjusting the PHP backend code. Getting image url, width, and height is comparatively trivial in WP :P
/**
* Implements hook_preprocess_HOOK() for Block document templates.
*/
function radicati_d8_preprocess_block(&$variables) {
if (!empty($variables["elements"]["#id"]) && $variables["elements"]["#id"] == 'defaultsitemessage') {
if (!empty($variables['elements']['content']['field_background_image'])) {
// get the image uri from the entity reference
$uri = $variables['content']['#block_content']->get('field_background_image')->entity->get('field_media_image')->entity->uri->value;
// get the image object attached to that uri
$image = \Drupal::service('image.factory')->get($uri);
// verify that it's really an image, and if so store the needed info as an object in $variables
if ($image->isValid()) {
$variables['site_message_background_image'] = [
'url' => file_create_url($uri),
'width' => $image->getWidth(),
'height' => $image->getHeight(),
];
}
}
}
}
{# The regular card template stuff goes here...#}
{% block card_extra_content %}
{# This is an alternative way of displaying the site message background image. It's a huge PITA and the only reason I'm doing this is that the regular image has a filter: blur applied, which IE doesn't support. #}
{# This solution depends on JS, so if somebody is running IE with JS disabled, they just don't get a blurry background image. #}
{# This isn't a responsive image, so it's loading the full-size original. However, it will only load if the ie-svg script is triggered, which copies the data-uri value to href and thus loads the image. #}
{# In theory, all the devices that are running IE will be non-mobile, so this should be ok... #}
<div {{ bem('ie-background-image-wrapper', null, 'card') }}>
<svg {{ bem('ie-background-image', null, 'card', ['image--ie-replacement-svg']) }} preserveAspectRatio="xMidYMid slice" viewbox="0 0 {{ background_image.width }} {{ background_image.height }}">
<defs>
<filter id="blur">
<feGaussianBlur stddeviation="3"/>
</filter>
</defs>
<image data-uri="{{ background_image.url }}" width="{{ background_image.width }}" height="{{ background_image.height }}" filter="url(#blur)"></image>
</svg>
</div>
{% endblock card_extra_content %}
(function($, Drupal) {
"use strict";
// find all the original images
var originalImageWrapper = document.querySelectorAll(".image--original");
// find all the svg replacement images
var ieSvgImageWrapper = document.querySelectorAll(".image--ie-replacement-svg");
// Detect Internet Explorer with Ducktyping
// https://stackoverflow.com/a/31479176/6412747
var isIE = /*@cc_on!@*/false || !!document.documentMode;
// only run this if the browser is ie, and thus unable to display the original images properly
if (isIE) {
// go through all the images tagged to replace
// set the original image to display none
// also remove its source and sourceset so it stops downloading and wasting bandwidth
for (var i = 0; i < originalImageWrapper.length; i++) {
originalImageWrapper[i].style.display = "none";
var originalImage = originalImageWrapper[i].querySelector('img');
originalImage.src = '';
originalImage.srcset = '';
}
// go through all the images tagged as replacements
// set the replacement images (which default to display: none) to display: block
// grab the url from the data-uri attribute and copy it to href so the image loads
for (var i = 0; i < ieSvgImageWrapper.length; i++) {
ieSvgImageWrapper[i].style.display = "block";
var ieSvgImage = ieSvgImageWrapper[i].querySelector("image");
var ieSvgImageUri = ieSvgImage.getAttribute('data-uri');
ieSvgImage.setAttribute("href", ieSvgImageUri);
}
}
})(jQuery, Drupal);