在Wordpress中处理SVG渲染的方法?


9

随着Internet浏览器的进步,我发现自己在对网站进行编码时使用SVGS越来越舒适……尤其是对于图标和可以用png即时替换的简单图形。

看起来wordpress几乎支持SVGS。我说这几乎是因为:

  1. 默认情况下,wordpress中不是允许的文件类型。因此,您需要在上传SVG之前添加它

  2. 您在媒体库中看不到SVG缩略图。(见下图)

  3. 有时,当您将其添加到编辑器中(通过添加媒体按钮)时,编辑器并不知道svg的大小,因此尽管将svg添加为图像,但其宽度和高度均为零。

  4. 当您从媒体上传弹出窗口中单击“编辑图像”时,您会收到一条消息,提示“图像不存在”。参见下图。

我对这个清单中的项目1感到满意,但是有人能找出解决方案2 3和4的方法吗?

在此处输入图片说明 在此处输入图片说明

关于项目1的更新:

要允许新的mime类型(例如SVG),您可以在functions.php中添加一个钩子

function allow_new_mime_type($mimes) {

    $mimes['svg'] = 'image/svg+xml';

    return $mimes;
}
add_filter( 'mime_types', 'allow_new_mime_type' );

现在,您应该可以上传SVG了。您可以在本教程中找到更多信息。这只能解决第1项,正如我之前提到的,这对我来说不是问题(尽管我认为默认情况下应允许)。

有关项目2的更新:

我做了一些挖掘,并找到了决定附件是否为图像的函数。看来一切都归结为wp-includes / post.php中的此功能

/**
 * Check if the attachment is an image.
 *
 * @since 2.1.0
 *
 * @param int $post_id Attachment ID
 * @return bool
 */
function wp_attachment_is_image( $post_id = 0 ) {
    $post_id = (int) $post_id;
    if ( !$post = get_post( $post_id ) )
        return false;

    if ( !$file = get_attached_file( $post->ID ) )
        return false;

    $ext = preg_match('/\.([^.]+)$/', $file, $matches) ? strtolower($matches[1]) : false;

    $image_exts = array( 'jpg', 'jpeg', 'jpe', 'gif', 'png' );

    if ( 'image/' == substr($post->post_mime_type, 0, 6) || $ext && 'import' == $post->post_mime_type && in_array($ext, $image_exts) )
        return true;
    return false;
}

如您所见,此函数中定义了一组有效的图像扩展名。我看不到任何可用于修改该数组的过滤器。但这是一个开始...

我不确定为什么最后一个if语句对svgs返回false。即使我不将svg扩展名添加到$ image_exts数组中,第一个条件也应返回true,不是吗?

if ( 'image/' == substr($post->post_mime_type, 0, 6)

这会检查“ image /”是否等于mime类型中的前六个字符,对于svg而言,该字符是image / svg + xml(前六个是“ image /”)。

更新

经过进一步调查,似乎问题根本不是wp_attachment_is_image,而是因为在上传SVG时未将图像大小(宽度和高度)添加到附件元数据中。这是因为用于计算所使用图像的函数是php函数getimagesize(),该函数不会返回SVG的图像大小。我在关于stackoverflow的getimagesize函数以及svgs行为方面找到了答案。在这里看到它。


安装SVG支持插件,它将在媒体库上显示svg-wordpress.org/plugins/svg-support
Nuno Sarmento

Answers:


10

看一下wp_prepare_attachment_for_js(),它是收集附件元数据以在Media页面上使用的内容。使用同名过滤器可以添加或更改元数据。

以下示例可以放入functions.php中。注意:这需要PHP中的SimpleXML支持。

function common_svg_media_thumbnails($response, $attachment, $meta){
    if($response['type'] === 'image' && $response['subtype'] === 'svg+xml' && class_exists('SimpleXMLElement'))
    {
        try {
            $path = get_attached_file($attachment->ID);
            if(@file_exists($path))
            {
                $svg = new SimpleXMLElement(@file_get_contents($path));
                $src = $response['url'];
                $width = (int) $svg['width'];
                $height = (int) $svg['height'];

                //media gallery
                $response['image'] = compact( 'src', 'width', 'height' );
                $response['thumb'] = compact( 'src', 'width', 'height' );

                //media single
                $response['sizes']['full'] = array(
                    'height'        => $height,
                    'width'         => $width,
                    'url'           => $src,
                    'orientation'   => $height > $width ? 'portrait' : 'landscape',
                );
            }
        }
        catch(Exception $e){}
    }

    return $response;
}
add_filter('wp_prepare_attachment_for_js', 'common_svg_media_thumbnails', 10, 3);

2

这不是您可以轻松地通过插件或少量代码“侵入”的东西。

简而言之,就其之前出现的所有图像而言,SVG基本上不是“图像”。SVG是基于矢量的图像,并且是第一个在网络上获得真正吸引力的图像。

之前的所有图像都是基于位图的。WordPress的图像处理系统是专门为处理这些问题而编写的,并且这种固有的设计位于系统的每个位置。

例如,这是一个假设,即图像具有宽度和高度。SVG没有,它们可以是任何大小。WordPress内置了用于图像的整个基本“编辑器”,这些功能都不能真正应用于SVG。

多媒体系统正在缓慢地重新开发,此处重点是“缓慢地”。有很多向后兼容性要维护,要实施新的设计。另外,大多数人对支持视频,音频和播放列表更感兴趣。随着这项重新设计工作的完成,并且库的各个部分变得更加抽象,随着时间的推移,这种事情将变得更易于支持。但这还不存在,而且不会持续一段时间。这就是为什么不支持SVG MIME类型的原因,因为在所有基础部分都起作用之前添加该MIME类型将是破坏之路。

对于SVG,wp_attachment_is_image应该返回false,因为wp_attachment_is_image它用于确定是否显示编辑器按钮以及是否image_downsize尝试将图像调整为缩略图等。无论如何,这两种方法都不适用于SVG。为了正确地支持SVG,您需要编写一个新系统以完全为这些图像添加元数据,然后在可能使用元数据的所有位置添加对它的支持。可以想象,这不是一件小事。


1
SVG确实有大小(视口和视图框),它比位图的固定像素相关尺寸更“虚拟”。
腊斯特2014年

1

只是从阅读源代码(而不是测试)中,我可以看到扩展名需要匹配:

if ( 'image/' == substr($post->post_mime_type, 0, 6) || $ext && 'import' == $post->post_mime_type && in_array($ext, $image_exts) )

读为(伪代码)

if image/是$ post对象post_mime_type属性中的前6个字符,或者是扩展名,import还是$ post对象post_mime_type属性,并且当前文件扩展名是(Array)中的一个

这意味着最后一条语句将始终确定结果是否if正确。

根据我的读物get_attached_file(),有一个过滤器可以伪造扩展名:

return apply_filters( 'get_attached_file', $file, $attachment_id );

换句话说,您可以尝试返回相同的文件,但具有不同的扩展名。它不会与其他部分发生冲突,因为wp_attachment_is_image()公正的回报bool

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.