天翔TNXGの空间站

使用Blurhash和mdui实现动态主题色与模糊预览

2024-06-09 12:45预计阅读时间: 2 分钟
/ ,
,
123

Summary

这篇博文介绍了如何结合使用Blurhash和mdui框架来实现网页的动态主题色和图片的模糊预览效果。Blurhash是一个用于生成模糊效果的库,而mdui是一个基于Material Design的前端框架。作者首先介绍了目标,即利用背景图的主色调设置页面主题色,并通过预处理图片生成Blurhash来优化页面加载性能。接着,提供了一个Python脚本,用于批量生成图片的Blurhash并存储在JSON文件中。然后,通过JavaScript代码将Blurhash转换为base64格式的图片,并从中提取主题色。最后,作者展示了实现的效果,并提供了相关项目的GitHub链接。

在现代Web开发中,用户体验的提升往往伴随着细节的优化。Blurhash 是一个用于生成和解码模糊哈希的库,能够实现图片的模糊预览效果。而 mdui 为我们提供了基于 Material Design 3 (Material You) 的前端框架,包含丰富的组件和样式。在这篇博文中,我们将结合Blurhash和mdui,实现一个根据背景图动态设置主题色的页面,并优化图片加载性能。

目标

我们希望在页面底部附上一张背景图,并使用这张背景图的主色调作为整个页面的主题色。

预处理图片生成Blurhash并通过随机图api直接提供

为了避免在页面加载时的计算开销,我们可以预先生成每张图片的Blurhash,并存储在一个JSON文件中。

下面的Python脚本可以批量处理图片并生成Blurhash:

import concurrent.futures
import os
import json
import logging
from PIL import Image
from blurhash import encode

logging.basicConfig(level=logging.INFO)

current_path = os.path.abspath(os.path.dirname(__file__))

def encode_file(file):
    logging.info(f'Encoding {file} to blurhash')
    image = Image.open(os.path.join(current_path, file))
    blurhash = encode(image, x_components=4, y_components=3)
    return file, blurhash

current_files = [f for f in os.listdir(current_path) if f.endswith(('jpg', 'png', 'jpeg'))]
blurhashes = {}

with concurrent.futures.ThreadPoolExecutor() as executor:
    future_to_file = {executor.submit(encode_file, file): file for file in current_files}
    for future in concurrent.futures.as_completed(future_to_file):
        file = future_to_file[future]
        try:
            file, blurhash = future.result()
            blurhashes[file] = blurhash
        except Exception as exc:
            logging.error('%r generated an exception: %s' % (file, exc))

with open('blurhash.json', 'w') as f:
    json.dump(blurhashes, f)

那么我们后端就可以通过读取这个json文件来获取到图片对应的blurhash值,并与图片一起提供

提供的数据大概如下

{
    "code": "200",
    "image": "https://cdn.tnxg.top/images/wallpaper/5.jpg",
    "blurhash": "LcI~*}r=TJS$~VX8S2b^?HW;wIoe"
}

设置背景图和主题色

我们这时候就已经拥有了图片的url以及对应的模糊哈希。

我们这时就能将模糊哈希转换为base64格式的图片

    const blurredImage = (blurhash) => {
      if (!blurhash) return '';
      const pixels = decode(blurhash, 32, 32);
      const canvas = document.createElement('canvas');
      canvas.width = 32;
      canvas.height = 32;
      const ctx = canvas.getContext('2d');
      const imageData = ctx.createImageData(32, 32);
      imageData.data.set(pixels);
      ctx.putImageData(imageData, 0, 0);
      return canvas.toDataURL();
    };

然后我们就能够将base64图片新建一个image对象,并获取其主题色

因为是原图的模糊哈希转换来的图片,主体色调应该差不太多,所以我们可以直接使用这个颜色作为主题色

const blurredImageData = blurredImage(data.blurhash);
const ColorImage = new Image();
ColorImage.src = blurredImageData;
getColorFromImage(ColorImage)
    .then(color => {
        setColorScheme(color);
        console.log('Color scheme set.' + color);
    })

生成出的base64模糊图也可以用来当做卡片的背景,保持背景和卡片的色调显得相得益彰

关于Blurhash的传递我们可以使用状态管理Pinia直接将转换过后的base64图片存储在全局状态中,这样就不用每次都重新计算了

最终效果

通过以上步骤,我们实现了在页面加载时先显示模糊预览图,并根据其主色调动态设置主题色。当高清背景图加载完成后,替换掉模糊预览图,提升了用户体验和页面性能。

以下是最终效果的示例:

示例效果

使用项目

希望这篇博文能帮助你更好地理解和使用Blurhash与mdui来提升Web应用的用户体验。如果你有任何问题或建议,欢迎在评论区留言。

使用Blurhash和mdui实现动态主题色与模糊预览
Author天翔TNXG
Update date2024-07-11