Medienpool: Height / Width für SVG auslesen
Description / Beschreibung
Aktuell bekommt man bei folgender Ausgabe keinen richtigen Wert zurück.
$media = rex_media::get('test.svg');
$media->getWidth() // returns 0
Um eine schönere Ausgabe für Nutzer zu geben ohne Cumulative Layout Shifting auszulösen.
Beispiel:
$attributes = [
'alt' => $media->getTitle(),
'title' => $media->getTitle(),
'src' => $media->getUrl(),
'loading' => 'lazy',
'height' => $media->getHeight(),
'width' => $media->getWidth(),
];
$attributes = array_merge($attributes, $attrs);
$attributesString = '';
foreach($attributes as $key => $val) {
$attributesString .= ' ' . rex_escape($key, 'html_attr') . '="'. rex_escape($val) . '"';
}
return '<img ' . $attributesString . '>';
Hierzu gibt es schon eine Library, die das ausließt: https://github.com/contao/imagine-svg/blob/08eb302552dc83ffc7d0f3b1b79f53207094cfa4/src/Image.php#L354-L390
Hab aber auch bereits eine simplere Funktion geschrieben:
if ($media->getExtension() == 'svg') {
$xml = simplexml_load_file(rex_path::media($media->getFileName()));
$width = $xml['width'] ? $xml['width']->__toString() : 0;
$height = $xml['height'] ? $xml['height']->__toString() : 0;
if (!$height && !$width) {
$viewBox = $xml['viewBox'] ? $xml['viewBox']->__toString() : 0;
$viewBox = preg_split('/[\s,]+/', $viewBox);
$width = (float) ($viewBox[2] ?? 0);
$height = (float) ($viewBox[3] ?? 0);
}
}
Affected versions / Verwendete Versionen
REDAXO: 5.12 PHP: 7.4 Database: 8.0 Browser: Firefox AddOns: Media Manager
@Sysix Ein kleiner Hinweis:
Du kannst hier abkürzen
$attributes = [
'alt' => $media->getTitle(),
'title' => $media->getTitle(),
'src' => $media->getUrl(),
'loading' => 'lazy',
'height' => $media->getHeight(),
'width' => $media->getWidth(),
];
return sprints('<img %s>', rex_string::buildAttributes(array_merge($attributes, $attrs)));
@Sysix ich habe deine Methode angepasst und binde sie über einen EP ein.
boot.php
rex_extension::register('MEDIA_UPDATED', array('MEINE KLASSE', 'mediapool_updated_svg_viewbox'));
Eigene Klasse
public static function mediapool_updated_svg_viewbox(rex_extension_point $ep)
{
$subject = $ep->getSubject();
$filename = $ep->getParam('filename');
$media = rex_media::get($filename);
if ('image/svg+xml' == $media->getType()) {
$xml = simplexml_load_file(rex_path::media($filename));
$viewBox = $xml['viewBox'] ? $xml['viewBox']->__toString() : 0;
$viewBox = preg_split('/[\s,]+/', $viewBox);
$width = (float) ($viewBox[2] - $viewBox[0] ?? 0);
$height = (float) ($viewBox[3] - $viewBox[1] ?? 0);
if (!$height && !$width) {
$width = $xml['width'] ? $xml['width']->__toString() : 0;
$height = $xml['height'] ? $xml['height']->__toString() : 0;
}
$sql = rex_sql::factory();
$sql->setWhere('filename="'.$filename.'"');
$sql->setTable('rex_media');
$sql->setValue('width', $width);
$sql->setValue('height', $height);
$sql->update();
}
return $subject;
}
In meinen SVGs habe ich in den Attributen Höhe/Breite 100% bekommen, deswegen möchte ich erst die viewBox auswerten. Ich kenne keine Situation, bei der die viewBox nicht bei 0|0 anfängt, aber falls doch, ziehe ich left von right und top von bottom ab.