如何在 Rails 中显示 SVG 图像?

问题描述 投票:0回答:11
ruby-on-rails ruby-on-rails-4 svg
11个回答
42
投票

在 Rails 应用程序中显示 SVG(可缩放矢量图形)

在资源编译中特别包含SVG文件类型

production.rb 

  config.assets.precompile += %w( '.svg' )  

  # Must include to get inline SVGs to work in deploy
  config.assets.css_compressor = :sass

创建一个助手来显示 SVG

myhelper.rb

def show_svg(path)
  File.open("app/assets/images/#{path}", "rb") do |file|
    raw file.read
  end
end

在您的视图中调用 SVG 处理助手

<%= show_svg('symbols.svg') %>

从你的问题来看,我并不是 100% 清楚你的实现,但这些步骤应该能让你看到你的 SVG 图像。一旦 SVG 可见,您就可以应用 CSS。


11
投票

尝试使用

inline_svg
gem,它添加了一个辅助方法,用于将文件中的 SVG 直接内联到模板中


8
投票

您可以在 Rails 中插入 svg 内联,无需任何额外的 gem,使用如下所示:

<%= render inline: Rails.root.join('public/icon.svg').read %>

如果您需要单击 svg 来执行某些操作,例如发出 POST 请求,请将整个内容包装在带有

link_to
do
中,如下所示:

<%= link_to some_path(@something), method: :post do %>
    <%= render inline: Rails.root.join('public/icon.svg').read %>
<% end %>

7
投票

您可以像显示图像一样显示 SVG。

例如在haml中:

%img{:src => "/images/image1.svg"}

希望有帮助!


4
投票

我一直在尝试不同的解决方案,最终决定将 svg 文档放入

html.erb
部分。由于 svg 是有效的 html,因此将其从资产移动到视图就可以正常工作。

<%# app/views/home/index.html.erb %>

<%= render partial: "svgs/some_svg.html.erb"

给定

app
| views
| | home
| | | index.html.erb
| | svgs
| | | some_svg.html.erb

3
投票

与nvm的方法类似,我有一个助手来帮助构建

use
标签的资源路径,并确保父
svg
标签具有适当的属性

def external_svg(identifier, attributes = {})
  # identifier: <file name without extension>#<fragment id>
  file_name, fragment = identifier.split('#')
  file_name += '.svg'
  attributes.merge!(xmlns: 'http://www.w3.org/2000/svg')
  content_tag :svg, attributes do
    tag.use href: "#{image_path(file_name)}##{fragment}"
  end
end

在视图中,您的 SVG 资源将被称为:

external_svg 'symbols#icon-search', class: 'icon'
,生成的 html:

<svg xmlns="http://www.w3.org/2000/svg" class="icon">
  <use href="<asset pipeline path>/symbols.svg#icon-search" />
</svg>

由于外部引用的 SVG 现在得到了良好的支持,因此您不需要任何 SVG 特定的 gem 即可实现此功能。

使用这种方法时值得注意的优点(缓存)和缺点(CSS 样式限制)。请参阅此 Twitter 帖子


2
投票

对于

ActiveStorage
,根据Elvn的回复,我发现有更好的方法

如果您有一个带有

item
has_one_attached :logo
物体:

<%= show_svg(item.logo_blob) %>

那么助手就是:

    def show_svg(blob)
      blob.open do |file|
        raw file.read
      end
    end

1
投票

很简单:

首先将svg添加到assets.rb中的资源预编译列表中

application.config.assets.precompile +=
    %w(<your other files> symbol-defs.svg)

然后在 erb/haml 文件中引用它,如下所示:

<svg class="icon gr-menu">
  <use xlink:href="<%= asset_path('symbol-defs') %>#gr-menu"></use>
</svg>

1
投票

创建一个助手:(每种情况的内容都不同,自定义您自己的)

def icon(icon, css_class: "")
  content_tag(:svg, class: "icon icon_#{icon} #{css_class}") do
      content_tag(:use, nil, 'xlink:href' => "#icon_#{icon}")
  end
end

像这样使用它:

<%= icon 'arrow-menu' , css_class: 'arrow-breadcrumb' %>

0
投票

如果你可以使用 inline_svg gem。它很旧但仍然有效的解决方案维护得很好

如果您不能(例如公司政策),简而言之,这就是 gem 的作用:

# app/helpers/svg_helper.rb
module SvgHelper
  SVGFileNotFoundError = Class.new(StandardError)

  def inline_svg_tag(path, options = {})
    path = Rails.root.join("app/assets/images/#{path}.svg")
    File.exist?(path) || raise(SVGFileNotFoundError, "SVG icon file does not exist: #{path}")
    svg_file_content = File.binread(path)

    if options.any?
      doc = Nokogiri::XML::Document.parse(svg_file_content)
      svg = doc.at_css("svg")
      svg["height"] = options[:height] if options[:height]
      svg["width"] = options[:width] if options[:width]
      svg["class"] = options[:class] if options[:class]
      svg_file_content = doc.to_html.strip
    end

    raw svg_file_content
  end
end

测试:

# spec/helpers/svg_helpers_spec.rb
require "rails_helper"

RSpec.describe SvgHelper do
  describe "#inline_svg_tag" do
    it "raises an error when the file does not exist" do
      expect { helper.inline_svg_tag("does-not-exist") }.to raise_error(SvgHelper::SVGFileNotFoundError)
    end

    it "when no options passed returns the SVG file contents with original HTML attribute values" do
      result = helper.inline_svg_tag("icons/profile")
      expect(result).to include("<svg")
      expect(result).to include('height="20"')
      expect(result).to include('width="20"')
      expect(result).not_to include("class")
    end

    it "when class option passed returns the SVG file contents with class HTML attribute" do
      result = helper.inline_svg_tag("icons/profile", class: "whatever")
      expect(result).to include("<svg")
      expect(result).to include('class="whatever"')
    end

    it "when height passed returns the SVG file contents with new height" do
      result = helper.inline_svg_tag("icons/profile", height: "12345")
      expect(result).to include("<svg")
      expect(result).not_to include('height="20"')
      expect(result).to include('height="12345"')
    end

    it "when width passed returns the SVG file contents with new width" do
      result = helper.inline_svg_tag("icons/profile", width: "54321")
      expect(result).to include("<svg")
      expect(result).not_to include('width="20"')
      expect(result).to include('width="54321"')
    end
  end
end

-1
投票

我真的不知道如何解析SVG文件;但同样的事情也可以用于 SVG 文件。然后,您可以在 SVG 文件中使用 asset_path 助手;但问题是 Rails 默认解析 CSS、JS 和 ERB。这样,SVG 内部的链接就可以与资源管道配合使用。也许如果您尝试将名称从“symbols.svg”更改为“symbols.svg.erb”,它会解析文件以获取正确的网址。

你的问题是资产管道没有按照rails使用。

这就是解析(预处理)svg 文件的方法:

编译文件的默认匹配器包括application.js, application.css 和所有非 JS/CSS 文件(这将包括所有图像 自动资产)从应用程序/资产文件夹,包括你的宝石:[ Proc.new { |文件名,路径|路径 =~ /app/assets/ && !%w(.js .css).include?(File.extname(文件名)) }, /application.(css|js)$/ ]

有关助手方法的更多信息

2.3.2 CSS 和 Sass

使用资产管道时,必须重写资产路径并 sass-rails 提供 -url 和 -path 帮助器(在 Sass 中连字符, 在 Ruby 中下划线)用于以下资产类别:图像、字体、 视频、音频、JavaScript 和样式表。

image-url("rails.png") becomes url(/assets/rails.png)
image-path("rails.png") becomes "/assets/rails.png".

也可以使用更通用的形式:

asset-url("rails.png") becomes url(/assets/rails.png)
asset-path("rails.png") becomes "/assets/rails.png"

2.3.3 JavaScript/CoffeeScript 和 ERB

如果您向 JavaScript 资产添加 erb 扩展,使其成为某种东西 例如 application.js.erb,然后您可以在中使用 asset_path 帮助器 你的 JavaScript 代码: $('#logo').attr({ src: "<%= asset_path('logo.png') %>" });

这将写入所引用的特定资产的路径。

同样,您可以在 CoffeeScript 文件中使用 asset_path 帮助器 带有 erb 扩展名(例如 application.js.coffee.erb):$('#logo').attr 来源:“<%= asset_path('logo.png') %>”

您可以检查: http://guides.rubyonrails.org/asset_pipeline.html#coding-links-to-assets

© www.soinside.com 2019 - 2024. All rights reserved.