redaxo icon indicating copy to clipboard operation
redaxo copied to clipboard

Medienpool: Height / Width für SVG auslesen

Open Sysix opened this issue 4 years ago • 4 comments

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 avatar Jun 15 '21 12:06 Sysix

@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)));

tbaddade avatar Jun 15 '21 13:06 tbaddade

@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.

AWqxKAWERbXo avatar Apr 18 '22 21:04 AWqxKAWERbXo