From 5ae036752587173bd031d4201bf4492e1628f74c Mon Sep 17 00:00:00 2001 From: songtianlun Date: Thu, 13 Feb 2025 15:25:12 +0800 Subject: [PATCH 1/5] feat: enhance image handling for weather arts - Remove deprecated `image_with_watermark` attachment. - Introduce `webp_image`, `preview_image`, and `watermarked_image` methods in `WeatherArt` model for optimized image formats. - Update views to use new image variants, including webp and previews, improving loading times and visual quality. - Ensure images are processed with relevant attributes such as quality and dimensions for better performance and user experience. These changes enhance the image handling capabilities of the application by ensuring images are served in a more efficient format (WebP) and with improved resizing options, leading to better performance overall. --- app/models/city.rb | 4 +- app/models/weather_art.rb | 142 ++++++++++++++++++++++++++- app/views/arts/index.html.erb | 4 +- app/views/cities/_city.html.erb | 2 +- app/views/cities/index.html.erb | 2 +- app/views/cities/show.html.erb | 4 +- app/views/weather_arts/show.html.erb | 8 +- 7 files changed, 153 insertions(+), 13 deletions(-) diff --git a/app/models/city.rb b/app/models/city.rb index 8f5e73f..4d7f95b 100644 --- a/app/models/city.rb +++ b/app/models/city.rb @@ -42,14 +42,14 @@ class City < ApplicationRecord # 根据数据库类型构建不同的查询 base_query = if ActiveRecord::Base.connection.adapter_name.downcase == "sqlite" joins(<<-SQL.squish) - LEFT JOIN ahoy_events ON + LEFT JOIN ahoy_events ON#{' '} json_extract(ahoy_events.properties, '$.city_id') = cities.id AND json_extract(ahoy_events.properties, '$.event_type') = 'city_view' AND ahoy_events.time > '#{start_time}' SQL else joins(<<-SQL.squish) - LEFT JOIN ahoy_events ON + LEFT JOIN ahoy_events ON#{' '} (ahoy_events.properties::jsonb->>'city_id')::integer = cities.id AND ahoy_events.properties::jsonb->>'event_type' = 'city_view' AND ahoy_events.time > '#{start_time}' diff --git a/app/models/weather_art.rb b/app/models/weather_art.rb index 1eea6e5..344fe8b 100644 --- a/app/models/weather_art.rb +++ b/app/models/weather_art.rb @@ -4,7 +4,6 @@ class WeatherArt < ApplicationRecord belongs_to :city has_one_attached :image - has_one_attached :image_with_watermark has_many :visits, class_name: "Ahoy::Visit", foreign_key: :weather_art_id has_many :events, class_name: "Ahoy::Event", foreign_key: :weather_art_id @@ -59,4 +58,145 @@ class WeatherArt < ApplicationRecord def image_url image.attached? ? image.blob : nil end + + def webp_image + return nil unless image.attached? + + image.variant( + format: "webp", + saver: { + quality: 100, + strip: true, # 移除元数据以减小文件大小 + interlace: "plane" # 渐进式加载 + } + ) + end + + # 添加图片变体处理 + PREVIEW_DIMENSIONS = { + big: [ 1792, 1024 ], + medium: [ 896, 512 ], + small: [ 448, 256 ] + }.freeze + def preview_image(size = :medium) + return nil unless image.attached? + + width, height = PREVIEW_DIMENSIONS[size] || PREVIEW_DIMENSIONS[:medium] + + image.variant( + resize_to_limit: [ width, height ], + format: "webp", + saver: { + quality: 75, + strip: true, # 移除元数据以减小文件大小 + interlace: "plane" # 渐进式加载 + } + ) + end + + def watermarked_image + return nil unless image.attached? + + overlay_text = create_overlay_text + + image.variant( + composite: [ { + input: overlay_text, + gravity: "southeast" + } ] + ) + end + + private + + def create_overlay_text + { + create: { + width: 400, + height: 100, + background: [ 0, 0, 0, 0.5 ] # 半透明黑色背景 + }, + "svg-overlay": %( + + + #{city.name} - #{weather_date.strftime('%Y-%m-%d')} + + + © todayaiweather.com + + + ) + } + end + + def create_text_layer(font_size) + text = [ + weather_date.strftime("%Y-%m-%d"), + "#{temperature}°C, #{description}", + "#{city.name}, #{city.country.name}, #{city.country.region.name}", + "© todayaiweather.com" + ].join("\n") + + { + create: { + width: 600, + height: 200, + background: [ 0, 0, 0, 0 ] + }, + "svg-overlay": %( + + + #{weather_date.strftime('%Y-%m-%d')} + #{temperature}°C, #{description} + #{city.name}, #{city.country.name} + © todayaiweather.com + + ) + } + end + + def watermark_command(font_size:, stroke_width:, spacing:) + date_str = weather_date.strftime("%Y-%m-%d") + weather_info = "#{temperature}°C, #{description}" + location_info = "#{city.name}, #{city.country.name}, #{city.country.region.name}" + copyright = "© todayaiweather.com" + + "gravity southeast " \ + "fill white " \ + "font Arial " \ + "pointsize #{font_size} " \ + "stroke black " \ + "strokewidth #{stroke_width} " \ + "text 30,#{spacing * 12} '#{copyright}' " \ + "text 30,#{spacing * 8} '#{location_info}' " \ + "text 30,#{spacing * 4} '#{weather_info}' " \ + "text 30,#{spacing} '#{date_str}'" + end + + def watermark_text + date_str = weather_date.strftime("%Y-%m-%d") + weather_info = "#{temperature}°C, #{description}" + location_info = "#{city.name}, #{city.country.name}, #{city.country.region.name}" + copyright = "© todayaiweather.com" + + [ + "text 30,120 '#{copyright}'", + "text 30,80 '#{location_info}'", + "text 30,40 '#{weather_info}'", + "text 30,0 '#{date_str}'" + ].join(" ") + end end diff --git a/app/views/arts/index.html.erb b/app/views/arts/index.html.erb index 7c677a9..42a55b1 100644 --- a/app/views/arts/index.html.erb +++ b/app/views/arts/index.html.erb @@ -6,7 +6,7 @@ <% if featured_art&.image&.attached? %>
- <%= image_tag featured_art.image, + <%= image_tag featured_art.webp_image.processed, class: "w-full h-full object-cover" %>
@@ -107,7 +107,7 @@
<% if art.image.attached? %> - <%= image_tag art.image, + <%= image_tag art.preview_image.processed, class: "w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-500" %>
diff --git a/app/views/cities/_city.html.erb b/app/views/cities/_city.html.erb index bf0ba53..438d472 100644 --- a/app/views/cities/_city.html.erb +++ b/app/views/cities/_city.html.erb @@ -5,7 +5,7 @@
- <%= image_tag city.latest_weather_art.image, + <%= image_tag city.latest_weather_art.preview_image.processed, class: "w-full h-full object-cover transform group-hover:scale-105 transition-transform duration-500" %>
diff --git a/app/views/cities/index.html.erb b/app/views/cities/index.html.erb index 07782c9..425138f 100644 --- a/app/views/cities/index.html.erb +++ b/app/views/cities/index.html.erb @@ -6,7 +6,7 @@ <% if featured_art&.image&.attached? %>
- <%= image_tag featured_art.image, + <%= image_tag featured_art.webp_image.processed, class: "w-full h-full object-cover object-center" %>
diff --git a/app/views/cities/show.html.erb b/app/views/cities/show.html.erb index 654b980..b0d504b 100644 --- a/app/views/cities/show.html.erb +++ b/app/views/cities/show.html.erb @@ -2,7 +2,7 @@ <% if @city.latest_weather_art&.image&.attached? %>
- <%= image_tag @city.latest_weather_art.image, + <%= image_tag @city.latest_weather_art.webp_image.processed, class: "absolute w-full h-full object-cover scale-110 filter blur-2xl opacity-25" %>
@@ -103,7 +103,7 @@
<% if art.image.attached? %> - <%= image_tag art.image, + <%= image_tag art.preview_image.processed, class: "w-full h-full object-cover transform hover:scale-105 transition-transform duration-500" %>
diff --git a/app/views/weather_arts/show.html.erb b/app/views/weather_arts/show.html.erb index b3261df..162fcdc 100644 --- a/app/views/weather_arts/show.html.erb +++ b/app/views/weather_arts/show.html.erb @@ -27,15 +27,15 @@