在 Laravel 5 Blade 模板中包含 SVG 内容

Posted

技术标签:

【中文标题】在 Laravel 5 Blade 模板中包含 SVG 内容【英文标题】:Including SVG contents in Laravel 5 Blade template 【发布时间】:2015-07-15 12:24:03 【问题描述】:

在 Laravel 5 刀片模板中包含 SVG 文件(位于 assets 文件夹中)的内容的最佳方式是什么?

我不想使用图像/对象/嵌入标签,出于速度原因,这应该是内联 SVG。

我知道我可以使用<?php file_get_contents("file.svg") ?>,但有没有更好的方法专门用于 Laravel/Blade?​​p>

编辑:澄清一下,该方法应该适用于所有 SVG文件,包括下面的一个。

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg">
<path stroke="red" fill="#00f" d="M10 10h100v100H10z"/>
</svg>

【问题讨论】:

.svg 是什么样的?它是具有不同图标的精灵图像吗? 当你做&lt;?php include("file.svg") ?&gt; 时会发生什么你看到什么渲染了吗? SVG 是一个标志。应该是 file_get_contents() 而不是 include(),但它确实有效(当 SVG 没有 XML 版本元素时)。我只是想找到一种更好的方法。 【参考方案1】:

View Composer 方法

我最终在服务提供商中使用了视图编辑器。

在服务提供者的boot()方法中:

// Wildcard view composer
view()->composer('*', function($view) 
    // Instantiate new DOMDocument object
    $svg = new DOMDocument();
    // Load SVG file from public folder
    $svg->load(public_path('images/logo.svg'));
    // Add CSS class (you can omit this line)
    $svg->documentElement->setAttribute("class", "logo");
    // Get XML without version element
    $logo = $svg->saveXML($svg->documentElement);
    // Attach data to view
    $view->with('logo', $logo);
);

在我看来:

<!-- Echo unescaped SVG content -->
!! $logo !!

我正在使用DOMDocument,因为它允许我删除不应在 html 中的 XML 版本元素。

CSS 类不是必需的,但可以省去我用另一个 HTML 元素包装徽标以进行样式设置。

如果您只需要特定 Blade 部分中的徽标,例如标题,您可以编写

view()->composer('header', function($view) );

http://laravel.com/docs/5.0/views#view-composershttps://laracasts.com/series/laravel-5-fundamentals/episodes/25

叶片局部法

这种方法不是最佳实践,因为这种代码实际上不应该出现在视图中。但是,它非常简单,比在每个视图中添加 PHP 代码要好得多。

使用以下代码创建一个新的部分(比如说 logo.blade.php):

<?php
// Instantiate new DOMDocument object
$svg = new DOMDocument();
// Load SVG file from public folder
$svg->load(public_path('images/logo.svg'));
// Add CSS class (you can omit this line)
$svg->documentElement->setAttribute("class", "logo");
// Echo XML without version element
echo $svg->saveXML($svg->documentElement);
?>

您现在可以在刀片模板中使用 SVG 图像,方法是像这样包含部分:

@include('logo')

【讨论】:

【参考方案2】:

这行得通,这是我能想到的最简单的方法:

!! file_get_contents('images/icon.svg') !!

【讨论】:

这种方法的问题是 XML 版本元素(如果它存在于 SVG 中)被包含在 HTML 中。【参考方案3】:

为什么不将 svg 放入刀片模板中?

resources/views/icons/dashboard.blade.php

然后使用刀片语法添加您的视图?

@include('icons.dashboard')

【讨论】:

【参考方案4】:

类似于接受的答案,但更简洁(imo)。

使用 laravel 指令来扩展刀片,就像这样(在您的应用服务提供程序中,如 here 所述):

    \Blade::directive('svg', function($arguments) 
        // Funky madness to accept multiple arguments into the directive
        list($path, $class) = array_pad(explode(',', trim($arguments, "() ")), 2, '');
        $path = trim($path, "' ");
        $class = trim($class, "' ");

        // Create the dom document as per the other answers
        $svg = new \DOMDocument();
        $svg->load(public_path($path));
        $svg->documentElement->setAttribute("class", $class);
        $output = $svg->saveXML($svg->documentElement);

        return $output;
    );

然后像这样在刀片中使用它:

        <div class="Login__image Login__cloud">
            @svg('cloud.svg', 'Cloud')
        </div>

【讨论】:

嗯,很高兴看到如何扩展刀片。如果它更好是一个不同的问题,虽然所有的处理和整个仪式?下一位读者的所有问号?我会用&lt;?= file_get_contents("file.svg") ?&gt; tbh 我不确定我明白你的意思吗? 对于 Sage(Roots WP 主题),我是这样使用的:sage('blade')-&gt;compiler()-&gt;directive('svg', function ($arguments) list($path, $class) = array_pad(explode(',', trim($arguments, "() ")), 2, ''); $path = trim($path, "' "); $class = trim($class, "' "); $svg = new \DOMDocument(); $svg-&gt;load(asset_path($path)); $svg-&gt;documentElement-&gt;setAttribute("class", $class); $output = $svg-&gt;saveXML($svg-&gt;documentElement); return $output; ); @Toskan 处理的重点是删除 XML 版本元素,如果包含该元素会使 HTML 无效。

以上是关于在 Laravel 5 Blade 模板中包含 SVG 内容的主要内容,如果未能解决你的问题,请参考以下文章

在每个 foreach 循环迭代中包含重复的刀片模板

使用 PhpUnit 测试在 Laravel 5 包中包含 @include 或 @extend 指令的刀片视图

在 laravel 5.3 中添加 css 和 js 文件

Laravel 5 - 所有模板中都可用的全局 Blade 视图变量

Laravel 5.1 Blade模板引擎

使用 Blade 模板的 Laravel 5 表单中预选选项的条件 @if 语句