SVG-Dimensionen können nicht extrahiert und festgelegt werden

7

Bisher hatte ich keine Probleme mit den Miniaturansichten der Hintergrundbilder in meinem Thema. Jetzt, da ich versuche, ein SVG als Bild zu verwenden, ist jedoch etwas kaputt. Das Problem scheint mit der Breite der SVGs zu zusammenhängen, die von als Null zurückgegeben werden wp_get_attachment_image_src(). Ich versuche also herauszufinden, wie man die Breiten- und Höheninformationen aus der SVG extrahiert und sie dann auf die entsprechenden Werte in den SVG-Datenbankfeldern setzt. Dies ist nicht einfach.

Hinweis: Es gibt kein allgemeines Problem beim Hochladen oder Rendern von SVGs. Sie werden in meinem Logo einwandfrei angezeigt.

Der Fehler und Code: Beweis der Nullbreite

Dies ist der Fehler, den Wordpress auf der Seite auslöst: Warning: Division by zero in /wp-content/themes/tesseract/functions.php on line 771

Dies ist der Code in functions.php vor dem Fehler (in Zeile 771).

    /*759*/ function tesseract_output_featimg_blog() {
    /*760*/
    /*761*/ global $post;
    /*762*/
    /*763*/ $thumbnail = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );
    /*764*/ $featImg_display = get_theme_mod('tesseract_blog_display_featimg');
    /*765*/ $featImg_pos = get_theme_mod('tesseract_blog_featimg_pos');
    /*766*/
    /*767*/ $w = $thumbnail[1]; /* supposed to return thumbnail width */
    /*768*/ $h = $thumbnail[2];  /* supposed to return thumbnail height */
    /*769*/ $bw = 720;
    /*770*/ $wr = $w/$bw;  
    /*771*/ $hr = $h/$wr; /**** this is the line that throws the error ****/

Sie können sehen, dass es eine Division mit $wrdem Nenner gibt. Es scheint, dass $wres als Null berechnet wird, weil sein einziger nicht konstanter Faktor $webenfalls Null ist (der andere Faktor ist 720, also kann es nicht schuld sein). $wDer Wert wird bestimmt durch $thumbnail[1]. $thumbnail[1]Der Wert wird in Zeile 763 mit folgendem Code eingestellt:

$thumbnail = wp_get_attachment_image_src( get_post_thumbnail_id( $post->ID ), 'full' );

Und gemäß dem Codex ist der zweite Wert im zurückkehrenden Array der Funktion wp_get_attachment_image_src(dh $thumbnail[1]) tatsächlich die Breite des Miniaturbilds. Dieser Wert scheint Null zu sein, da es sich um denselben Wert handelt wie $w, der in Zeile 771 tatsächlich der Nenner ist. :(

Wichtiger Hinweis: Mein Thema implementiert Miniaturansichten als Hintergrundbilder

Das übergeordnete Thema, das ich verwende, "Tesseract", platziert ausgewählte Bilder als Hintergrundbilder von Ankern / <a>Elementen, anstatt sie als <img>Elemente zu platzieren. Ich glaube nicht, dass dies die Ursache des Problems ist, aber wenn Lösungen angeboten werden, sollten sie mit Hintergrundbildern kompatibel sein, nicht mit <img>Objekten.

Fix # 1 konnte nicht angepasst werden:

Ich habe diese Webseite gefunden, die eine Lösung für Probleme bei der Verwendung von SVGs als vorgestellte Bilder bietet. Dies deutet darauf hin, dass das Problem mit der Berechnung der Breite zusammenhängt. Ich kann dieses Update jedoch nicht anwenden, da es sich um ein imgElement handelt, für das eine SVG als vorhanden srcist. Ich habe ein <a>Element, dessen SVG-Position auf background-image- gesetzt ist url.

Dies ist die Lösung

function custom_admin_head() {
  $css = '';
  $css = 'td.media-icon img[src$=".svg"] { width: 100% !important; height: auto !important; }';
  echo '<style type="text/css">'.$css.'</style>';
}
add_action('admin_head', 'custom_admin_head');

Fix # 2 (minimale Breite über CSS) hat nicht funktioniert

Basierend auf der Idee, die ich von der obigen Seite bekommen habe, dass die Breite des Problems das Problem sein könnte, habe ich versucht, eine Mindestbreite von 50% festzulegen, indem ich nur CSS für das verwendet habe <a>. Hier ist der Code:

a.entry-post-thumbnail.above {
    min-width: 50% !important;
} 

Meine Entwicklertools zeigten, dass das CSS "nahm", dass die Mindestbreite auf 50% eingestellt wurde. Trotzdem warf WP den gleichen Fehler, den das Bild nicht zeigte. Vielleicht setzt das CSS es nicht, bevor functions.php wp_get_attachment_image_src ausführt, also spielt es keine Rolle?

Hat jemand irgendwelche Hinweise, wie man diese Nullberechnung umgeht? Ich würde das wirklich gerne mit den Hintergrundbildern zum Laufen bringen, ohne zu viel vom übergeordneten Thema überschreiben zu müssen.

Fix # 3 (Einbinden eines Filters) hat nicht funktioniert.

Mit Hilfe von @Milo, @NathanJohnson und @prosti konnte ich versuchen, einen Filter zu ändern wp_get_attachment_image_src(). Der Code erzeugt keinen Fehler, entfernt jedoch nicht den Teilungsfehler und bringt die SVG nicht zur Anzeige. Dies ist das Snippet, das ich in functions.php platziert habe. Vielleicht sind die Prioritäten falsch? ::

add_filter( 'wp_get_attachment_image_src', 'fix_wp_get_attachment_image_svg', 10, 4 );  /* the hook */

     function fix_wp_get_attachment_image_svg($image, $attachment_id, $size, $icon) {
        if (is_array($image) && preg_match('/\.svg$/i', $image[0]) && $image[1] == 1) {
            if(is_array($size)) {
                $image[1] = $size[0];
                $image[2] = $size[1];
            } elseif(($xml = simplexml_load_file($image[0])) !== false) {
                $attr = $xml->attributes();
                $viewbox = explode(' ', $attr->viewBox);
                $image[1] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null);
                $image[2] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null);
            } else {
                $image[1] = $image[2] = null;
            }
        }
        return $image;
    } 

Das Fazit:

Ich glaube, ich muss herausfinden, wie die Breiteninformationen aus der SVG-Datei selbst extrahiert und zur WP-Datenbank hinzugefügt werden können, bevor functions.php die Berechnung in Zeile 771 ausführt. Wenn Sie wissen, wie, wäre Ihre Anleitung sehr dankbar.

Einige potenziell hilfreiche Ressourcen

  • Diese Frage scheint hilfreiche Informationen zu enthalten, und das dort von @Josh bereitgestellte Snippet ermöglichte es mir, meine SVGs endlich in der Medienbibliothek anzuzeigen, aber das vorgestellte Bild ist immer noch fehlerhaft.
  • Diese Frage scheint einige XML-basierte Lösungen zu haben, aber ich weiß nicht, wie ich sie an WP anpassen soll.
  • Auch ein Kommentator unten hat mich auf diesen Filter hingewiesen , der relevant zu sein scheint.

Der Header der SVG-Datei

Dies ist der SVG-Header:

<?xml version="1.0" encoding="utf-8"?> <!-- Generator: Adobe Illustrator 15.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) --> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="475.419px" height="406.005px" viewBox="0 0 475.419 406.005" enable-background="new 0 0 475.419 406.005" xml:space="preserve">
CoderScissorhands
quelle
1
Schauen Sie sich wp_get_attachment_image_srcim Quellcode an, es gibt einen gleichnamigen Filter. Verwenden Sie den Filter, um die richtigen Größen für SVG-Bilder zurückzugeben.
Milo
1
SVGs sind eigentlich keine "Bilder" und WordPress hat keine native Unterstützung für sie. Sie müssen untersuchen, was Ihrer Site SVG-Unterstützung hinzufügt, und das Problem darin beheben.
Otto
1
Schauen Sie sich fix_wp_get_attachment_image_svgFunktion hier und wo die Filter hinzugefügt hier . Lesen Sie add_filterin docs für eine Erklärung von Filtern.
Milo
1
SVGs sind keine Bilder. Wenn WordPress die Bildgröße berechnet, erkennt es die Datei nicht als Bild und gibt daher Null zurück. Die Verwendung des Filters wp_get_attachment_image_src zur "manuellen" Rückgabe der Bildgröße scheint der richtige Ansatz zu sein.
Nathan Johnson
Kommentare sind nicht für eine ausführliche Diskussion gedacht. Dieses Gespräch wurde in den Chat verschoben .
Howdy_McGee

Antworten:

7

Ich habe es gelöst !!! Der Filter in Fix 3 (oben) funktionierte aufgrund der dritten Bedingung dieser ifAnweisung, die das Extrahieren und Anhängen von Dimensionen auslöst, nicht:

if (is_array($image) && preg_match('/\.svg$/i', $image[0]) && $image[1] == 1)

$image[1]In der dritten Bedingung ist die gemeldete Breite der SVG-Datei so, wie WP sie sieht, bevor sie in den Filter eintritt. Da ich weiß, dass sein Wert, die Breite, 0 ist (aufgrund des oben beschriebenen "Nullteilungsfehlers"), vermutete ich, dass dieser Wert geändert werden musste, um mit ihm übereinzustimmen. Ich habe das Finale 1unter dieser ifBedingung in a 0und..voila geändert! Der Teilungsfehler ist verschwunden und das Bild wird angezeigt, und wunderschön, damit ich Werbung machen kann!

Ich konnte dies erkennen, weil sich in vielen Foren Leute darüber beschweren, dass SVGs fälschlicherweise Breiten von 1 Pixel zugewiesen bekommen. Dies war wahrscheinlich in einigen Versionen von WP der Fall, aber in meiner WP 4.7.2-Medienbibliothek wird keine Dimension für die SVG 1pxals Dimension veröffentlicht , nicht einmal veröffentlicht. Stattdessen gab es in meinem Fall einfach keine Metadaten zu Dimensionen.

Ich denke, eine flexible Version des Filters würde es ermöglichen, ihn anzuwenden, wenn die Breite 1 oder 0 ist, für Leute, die das 1px-Problem hatten, und für Leute wie mich, die eine Breite von 0 hatten. Unten habe ich den Fix mit $image[1] <= 1as eingefügt die dritte Bedingung der ifAussage anstelle von, $image[1] == 1aber ich nehme an, Sie könnten dies auch verwenden:( ($image[1] == 0) || ($image[1] == 1) )

Der Arbeitsfilter

 add_filter( 'wp_get_attachment_image_src', 'fix_wp_get_attachment_image_svg', 10, 4 );  /* the hook */

 function fix_wp_get_attachment_image_svg($image, $attachment_id, $size, $icon) {
    if (is_array($image) && preg_match('/\.svg$/i', $image[0]) && $image[1] <= 1) {
        if(is_array($size)) {
            $image[1] = $size[0];
            $image[2] = $size[1];
        } elseif(($xml = simplexml_load_file($image[0])) !== false) {
            $attr = $xml->attributes();
            $viewbox = explode(' ', $attr->viewBox);
            $image[1] = isset($attr->width) && preg_match('/\d+/', $attr->width, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[2] : null);
            $image[2] = isset($attr->height) && preg_match('/\d+/', $attr->height, $value) ? (int) $value[0] : (count($viewbox) == 4 ? (int) $viewbox[3] : null);
        } else {
            $image[1] = $image[2] = null;
        }
    }
    return $image;
} 

Vielen Dank an alle für Ihre Hilfe, es war wirklich eine Teamleistung!

CoderScissorhands
quelle
Funktioniert nicht unter WordPress 4.9.4
Vadim H
2

Es ist schwer genau zu erraten, was das Problem für den WordPress-Enthusiasten wie mich sein könnte, aber seit du mich in der Schleife gepingt hast ...

Nur um zu erwähnen, dass Sie die Themendateien nicht geteilt haben ...

File: wp-includes/media.php
804: /**
805:  * Retrieve an image to represent an attachment.
806:  *
807:  * A mime icon for files, thumbnail or intermediate size for images.
808:  *
809:  * The returned array contains four values: the URL of the attachment image src,
810:  * the width of the image file, the height of the image file, and a boolean
811:  * representing whether the returned array describes an intermediate (generated)
812:  * image size or the original, full-sized upload.
813:  *
814:  * @since 2.5.0
815:  *
816:  * @param int          $attachment_id Image attachment ID.
817:  * @param string|array $size          Optional. Image size. Accepts any valid image size, or an array of width
818:  *                                    and height values in pixels (in that order). Default 'thumbnail'.
819:  * @param bool         $icon          Optional. Whether the image should be treated as an icon. Default false.
820:  * @return false|array Returns an array (url, width, height, is_intermediate), or false, if no image is available.
821:  */
822: function wp_get_attachment_image_src( $attachment_id, $size = 'thumbnail', $icon = false ) {
823:    // get a thumbnail or intermediate image if there is one
824:    $image = image_downsize( $attachment_id, $size );
825:    if ( ! $image ) {
826:        $src = false;
827: 
828:        if ( $icon && $src = wp_mime_type_icon( $attachment_id ) ) {
829:            /** This filter is documented in wp-includes/post.php */
830:            $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
831: 
832:            $src_file = $icon_dir . '/' . wp_basename( $src );
833:            @list( $width, $height ) = getimagesize( $src_file );
834:        }
835: 
836:        if ( $src && $width && $height ) {
837:            $image = array( $src, $width, $height );
838:        }
839:    }

Dieser Teil mit:

@list( $width, $height ) = getimagesize( $src_file );

Sieht nach dem Problem aus, da SVG-Bilder nicht über die Größeninformationen verfügen . Sie passen einfach in den Behälter.

Sie können also eine eigene Version erstellen, wp_get_attachment_image_srcin der Sie die Größe festlegen können.

Prosti
quelle
Lassen Sie uns diese Diskussion im Chat fortsetzen .
CoderScissorhands