画像の読み込みが遅いのをごまかすテクニックの紹介。こんな動きをするやつです:
- 解像度の低いもやっとした軽量版の画像をあらかじめ表示
- 解像度の高いきれいな画像をロードできたタイミングで置き換え
私の初見は medium.com でした。今は他のサイトでも使われてるのを見ます。
ちゃんと名前があって、“Blur Up” というそうです。知りませんでした。
複数の画像を用意しなきゃいけないけれど、Rails の ActiveStorage なんかを使えば、そこはわりとかんたんにクリアできます。js 側も、作ってみると結構かんたんでした(こだわらなければ)。
こんなモデルがあったとして、
class Comment < ApplicationRecord
has_one_attached :image
end
こんなヘルパーを用意して、
def blur_up_image_tag(comment, width:, height:)
image_tag low_quality_image(comment), data: { high_src: url_for(high_quality_image(comment)) },
class: 'js-blur-up', width: width, height: height
end
def low_quality_image(comment)
comment.image.variant(resize_to_limit: [100, 100], saver: { quality: 10 })
end
def high_quality_image(comment)
comment.image.variant(resize_to_limit: [800, 800], saver: { quality: 90 })
end
erb からヘルパーを叩いて、
<%= blur_up_image_tag(@comment, width: 500, height: 320) %>
js でゴニョります。
for (const img of document.querySelectorAll('.js-blur-up')) {
img.style.filter = 'blur(20px)'
const high = new Image()
high.onload = () => {
img.style.filter = 'none'
img.style.transition = 'filter .1s ease-out'
img.src = high.src
}
high.src = img.dataset.highSrc
}
low_quality_image
は画像のサイズも小さければ、JPEG の品質も低めに設定しています。画像にもよるけど、試しに使ってたものだと 3kb 弱でした。これなら一瞬でロードできそうですよね。引き伸ばしてそのまま表示すると、まともに見れたものではありません。そこで CSS の filter
でぼやかしてやります。
high_quality_image
はサイズも品質も高めに設定しています。この画像をロードしたタイミングで、画面上の画像を置き換えつつ、ぼやかし用の filter
を解除してやります。解除時にちょっとアニメーションを入れてやることで、かっこよくなります。このへんは好みということで。