问题描述

到目前为止,我的主题中没有 background-image 缩略图的问题。然而,现在我正在尝试使用 SVG 作为特色图像,有些东西正在破裂。问题似乎与由 wp_get_attachment_image_src()返回为零的 SVG 的宽度有关。所以我想做的是弄清楚如何从 SVG 中提取宽度和高度信息,然后将它们设置为 SVG 数据库字段中的适当值,这并不容易。

注意:上传或呈现 svgs 并不存在一般问题,它们在我的徽标中显示正常。

错误和代码:zero-width 的证据

这是 Wordpress 在页面上抛出的错误:Warning: Division by zero in /wp-content/themes/tesseract/functions.php on line 771

这是在错误之前的 functions.php 中的代码 (在第 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 ****/

您可以看到有一个与 $wr 作为分母的部门。 $wr 似乎被计算为零,因为它的唯一 non-constant 因子 $w 也是零 (另一个因素是 720,所以不能怪) 。 $w 的值由 $thumbnail[1]确定。 $thumbnail[1]的值是在第 763 行设置的,代码如下:

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

并且根据 the Codex,函数 wp_get_attachment_image_src(即 $thumbnail[1]) 的返回数组中的第二个值确实是缩略图的宽度。该值似乎为零,因为它与 $w 的值相同,它确实是 771 行的分母。:(

重要说明:我的主题实现缩略图为 background-images

我使用的父主题”Tesseract” 将特征图像作为锚点/<a> 元素的背景图像,而不是将它们放置为<img> 元素。我不相信这是问题的原因,但提供解决方案时,应该与 background-images 兼容,而不是<img> 对象。

无法修改#1:

我找到了 this webpage,它为使用 SVG 作为特征图像的问题提供了一个修复。这表明这个问题与宽度的计算有关。但是,我不能应用此修复程序,因为它是一个 img 元素,具有 SVG 作为 src,我有一个<a> 元素,其 SVG 位置设置为 background-imageurl

这是修复

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

修复#2(min-width 通过 CSS) 没有工作

根据我从上述页面得到的想法,可能是宽度可能是问题,我尝试使用 CSS 将<a> 设置为 50%的 min-width 。这是代码:

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

我的开发人员工具显示,CSS “took”,min-width 的设置为 50%。 Still WP 抛出的图像没有显示相同的错误。也许 CSS 没有在 functions.php 之前设置它运行 wp_get_attachment_image_src,所以没关系?

任何人都有关于如何解决这个零计算的任何线索?我真的想让这个工作与 background-images,而不必覆盖太多的父主题。

修复#3(挂起一个过滤器) 没有工作。

在 @Milo,@NathanJohnson 和 @prosti 的帮助下,我可以尝试过滤器来更改 wp_get_attachment_image_src()。代码不会产生错误,但它不会消除分裂错误或使 SVG 显示。这是我放在 functions.php 中的代码段。优先事项也许是错误的? :

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;
    }

底线:

我相信我需要弄清楚如何从 SVG 文件本身提取宽度信息,并将其添加到 WP 数据库中,然后在.7p 行运行计算。如果您知道如何,您的指导将非常受赞赏。

一些潜在有用的资源

  • This question 似乎有帮助的信息,而 @Josh 提供的片段让我终于可以在媒体库中查看我的 SVG,但是特色图片仍然被打破。

  • This question 似乎有一些 XML-based 解决方案,但我不知道如何适应 WP 。

  • 下面的一位评论员也指出我对 This filter 的看法是相关的。

SVG 文件的标题

这是 SVG 标题:

<?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">

最佳解决方案

我解决了!由于触发维度提取和附件的 if 语句的第三个条件,修补程序#3(上) 中的过滤器不起作用:

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

在第三个条件下,$image[1]是 WP 进入过滤器之前报告的 SVG 文件的宽度。因为我知道它的值,宽度是 0(从上面的 「zero-division 错误」) 我怀疑这个值需要改变以匹配它。我将 if 的最终 1 更改为 0 和… 。分裂错误消失,图像显示,美丽,所以我可以广告!

我能够发现这一点,因为在许多论坛上,人们抱怨说,SVG 不正确地获得 1px 的分配宽度。这在 WP 的某些版本中可能是这种情况,但在我的 WP 4.7.2 媒体库中,没有 SVG 的维度,甚至没有张贴 1px 的维度。相反,在我的情况下,根本就没有关于维度的元数据。

我认为过滤器的灵活版本将允许应用宽度为 1 或 0,对于具有 1px 问题的人和像我这样的人,宽度为 0. 下面我包括修复,使用 $image[1] <= 1 作为 if 语句的第三个条件而不是 $image[1] == 1,但我想你也可以使用它:( ($image[1] == 0) || ($image[1] == 1) )

工作过滤器

 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;
}

感谢大家的帮助,这真的是一个团队的努力!

次佳解决方案

很难猜出像我这样的 WordPress 爱好者可能是什么问题,但是因为你在循环中 ping 了我…

只是提到你还没有共享主题文件…

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:    }

这部分与:

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

看起来像 SVG 图像 don’t have the size info 的问题。他们只是适合容器。

所以你可以创建自己的版本的 wp_get_attachment_image_src,你可以在某种程度上设置大小。

参考文献

注:本文内容整合自 Google/Baidu/Bing 辅助翻译的英文资料结果。如果您对结果不满意,可以加入我们改善翻译效果:薇晓朵技术论坛。