diff --git a/app/helpers/image_helper.rb b/app/helpers/image_helper.rb new file mode 100644 index 0000000..9b6afd7 --- /dev/null +++ b/app/helpers/image_helper.rb @@ -0,0 +1,16 @@ +module ImageHelper + # 画像圧縮オプション(品質85%で視覚的な劣化なく30-50%削減) + IMAGE_COMPRESSION_OPTIONS = { saver: { quality: 85 } }.freeze + + # variantオプションに圧縮設定をマージ + # + # @param options [Hash] resize_to_fillなどのvariantオプション + # @return [Hash] 圧縮設定がマージされたオプション + # + # @example + # compressed_variant(resize_to_fill: [450, 300]) + # # => { resize_to_fill: [450, 300], saver: { quality: 85 } } + def compressed_variant(options) + options.merge(IMAGE_COMPRESSION_OPTIONS) + end +end diff --git a/app/views/shared/_membership_avatar.html.erb b/app/views/shared/_membership_avatar.html.erb index ce739af..af5d43e 100644 --- a/app/views/shared/_membership_avatar.html.erb +++ b/app/views/shared/_membership_avatar.html.erb @@ -1,9 +1,10 @@ <% size ||= 60 %> <% initial_font_size ||= 'sm' %> +<% lazy ||= true %> <% if membership.avatar.attached? %>
- <%= image_tag membership.avatar.variant(resize_to_fill: [size, size]), alt: "#{membership.display_name}のアバター", class: "w-#{size/4} h-#{size/4} rounded-full object-cover" %> + <%= image_tag membership.avatar.variant(compressed_variant(resize_to_fill: [size, size])), alt: "#{membership.display_name}のアバター", class: "w-#{size/4} h-#{size/4} rounded-full object-cover", loading: lazy ? "lazy" : "eager" %>
<% else %>
diff --git a/app/views/teams/events/_main_column.html.erb b/app/views/teams/events/_main_column.html.erb index 9c081dd..b171714 100644 --- a/app/views/teams/events/_main_column.html.erb +++ b/app/views/teams/events/_main_column.html.erb @@ -25,7 +25,7 @@ <% if event.image.attached? %>
- <%= image_tag event.image.variant(resize_to_fill: [1500, 1000]), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover" %> + <%= image_tag event.image.variant(compressed_variant(resize_to_fill: [1500, 1000])), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover" %>
<% else %>
@@ -127,7 +127,7 @@
<% if event.report_image.attached? %>
- <%= image_tag event.report_image.variant(resize_to_fill: [1500, 1000]), alt: "#{event.name}の開催レポート画像", class: "w-full h-full object-cover" %> + <%= image_tag event.report_image.variant(compressed_variant(resize_to_fill: [1500, 1000])), alt: "#{event.name}の開催レポート画像", class: "w-full h-full object-cover", loading: "lazy" %>
<% end %> diff --git a/app/views/teams/memberships/_event_item.html.erb b/app/views/teams/memberships/_event_item.html.erb index 5b88b4d..e423382 100644 --- a/app/views/teams/memberships/_event_item.html.erb +++ b/app/views/teams/memberships/_event_item.html.erb @@ -1,7 +1,7 @@ <%= link_to team_event_path(@team, event), class: "flex gap-4 py-4 border-t border-gray-200" do %>
<% if event.image.attached? %> - <%= image_tag event.image.variant(resize_to_fill: [150, 100]), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover" %> + <%= image_tag event.image.variant(compressed_variant(resize_to_fill: [150, 100])), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover", loading: "lazy" %> <% else %>
No Image diff --git a/app/views/teams/show.html.erb b/app/views/teams/show.html.erb index f8b37cc..551de18 100644 --- a/app/views/teams/show.html.erb +++ b/app/views/teams/show.html.erb @@ -16,7 +16,7 @@
<% if event.image.attached? %>
- <%= image_tag event.image.variant(resize_to_fill: [450, 300]), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover" %> + <%= image_tag event.image.variant(compressed_variant(resize_to_fill: [450, 300])), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover", loading: "lazy" %>
<% else %>
@@ -167,7 +167,7 @@
<% if event.image.attached? %>
- <%= image_tag event.image.variant(resize_to_fill: [450, 300]), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover" %> + <%= image_tag event.image.variant(compressed_variant(resize_to_fill: [450, 300])), alt: "#{event.name}のイメージ画像", class: "w-full h-full object-cover", loading: "lazy" %>
<% else %>
diff --git a/spec/helpers/image_helper_spec.rb b/spec/helpers/image_helper_spec.rb new file mode 100644 index 0000000..b24e926 --- /dev/null +++ b/spec/helpers/image_helper_spec.rb @@ -0,0 +1,20 @@ +require 'rails_helper' + +RSpec.describe ImageHelper, type: :helper do + describe '#compressed_variant' do + it '圧縮オプションをマージして返す' do + result = helper.compressed_variant(resize_to_fill: [ 450, 300 ]) + expect(result).to eq(resize_to_fill: [ 450, 300 ], saver: { quality: 85 }) + end + + it '既存のオプションを保持しつつ圧縮オプションを追加する' do + result = helper.compressed_variant(resize_to_limit: [ 1000, 1000 ], format: :webp) + expect(result).to eq(resize_to_limit: [ 1000, 1000 ], format: :webp, saver: { quality: 85 }) + end + + it '空のハッシュにも圧縮オプションを追加する' do + result = helper.compressed_variant({}) + expect(result).to eq(saver: { quality: 85 }) + end + end +end