作者: zzh

  • 一些获取随机图像的接口

    不评判储存在服务器还是使用第三方的方案,只记录一些随机获取图像的接口。下面每个方案前都会放置相对于的接口的图像。

    以下内容仅为个人记录用处,从未有意侵权已注册商标,也从未试图冒充任何开放内容官方。当然如果您认为下列内容侵犯了您的权益,请您与我联系 m#hoytzhang.com

    无需注册的方案

    Bing image

    bing image

    2025年3月3日 发现该网站证书失效。有兴趣的朋友可以访问下面的开源地址。或者你也可以考虑自己部署这个仓库到vercel上。 https://github.com/flow2000/bing-wallpaper-api

    TL;DR

    获取bing每日图像的接口非常多,下面是我推荐的一个,目前运行还是比较稳定的

    官网地址

    https://bing.img.run/api.html

    开源地址

    https://github.com/mike126126/bing

    使用方法

    Bing今日壁纸

    <img src="https://bing.img.run/uhd.php" alt="Bing每日壁纸UHD超高清原图" />
    <img src="https://bing.img.run/1920x1080.php" alt="Bing每日壁纸1080P高清" />
    <img src="https://bing.img.run/1366x768.php" alt="Bing每日壁纸普清" />
    <img src="https://bing.img.run/m.php" alt="Bing每日壁纸手机版1080P高清" />

    随机获取Bing历史壁纸

    <img src="https://bing.img.run/rand_uhd.php" alt="随机获取Bing历史壁纸UHD超高清原图" />
    <img src="https://bing.img.run/rand.php" alt="随机获取Bing历史壁纸1080P高清" />
    <img src="https://bing.img.run/rand_1366x768.php" alt="随机获取Bing历史壁纸普清" />
    <img src="https://bing.img.run/rand_m.php" alt="随机获取Bing历史壁纸手机版1080P高清" />

    Picsum.Photos

    Picsum.Photos

    官网

    TL;DR

    一款开源的,采用Unsplash图像源的免费网站

    下面的内容我几乎是从他的官网直接复制过来的。你可以点击下面访问官网,带有图像更容易理解方便你使用。

    https://picsum.photos/

    源码

    https://github.com/DMarby/picsum-photos

    使用方法

    • 直接返回固定大小图像地址
    https://picsum.photos/200/300
    • 返回固定大小的方形图像
    https://picsum.photos/200
    https://picsum.photos/id/237/200/300
    • 自定义seed的图像
    https://picsum.photos/seed/picsum/200/300
    • 去色图像(灰色)
    https://picsum.photos/200/300?grayscale
    • 添加高斯模糊(最后的参数支持1-10)
    https://picsum.photos/200/300/?blur
    https://picsum.photos/200/300/?blur=5

    官方推荐的使用方法

    您可以组合上述任何选项。

    例如,获取灰度和模糊的特定图像。

    https://picsum.photos/id/870/200/300?grayscale&blur=2

    要在浏览器中请求多个相同大小的图片,请添加 random 查询参数以防止图片被缓存:

    <img src="https://picsum.photos/200/300?random=1">
    <img src="https://picsum.photos/200/300?random=2">

    如果需要文件结尾,可以在 url 末尾添加 .jpg。

    https://picsum.photos/200/300.jpg

    要获取 WebP 格式的图像,您可以在 URL 末尾添加 .webp。

    https://picsum.photos/200/300.webp

    列出图像地址

    列出图片

    使用 /v2/list 端点获取图像列表。

    https://picsum.photos/v2/list

    默认情况下,API 将每页返回 30 个项目。

    要请求另一个页面,请使用 ?page 参数。

    要更改每页的项目数,请使用 ?limit 参数。

    https://picsum.photos/v2/list?page=2&limit=100

    链接的header需要包含有关下一页/上一页的分页信息

    获取图像信息

    https://picsum.photos/id/0/info
    https://picsum.photos/seed/picsum/info

    返回的格式如下

    {
            "id": "0",
            "author": "Alejandro Escamilla",
            "width": 5616,
            "height": 3744,
            "url": "https://unsplash.com/...",
            "download_url": "https://picsum.photos/..."
    }

    LoremFlickr

    LoremFlickr

    官网

    TL;DR

    图像来自于Flickr,官网称目前的服务被严重影响

    官网仅推荐当作占位符(Placeholder)来使用

    https://loremflickr.com/

    开源地址

    https://github.com/MastaBaba/LoremFlickr-2

    • 直接使用

    如果你不指定任意内容,将会返回小猫的图像,例如下面的这种用法

    https://loremflickr.com/320/240
    • 指定主题
    //这个地址将会返回`小狗(dog)`相关的图像
    https://loremflickr.com/320/240/dog
    • 保留色彩

    相对于picsum的灰色图像,LoremFlickr可以选择保留更多色彩

    https://loremflickr.com/g/320/240/paris

    这个示例将会返回灰色的 小狗(dog) 相关的图像。你还可以尝试 predgreenblue 这些关键字!

    • 多个关键字

    下面这个地址将会返回与 小猫(cat)和小狗(dog) 相关的图像

    https://loremflickr.com/320/240/cat,dog
    • 强调关键字

    上面的使用方案可能会同时包含 小猫(cat)和小狗(dog) ,如果你像强调关键字,那么你可以使用下面的方法

    https://loremflickr.com/320/240/cat,dog/all

    可以搭配色彩关键字使用

    https://loremflickr.com/g/320/240/cat,dog/all
    • 锁定图像
    https://loremflickr.com/320/240?lock=30976
    • 避免重复图像,同样支持random函数
    https://loremflickr.com/320/240?random=1
    https://loremflickr.com/320/240?random=2
    https://loremflickr.com/320/240?random=3
    • 支持json返回数据
    https://loremflickr.com/json/g/320/240/paris,girl/all
    • 支持RSS订阅
    https://loremflickr.com/rss/d/g/320/240/paris,girl/all

    需要注册的方案

    Unsplash

    大名鼎鼎的Unsplash的免费接口寿终正寝后(貌似是因为流量太大且没有回流),api从开放式改为账号调用。

    2024年6月11日官方下线了免费调用,但是你依旧可以注册后使用这个服务,不过免费服务存在一些限制,下面是三个档次的服务区别:

    1. Demo:每小时50次调用
    2. Production:在遵守Unsplash条件的前提下,每小时5000次
    3. Enterprise:联系Unsplash团队

    在第二条中,Unsplash的要求包括但不限于:

    • 每张图片只允许使用Url返回的 photo.urls 的图像
    • 用户进行图像下载时,必须使用 photo.links.download_location 的链接进行下载
    • 每张图像展示时标明摄影师且附带摄影师的个人链接
    • 不允许制作Unsplash的竞品程序

    如果你可以接受并遵守以上条件,你可以访问这个文档进行申请:https://unsplash.com/documentation

  • 仿照linktree做的个人主页

    你可以访问这里查看: https://hoytzhang.com

    pc-hoytzhang.webp

    实现的效果:

    • 随机显示背景图像
    • 从背景图像提取主要颜色设置为按钮的颜色
    • 适配移动端
    • 点击项目按钮展开/收缩项目

    下面是代码,当然还有一个去除JS的代码,一起附在下面,可能需要你手动设置按钮颜色

    附带JS的版本

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My page</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
        <style>
            @font-face {
                font-family: 'Opposans';
                src: url('opposans.woff2') format('woff2');
                font-weight: normal;
                font-style: normal;
            }
            html, body {
                height: 100%;
                margin: 0;
                overflow: hidden;
            }
            #buttonContainer hr {
                border: none;
                border-top: 2px dashed #007bff;
                margin: 10px 10px;
            }
            body {
                font-family: 'Opposans', Arial, sans-serif;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                background-size: cover;
                background-position: center;
                background-repeat: no-repeat;
                transition: background 0.5s;
            }
            .container {
                text-align: center;
                backdrop-filter: blur(20px);
                border-radius: 20px;
                padding: 30px;
                width: 90%;
                max-width: 400px;
                box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
            }
            h1 {
                color: white;
                padding: 0;
                margin: 0;
            }
            .link {
                display: flex;
                align-items: center;
                justify-content: flex-start;
                color: white;
                padding: 15px;
                margin: 10px 0;
                text-decoration: none;
                border-radius: 30px;
                transition: background 0.3s;
            }
            .link i {
                padding: 0px;
                width: 1.2rem;
                height: 1.2rem;
                font-size: 1.2rem;
                margin-right: 10px;
            }
            .social-media {
                margin: 20px;
                display: flex;
                justify-content: center;
            }
            .social-icon {
                background-color: rgba(255, 255, 255, 0.2);
                color: white;
                border-radius: 50%;
                width: 2.5rem;
                height: 2.5rem;
                display: flex;
                justify-content: center;
                align-items: center;
                margin: 0 10px;
                font-size: 1.2rem;
                transition: background 0.3s;
                text-decoration: none;
            }
            .social-icon:hover {
                background-color: rgba(255, 255, 255, 0.4);
            }
            footer {
                margin-top: 20px;
                font-size: 0.8em;
                color: white;
            }
    
            @media (max-width: 600px) {
                .container {
                    backdrop-filter: none;
                    box-shadow: none;
                }
            }
        </style>
    </head>
    <body>
    
    <div class="container">
        <h1>Name here</h1>
        <div class="social-media">
            <a class="social-icon" href="https://github.com/username" target="_blank"><i class="fa-brands fa-github"></i></a>
            <a class="social-icon" href="https://x.com/username" target="_blank"><i class="fa-brands fa-x-twitter"></i></a>
            <a class="social-icon" href="https://instagram.com/username" target="_blank"><i class="fa-brands fa-instagram"></i></a>
            <a class="social-icon" href="https://t.me/username" target="_blank"><i class="fa-brands fa-telegram"></i></a>
        </div>
        <a class="link" href="https://myblog.com"><i class="fas fa-scroll"></i>Blog</a>
        <a class="link" href="mailto:m@username.com"><i class="fas fa-envelope"></i>Hire me</a>
        <a class="link" href="/" id="dynamicButtonLink"><i class="fa-solid fa-file-code"></i>Projects</a>
        <div id="buttonContainer" style="display: none;">
            <hr>
            <a class="link" href="https://username.site"><i class="fas fa-link"></i>Projects name</a>
            <a class="link" href="https://github.com/username/Projects1/"><i class="fab fa-github"></i>Projects1</a>
            <a class="link" href="https://github.com/username/Projects2/"><i class="fab fa-github"></i>Projects2</a>
        </div>
    </div>
    
    <footer>
        <p>&copy; 2024 Name</p>
    </footer>
    
    <canvas id="myCanvas" style="display:none;"></canvas>
    
    <script>
        const backgrounds = [
            '1.webp',
            '2.webp',
            '3.webp',
            '4.webp',
            '5.webp',
            '6.webp',
            '7.webp',
            '8.webp',
            '9.webp',
            '10.webp',
            '11.webp',
            '12.webp',
            '13.webp',
            '14.webp',
            '15.webp',
            '16.webp',
            '17.webp',
            '18.webp'
        ];
        
        const randomIndex = Math.floor(Math.random() * backgrounds.length);
        const backgroundImage = backgrounds[randomIndex];
        document.body.style.backgroundImage = `url(${backgroundImage})`;
    
        const canvas = document.getElementById('myCanvas');
    
        function getImageColor(canvas, img) {
            canvas.width = img.width;
            canvas.height = img.height;
    
            const context = canvas.getContext("2d");
            context.drawImage(img, 0, 0, canvas.width, canvas.height);
    
            const data = context.getImageData(0, 0, img.width, img.height).data;
            let r = 0, g = 0, b = 0;
    
            const pixelCount = img.width * img.height;
            for (let i = 0; i < data.length; i += 4) {
                r += data[i];     // R
                g += data[i + 1]; // G
                b += data[i + 2]; // B
            }
            r = Math.round(r / pixelCount);
            g = Math.round(g / pixelCount);
            b = Math.round(b / pixelCount);
    
            return `rgb(${r}, ${g}, ${b})`;
        }
    
        function lightenColor(rgb, percent) {
            const rgbValues = rgb.match(/\d+/g).map(Number);
            const r = Math.min(255, Math.round(rgbValues[0] + (255 - rgbValues[0]) * percent));
            const g = Math.min(255, Math.round(rgbValues[1] + (255 - rgbValues[1]) * percent));
            const b = Math.min(255, Math.round(rgbValues[2] + (255 - rgbValues[2]) * percent));
            return `rgb(${r}, ${g}, ${b})`;
        }
    
        const img = new Image();
        img.crossOrigin = 'anonymous';
        img.src = backgroundImage;
    
        img.onload = function() {
            const rgbColor = getImageColor(canvas, img);
            
            const links = document.querySelectorAll('.link');
            links.forEach(link => {
                link.style.backgroundColor = rgbColor;
                link.style.color = 'white';
                
                const hoverColor = lightenColor(rgbColor, 0.2);
                link.addEventListener('mouseover', () => {
                    link.style.backgroundColor = hoverColor;
                });
                link.addEventListener('mouseout', () => {
                    link.style.backgroundColor = rgbColor;
                });
            });
            const hr = document.querySelector('#buttonContainer hr');
            hr.style.borderTop = `2px dashed ${rgbColor}`;
            const socialIcons = document.querySelectorAll('.social-icon');
            socialIcons.forEach(icon => {
                icon.style.backgroundColor = rgbColor;
                
                const hoverColor = lightenColor(rgbColor, 0.2);
                icon.addEventListener('mouseover', () => {
                    icon.style.backgroundColor = hoverColor;
                });
                icon.addEventListener('mouseout', () => {
                    icon.style.backgroundColor = rgbColor;
                });
            });
    
            const footer = document.querySelector('footer');
            footer.style.color = rgbColor;
        };
        document.getElementById('dynamicButtonLink').addEventListener('click', function(event) {
            event.preventDefault();
    
            const buttonContainer = document.getElementById('buttonContainer');
    
            if (buttonContainer.style.display === 'none') {
                buttonContainer.style.display = 'block';
            } else {
                buttonContainer.style.display = 'none';
            }
        });
    </script>
    
    </body>
    </html>
    

    去除JS的版本

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>My page</title>
        <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css">
        <style>
            @font-face {
                font-family: 'Opposans';
                src: url('opposans.woff2') format('woff2');
                font-weight: normal;
                font-style: normal;
            }
            html, body {
                height: 100%;
                margin: 0;
                overflow: hidden;
            }
            #buttonContainer hr {
                border: none;
                border-top: 2px dashed #007bff;
                margin: 10px 10px;
            }
            body {
                font-family: 'Opposans', Arial, sans-serif;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                background-size: cover;
                background-position: center;
                
                background-repeat: no-repeat;
                transition: background 0.5s;
            }
            .container {
                text-align: center;
                backdrop-filter: blur(20px);
                border-radius: 20px;
                padding: 30px;
                width: 90%;
                max-width: 400px;
                box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
            }
            h1 {
                color: white;
                padding: 0;
                margin: 0;
            }
            .link {
                display: flex;
                align-items: center;
                justify-content: flex-start;
                color: white;
                padding: 15px;
                margin: 10px 0;
                text-decoration: none;
                border-radius: 30px;
                transition: background 0.3s;
            }
            .link i {
                padding: 0px;
                width: 1.2rem;
                height: 1.2rem;
                font-size: 1.2rem;
                margin-right: 10px;
            }
            .social-media {
                margin: 20px;
                display: flex;
                justify-content: center;
            }
            .social-icon {
                background-color: rgba(255, 255, 255, 0.2);
                color: white;
                border-radius: 50%;
                width: 2.5rem;
                height: 2.5rem;
                display: flex;
                justify-content: center;
                align-items: center;
                margin: 0 10px;
                font-size: 1.2rem;
                transition: background 0.3s;
                text-decoration: none;
            }
            .social-icon:hover {
                background-color: rgba(255, 255, 255, 0.4);
            }
            footer {
                margin-top: 20px;
                font-size: 0.8em;
                color: white;
            }
    
            @media (max-width: 600px) {
                .container {
                    backdrop-filter: none;
                    box-shadow: none;
                }
            }
        </style>
    </head>
    <body>
    
    <div class="container">
        <h1>Name here</h1>
        <div class="social-media">
            <a class="social-icon" href="https://github.com/username" target="_blank"><i class="fa-brands fa-github"></i></a>
            <a class="social-icon" href="https://x.com/username" target="_blank"><i class="fa-brands fa-x-twitter"></i></a>
            <a class="social-icon" href="https://instagram.com/username" target="_blank"><i class="fa-brands fa-instagram"></i></a>
            <a class="social-icon" href="https://t.me/username" target="_blank"><i class="fa-brands fa-telegram"></i></a>
        </div>
        <a class="link" href="https://myblog.com"><i class="fas fa-scroll"></i>Blog</a>
        <a class="link" href="mailto:m@username.com"><i class="fas fa-envelope"></i>Hire me</a>
        <a class="link" href="/" id="dynamicButtonLink"><i class="fa-solid fa-file-code"></i>Projects</a>
        <hr>
        <a class="link" href="https://username.site"><i class="fas fa-link"></i>Projects name</a>
        <a class="link" href="https://github.com/username/Projects1/"><i class="fab fa-github"></i>Projects1</a>
        <a class="link" href="https://github.com/username/Projects2/"><i class="fab fa-github"></i>Projects2</a>
    </div>
    
    <footer>
        <p>&copy; 2024 Name</p>
    </footer>
    
    </body>
    </html>

    附加随机图像

    如果你想要一个每次打开都会展示不一样的背景图像的页面,你可以使用下面的代码。如果你不想使用代码里的随机图像方案,你可以查看我的另一篇文章,里面有其他可选择的随机图像api: https://banzhuanriji.com/frontend/random-image.html

    <!DOCTYPE html>
    <html lang="zh">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>Name</title>
        <link rel="stylesheet" href="https://s4.zstatic.net/ajax/libs/font-awesome/6.7.2/css/all.min.css">
        <style>
            @font-face {
                font-family: 'Opposans';
                src: url('opposans.woff2') format('woff2');
                font-weight: normal;
                font-style: normal;
            }
            html, body {
                height: 100%;
                margin: 0;
                overflow: hidden;
            }
            #buttonContainer hr {
                border: none;
                border-top: 2px dashed #007bff;
                margin: 10px 10px;
            }
            body {
                font-family: 'Opposans', Arial, sans-serif;
                display: flex;
                flex-direction: column;
                justify-content: center;
                align-items: center;
                background-size: cover;
                background-position: center;
                background-repeat: no-repeat;
                transition: background 0.5s;
            }
            .container {
                text-align: center;
                backdrop-filter: blur(20px);
                border-radius: 20px;
                padding: 30px;
                width: 90%;
                max-width: 400px;
                box-shadow: 0 0 15px rgba(0, 0, 0, 0.5);
            }
            h1 {
                color: white;
                padding: 0;
                margin: 0;
            }
            .link {
                display: flex;
                align-items: center;
                justify-content: flex-start;
                color: white;
                padding: 15px;
                margin: 10px 0;
                text-decoration: none;
                border-radius: 30px;
                transition: background 0.3s;
            }
            .link i {
                padding: 0px;
                width: 1.2rem;
                height: 1.2rem;
                font-size: 1.2rem;
                margin-right: 10px;
            }
            .social-media {
                margin: 20px;
                display: flex;
                justify-content: center;
            }
            .social-icon {
                background-color: rgba(255, 255, 255, 0.2);
                color: white;
                border-radius: 50%;
                width: 3rem;
                height: 3rem;
                display: flex;
                justify-content: center;
                align-items: center;
                margin: 0 10px;
                font-size: 1.2rem;
                transition: background 0.3s;
                text-decoration: none;
            }
            .social-icon:hover {
                background-color: rgba(255, 255, 255, 0.4);
            }
            footer {
                margin-top: 20px;
                font-size: 0.8em;
                color: white;
            }
    
            @media (max-width: 600px) {
                .container {
                    backdrop-filter: none;
                    box-shadow: none;
                }
            }
        </style>
    </head>
    <body>
    
    <div class="container">
        <h1>Name</h1>
        <div class="social-media">
            <a class="social-icon" href="https://github.com/username" target="_blank"><i class="fa-brands fa-github"></i></a>
            <a class="social-icon" href="https://x.com/username" target="_blank"><i class="fa-brands fa-x-twitter"></i></a>
            <a class="social-icon" href="https://instagram.com/username" target="_blank"><i class="fa-brands fa-instagram"></i></a>
            <a class="social-icon" href="https://t.me/username" target="_blank"><i class="fa-brands fa-telegram"></i></a>
        </div>
        <a class="link" href="https://name.com"><i class="fas fa-scroll"></i>Blog</a>
        <a class="link" href="/"><i class="fas fa-envelope"></i>Hire me</a>
        <a class="link" href="/" id="dynamicButtonLink"><i class="fa-solid fa-file-code"></i>Projects</a>
        <div id="buttonContainer" style="display: none;">
            <hr>
            <a class="link" href="https://github.com/username/Project1/"><i class="fab fa-github"></i>Project1</a>
            <a class="link" href="https://github.com/username/Project2/"><i class="fab fa-github"></i>Project2</a>
        </div>
    </div>
    
    <footer>
        <p>&copy; 2024 username</p>
    </footer>
    
    <canvas id="myCanvas" style="display:none;"></canvas>
    
    <script>
        const imageUrl = 'https://picsum.photos/1920/1080.webp';
    
        // Fetch the image to get a consistent URL
        fetch(imageUrl)
            .then(response => {
                if (response.ok) {
                    const img = new Image();
                    img.crossOrigin = 'anonymous';
                    img.src = response.url; // Use the resolved URL
                    img.onload = function() {
                        document.body.style.backgroundImage = `url(${response.url})`;
                        const canvas = document.getElementById('myCanvas');
                        const rgbColor = getImageColor(canvas, img);
    
                        const links = document.querySelectorAll('.link');
                        links.forEach(link => {
                            link.style.backgroundColor = rgbColor;
                            link.style.color = 'white';
    
                            const hoverColor = lightenColor(rgbColor, 0.2);
                            link.addEventListener('mouseover', () => {
                                link.style.backgroundColor = hoverColor;
                            });
                            link.addEventListener('mouseout', () => {
                                link.style.backgroundColor = rgbColor;
                            });
                        });
    
                        const hr = document.querySelector('#buttonContainer hr');
                        hr.style.borderTop = `2px dashed ${rgbColor}`;
                        const socialIcons = document.querySelectorAll('.social-icon');
                        socialIcons.forEach(icon => {
                            icon.style.backgroundColor = rgbColor;
    
                            const hoverColor = lightenColor(rgbColor, 0.2);
                            icon.addEventListener('mouseover', () => {
                                icon.style.backgroundColor = hoverColor;
                            });
                            icon.addEventListener('mouseout', () => {
                                icon.style.backgroundColor = rgbColor;
                            });
                        });
    
                        const footer = document.querySelector('footer');
                        footer.style.color = rgbColor;
                    };
                } else {
                    console.error('Failed to fetch image:', response.status);
                }
            })
            .catch(error => console.error('Error fetching the image:', error));
    
        function getImageColor(canvas, img) {
            canvas.width = img.width;
            canvas.height = img.height;
    
            const context = canvas.getContext("2d");
            context.drawImage(img, 0, 0, canvas.width, canvas.height);
    
            const data = context.getImageData(0, 0, img.width, img.height).data;
            let r = 0, g = 0, b = 0;
    
            const pixelCount = img.width * img.height;
            for (let i = 0; i < data.length; i += 4) {
                r += data[i];     // R
                g += data[i + 1]; // G
                b += data[i + 2]; // B
            }
            r = Math.round(r / pixelCount);
            g = Math.round(g / pixelCount);
            b = Math.round(b / pixelCount);
    
            return `rgb(${r}, ${g}, ${b})`;
        }
    
        function lightenColor(rgb, percent) {
            const rgbValues = rgb.match(/\d+/g).map(Number);
            const r = Math.min(255, Math.round(rgbValues[0] + (255 - rgbValues[0]) * percent));
            const g = Math.min(255, Math.round(rgbValues[1] + (255 - rgbValues[1]) * percent));
            const b = Math.min(255, Math.round(rgbValues[2] + (255 - rgbValues[2]) * percent));
            return `rgb(${r}, ${g}, ${b})`;
        }
    
        document.getElementById('dynamicButtonLink').addEventListener('click', function(event) {
            event.preventDefault();
    
            const buttonContainer = document.getElementById('buttonContainer');
    
            if (buttonContainer.style.display === 'none') {
                buttonContainer.style.display = 'block';
            } else {
                buttonContainer.style.display = 'none';
            }
        });
    </script>
    
    </body>
    </html>
  • 我制作的两款blog主题

    1. 基于hexo平台,主题名为ink,灵感来自bearblog的starter

    https://github.com/hoytzhang/hexo-theme-ink

    1. 一款简约的typecho主题,你可以访问 https://final.linkpark.site/ 查看实现效果

    https://github.com/hoytzhang/typecho-theme-final

  • 为什么不应该在超链接中使用下划线

    一、不利于SEO

    搜索引擎会认为 aaa_bbb 是一个连词,从而识别为这是一个整体单词 aaabbb 。例如你搜索 my_site ,搜索引擎会认为你搜索了 mysite 而非 my site 。而在链接中使用 - 会让搜索引擎认为这是分词符,从而输入更多的准确的关键字。可以参考Google的说明文档

    进而,在用户进行搜索时,搜索引擎可能会忽略你的网站内容。

    二、利于分辨

    友好的内容不仅应该方便机器读取,更应该首先考虑人的感受。那么从人的角度来说为什么不应该使用下划线

    1. 下划线同样会给人一个“这是个长单词的感觉”。没有人会记住你想表达的内容。
    2. 一般的超链接的样式会设置为下划线和蓝色,如果你的链接内带有下划线,有可能会和样式产生重叠和遮挡。
    3. 如果超链接在文本中进行展示时,当你有一个比较长的链接,比如: site.com/this_is_a_very_long_link_on_my_website 。人在试图读这个链接时,眼睛会不由自主地跟随下划线移动。这似乎不太合适。

    三、约定俗成的习惯和莫名其妙的bug

    一般在计算机领域,我们在本地文件会使用下划线内容。然后上传文件后对外提供的链接就会是这样: http://site.com/file_name.txt 。但是这样会出现一个问题:在互联网传播时,浏览器内复制粘贴会将 _ 转义为 %5F ,如果服务器没有进行配置,那你的超链接的文件就会404。而且貌似很多知名公司都有这个问题
    (现在可能已经被修复)。

    四、在域名中不合法

    RFC1738RFC1035等多次投票结果的规则中对域名中出现 _ 表示禁止。也对以前申请了证书的带有下划线的域名的证书进行了回收和禁止续费。但这只是顶级域名的要求,而不是对于顶级域名下的子超链接和文件的限制。

    其实只是很久以前看过的一个博客。说的是在美国军队中导致的一些问题从而禁用了下划线,最近想到了就重新整理一下写成文章分享出来。

  • 网页程序如何正确设置用户路由

    以下是一些在网页程序中设置用户主页路由比较合理的方式及相关要点:

    基于 RESTful 风格

    路径设计

    通常可以采用类似 /users/{username} 这样的路径形式,其中 {username} 是可变的部分,代表具体的用户名。例如,若用户名为 john,那访问 /users/john 就可以跳转到对应的用户主页。这种方式清晰地体现了资源(用户)与对应的标识(用户名)的关系,符合 RESTful 规范中对资源定位的要求,方便理解和记忆,也利于前后端的分工协作以及接口的统一管理。

    还可以添加版本号在路由最前面,如 /v1/users/{username},便于后续对 API 等进行迭代升级,不同版本的路由逻辑可以独立维护,不会相互干扰。

    HTTP 方法匹配

    对于用户主页的获取(也就是查看用户主页信息),一般使用 GET 方法来请求对应的路由。比如,当浏览器发起 GET 请求到 /users/john 时,后端根据这个路由和请求方法,查询数据库中关于 john 用户的信息并返回给前端进行展示,符合 RESTful 中不同方法对应不同操作语义的原则,GET 方法专门用于获取资源这一操作场景。

    考虑用户身份验证与授权相关路由整合

    登录态验证

    • 在用户主页路由对应的处理逻辑之前,往往需要先验证用户是否已经登录。可以通过中间件来拦截请求,检查请求中携带的登录凭证(如 token 等)是否有效。比如,在很多基于 Node.js 的 Web 框架(像 Express)中,编写一个验证登录态的中间件,在路由配置里让用户主页路由先经过这个中间件,只有验证通过才能继续后续的主页数据获取和渲染流程,确保未登录用户无法直接访问用户主页,保障页面的访问安全性和隐私性。

    权限控制路由结合

    有时候用户主页可能根据用户权限展示不同内容,例如管理员用户的主页可能有更多管理功能入口。此时,路由可以配合权限控制模块,根据用户的角色(如普通用户、管理员等)来决定在加载用户主页时,返回哪些对应的模块数据和页面布局。像可以在路由处理函数中先获取用户角色信息,再依据角色从数据库中查询相应权限下的页面配置数据,以准确渲染出符合其权限的用户主页。

    动态路由参数与页面状态关联

    页面主题切换参数

    若用户主页支持切换主题(如亮色模式、暗色模式等),可以在路由中添加额外的参数来表示主题状态,比如 /users/{username}?theme=dark 表示访问 username 用户的主页且采用暗色主题模式。后端接收到这样带有参数的路由请求后,根据 theme 参数的值来调整返回给前端的页面样式相关资源,实现灵活的页面状态定制。

    分页相关参数

    当用户主页有分页展示内容(比如用户发布的文章列表分页显示等),路由中可以包含分页参数,像 /users/{username}/posts?page=2&limit=10,表示查看 username 用户的文章列表,当前是第 2 页,每页显示 10 条内容。后端根据这些参数从数据库中准确提取对应的数据返回给前端,方便用户浏览不同页面的数据内容,提升用户体验。

    路由懒加载与缓存策略配合

    懒加载实现

    对于比较复杂的用户主页,尤其是包含很多模块(如动态的个人动态展示、好友推荐等多个功能模块),可以采用路由懒加载的方式。例如在基于 Vue.js 或 React 等前端框架构建的单页面应用中,将用户主页的不同组件模块配置成懒加载形式,如 const UserHomePage = () => import (‘./UserHomePage.vue’);(Vue.js 示例),这样当用户访问到对应路由时,才会去加载对应的模块代码,减少初始加载的资源量,提高页面加载速度。

    缓存优化

    结合缓存策略,对于用户主页中一些相对静态、不常变化的数据(比如用户的基本信息介绍等),可以在浏览器端或者服务器端设置缓存机制。比如,在服务器端通过设置合适的缓存头(如 Cache-Control 等),告诉浏览器在一定时间内可以直接使用缓存的页面内容,减少重复请求,提升用户再次访问主页的响应速度,同时减轻服务器压力。

    国际化与本地化路由适配

    语言参数设置

    如果网页程序支持多语言,在用户主页路由中可以添加语言相关参数,比如 /users/{username}?lang=en 表示访问 username 用户的主页且采用英语语言环境。后端根据这个参数,加载对应的语言包来渲染页面文字内容,使得不同语言习惯的用户都能获得合适的用户主页展示效果,方便国际化拓展和满足不同地区用户的需求。

    总之,设置用户主页路由需要综合考虑多方面因素,从路由的规范、安全性、页面状态灵活度、性能优化以及多语言适配等角度出发,打造出合理且易用的路由体系。

    次级域名方案分析

    技术可行性

    从技术角度来说,是可以设置username.website.com这类次级域名(也称为子域名)路由的。在服务器配置层面,对于支持虚拟主机的 Web 服务器(如 Apache 和 Nginx),可以通过配置虚拟主机来实现子域名的指向。

    以 Nginx 为例,你需要在服务器配置文件中添加一个新的服务器块(server block)。假设你的主域名是website.com,要为用户username设置子域名路由,配置可能如下:

    server {
        listen       80;
        server_name  username.website.com;
        # 以下是实际指向的路径,例如指向用户主页的目录
        location / {
            root   /var/www/username_homepage;
            index  index.html;
        }
    }

    这就将username.website.com这个子域名请求指向了/var/www/username_homepage这个服务器上的目录,当用户访问该子域名时,服务器会从这个目录中寻找并返回相应的网页文件。

    域名系统(DNS)配置

    要使用username.website.com这样的子域名,还需要在域名系统(DNS)中进行正确的配置。你需要添加一条CNAME(规范名称)记录或者A记录(如果是直接指向IP地址)来将子域名指向你的服务器。

    如果你的网站是通过域名注册商管理的,你可以登录到域名管理控制台,在DNS设置区域添加相应的记录。例如,添加一个CNAME记录,将username.website.com指向website.com(假设website.com已经正确配置指向服务器的IP地址),或者直接添加A记录,将username.website.com指向服务器的实际IP地址。

    应用程序路由逻辑

    在网页程序内部,你需要根据请求的子域名来确定对应的路由逻辑。例如,在后端应用程序(如使用Python的Flask或Django等框架)中,需要编写代码来识别子域名部分,并根据不同的username加载相应的用户主页内容。

    在Flask中,你可以使用request对象来获取请求的子域名信息,如下所示:

       from flask import Flask, request
       app = Flask(__name__)
       @app.route('/')
       def user_homepage():
           subdomain = request.headers.get('Host').split('.')[0]
           # 根据子域名subdomain(也就是username)加载对应的用户主页内容
           # 这里只是示例,实际可能需要查询数据库等操作
           return f"Welcome to the homepage of {subdomain}"

    注意事项

    • 安全性:确保在处理子域名请求时,进行适当的安全验证。例如,防止恶意用户通过构造虚假的子域名来访问未授权的内容或者进行攻击。可以通过验证用户身份、检查子域名是否在合法的用户列表中等方式来增强安全性。
    • 性能和维护成本:使用大量的子域名可能会增加服务器配置的复杂性和维护成本。每次添加新的子域名都需要在服务器和 DNS 中进行配置,并且需要确保应用程序能够正确处理这些子域名请求。此外,过多的子域名可能会对服务器性能产生一定的影响,尤其是在处理大量并发请求时。
    • 兼容性:有些浏览器或者网络环境可能对某些子域名设置有特殊的限制或者兼容性问题。在部署使用子域名的路由之前,最好进行充分的测试,以确保在各种主流设备和浏览器上都能正常工作。
    • 一些需要保留的用户名或者分层进行路由处理。例如典型的www用户名,可能会使用户主页引向产品首页。还有比如github的security 用户,你打开他的主页就会跳转到 github.com/security 的页面。此外gitee也有类似的问题。

    所以在设置用户路由或者用户页面时,需要首先考虑到安全性,其次就是功能性,这种可能影响到内容使用和系统安全的操作,用户体验或许需要向后排一排。

  • 本地部署nexus3 搭建maven私服

    由于JFREG的一系列惊人操作,GITEE关闭maven功能,不得已,本地搭建以下maven服务。

    准备工作:JDK (如果你的设备存在JDK环境,请忽略这部分。)

    (更多…)

  • Android Studio console 输出乱码解决

    打开 Edit Custom VM Options ,打开方法有两种

    1.双击shift键,输入ECVO或者Edit Custom VM Options

    2024-12-13T03:33:02.png

    2.或者手动打开用户名/AppData/Roaming/Google/AndroidStudiox.x/studio64.exe.vmoptions
    然后把-Dfile.encoding=UTF-8添加进去

    重启Android Studio即可

  • Android 的 v-a/b分区简单理解

    基础理解

    我们可以直接把v-a/b分区理解成,当你在使用手机,进行系统升级,系统会把升级内容存放在A分区,你继续使用B分区,前面的V就是虚拟的意思(virtual)。在尽量不影响你使用的开机情况下进行升级,取消了在rec分区进行升级的复杂操作

    (更多…)

  • 培养欣赏艺术的能力

    在人类文明的长河中,艺术宛如一颗璀璨的明珠,闪耀着无尽的魅力。它以多样的形式存在于我们的生活周围,从绘画中绚丽的色彩与独特的构图,到音乐里动人的旋律与和谐的节奏;从雕塑那立体的造型与质感的呈现,到文学作品中深刻的思想与精妙的文字表达。然而,若想真正领略艺术的深邃内涵与独特价值,培养欣赏艺术的能力则显得尤为重要。

    培养欣赏艺术的能力,首先要学会用心去感受。艺术作品并非仅仅是一些外在形式的简单组合,它蕴含着创作者的情感、思想与灵魂。当我们面对一幅画作时,不能仅仅看到画面上的人物、风景或物体,而应尝试去体会画家在创作时的心境。比如梵高的《向日葵》,那热烈奔放的色彩,看似只是对向日葵的描绘,但其中却倾注了梵高对生命的热爱与渴望。他以一种近乎癫狂的笔触和浓烈的色彩,将内心深处对美好生活的向往以及自身的孤独与挣扎都融入其中。我们只有静下心来,用心去感受那色彩背后的情感力量,才能触及到作品的灵魂深处,体会到艺术所带来的震撼与感动。

    丰富的知识储备是培养欣赏艺术能力的重要基石。了解艺术史、不同艺术流派的特点以及艺术家的生平经历等知识,能够为我们打开一扇深入理解艺术作品的大门。例如,在欣赏古典音乐时,如果我们对巴洛克时期、古典主义时期和浪漫主义时期音乐的风格特点有所了解,对莫扎特、贝多芬等音乐家的创作背景和个人经历有所知晓,那么当我们聆听他们的作品时,就能更好地理解音乐中所运用的创作手法、表达的情感主题以及所具有的时代特征。对于绘画艺术也是如此,熟悉文艺复兴时期、印象派、现代派等不同流派的发展脉络和核心主张,能够帮助我们更精准地解读一幅画作在艺术史上的地位和意义,明白画家为何采用这样的表现形式,从而提升我们欣赏艺术作品的深度和广度。

    培养敏锐的观察力是欣赏艺术不可或缺的环节。艺术作品中的每一个细节都可能蕴含着创作者的巧思与深意。在欣赏一幅精美的刺绣作品时,那细腻的针法、丰富的色彩过渡以及图案中微小的装饰元素,都值得我们仔细品味。同样,在阅读一部文学作品时,对字词的运用、段落的结构安排、情节的微妙转折等细节的留意,能够让我们更深刻地理解作者的创作意图。以《红楼梦》为例,书中对人物服饰、饮食、住所等细节的描写极为细致入微,这些细节不仅生动地展现了当时的社会风貌和贵族生活场景,更从侧面反映了人物的性格特点、身份地位以及命运走向。通过对这些细节的观察与分析,我们仿佛能够穿越时空,走进那个封建大家族的兴衰沉浮之中,感受到文学艺术的强大魅力。

    保持开放包容的心态对于培养欣赏艺术的能力同样至关重要。艺术是多元的,不同的文化背景、地域特色以及时代发展都会孕育出风格迥异的艺术形式和作品。我们不能以自己固有的审美观念去评判一切艺术,而应尊重和接纳各种艺术表达。现代艺术中的一些作品可能会打破传统的艺术观念和表现形式,让很多人一时难以理解。例如,某些抽象艺术作品,画面上可能只是一些看似随意的线条、形状和色彩的组合,但这并不意味着它们毫无价值。这些作品往往是艺术家对内心世界、社会现象或哲学思考的独特表达,它们挑战着我们的常规认知,促使我们重新审视艺术的定义和边界。只有以开放包容的心态去面对这些多元的艺术形式,我们才能不断拓宽自己的艺术视野,发现更多艺术之美。

    培养欣赏艺术的能力是一个长期而丰富的过程,它需要我们用心去感受、用知识去武装、用敏锐的观察力去发现、用开放包容的心态去接纳。在这个过程中,我们不仅能够提升自己的审美素养和精神境界,更能在艺术的浩瀚海洋中畅游,领略人类文明所创造的无尽辉煌与美好。让我们积极地投身于艺术欣赏的实践中,不断培养和提升自己欣赏艺术的能力,使艺术成为我们生活中不可或缺的精神滋养源泉。


    Developing the ability to appreciate art

    Translated by poe.com

    In the long history of human civilization, art shines like a brilliant pearl, radiating endless charm. It exists in various forms around us, from the vivid colors and unique compositions of paintings to the enchanting melodies and harmonious rhythms of music; from the three-dimensional shapes and textures of sculptures to the profound ideas and exquisite expressions found in literature. However, to truly appreciate the profound connotations and unique value of art, it is particularly important to cultivate the ability to appreciate art.

    To cultivate the ability to appreciate art, one must first learn to feel with the heart. Artistic works are not merely simple combinations of external forms; they contain the emotions, thoughts, and souls of their creators. When we face a painting, we should not just see the figures, landscapes, or objects depicted but should try to experience the artist’s mindset during the creation. For example, in Van Gogh’s “Sunflowers,” the vibrant and passionate colors seem to merely depict sunflowers, yet they are infused with Van Gogh’s love and yearning for life. With a near-manic brushstroke and intense colors, he integrates his deep longing for a beautiful life and his own loneliness and struggles. Only by calming our minds and feeling the emotional power behind the colors can we touch the soul of the work and experience the shock and emotion that art brings.

    A rich knowledge base is an important cornerstone for cultivating the ability to appreciate art. Understanding art history, the characteristics of different artistic movements, and the life experiences of artists can open a door to a deeper understanding of artistic works. For instance, when appreciating classical music, if we are familiar with the stylistic characteristics of Baroque, Classical, and Romantic music, and know about the backgrounds and personal experiences of composers like Mozart and Beethoven, we can better understand the creative techniques, emotional themes, and historical characteristics expressed in their works. The same applies to painting; being familiar with the development and core tenets of different movements such as the Renaissance, Impressionism, and Modernism can help us interpret a painting’s position and significance in art history and understand why the artist chose a particular form of expression, thereby enhancing our depth and breadth of art appreciation.

    Cultivating keen observation skills is an indispensable part of appreciating art. Every detail in an artwork may contain the creator’s ingenuity and deep meaning. When admiring a beautiful embroidery piece, the intricate stitching, rich color transitions, and small decorative elements in the pattern deserve our careful appreciation. Similarly, when reading a literary work, paying attention to the use of words, the arrangement of paragraphs, and the subtle shifts in plot can lead to a deeper understanding of the author’s intentions. For example, in “Dream of the Red Chamber,” the meticulous descriptions of characters’ clothing, food, and residences vividly depict the social landscape and aristocratic life of the time, while also reflecting the characters’ personalities, social status, and destinies. Through observing and analyzing these details, we seem to traverse time and space, stepping into the rise and fall of that feudal family, experiencing the powerful charm of literary art.

    Maintaining an open and inclusive mindset is equally crucial for cultivating the ability to appreciate art. Art is diverse; different cultural backgrounds, regional characteristics, and historical developments give birth to distinct artistic forms and works. We should not judge all art by our inherent aesthetic concepts but should respect and embrace various artistic expressions. Some works in modern art may challenge traditional art concepts and forms, making them difficult for many to understand at first. For example, certain abstract artworks may appear to be mere random combinations of lines, shapes, and colors, but that does not mean they lack value. These works often represent the artist’s unique expression of their inner world, social phenomena, or philosophical reflections; they challenge our conventional understanding and prompt us to reconsider the definitions and boundaries of art. Only by approaching these diverse forms of art with an open and inclusive mindset can we continually broaden our artistic horizons and discover more beauty in art.

    Cultivating the ability to appreciate art is a long and enriching process that requires us to feel deeply, arm ourselves with knowledge, discover through keen observation, and accept with an open heart. Through this process, we can not only enhance our aesthetic literacy and spiritual realm but also sail through the vast ocean of art, experiencing the endless brilliance and beauty created by human civilization. Let us actively engage in the practice of art appreciation, continually cultivating and enhancing our ability to appreciate art, making it an indispensable source of spiritual nourishment in our lives.

  • 一行代码没写,我通过ai搭建了个网站

    收藏夹是我强行称呼的。其实就是一个列表。你可以访问 linkpark.site 。实现效果如下:

    _20241207133002.png

    实现的效果:

    1. 读取我手动维护的静态文件(markdown文件)来生成网页列表
    2. 列表搜索
    3. 随机跳转某个Link的按钮
    4. 在随机列表获取一张图片作为背景图
    5. 获取到背景图的主要颜色设置为按钮的配色

    如果你对这个内容有兴趣,你可以参考一下下面的代码:

    <!DOCTYPE html>
    <html lang="zh">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>LINKPARK.SITE</title>
    <link rel="icon" href="./icon.png">
    <style>
            body {
                font-family:  "Ubuntu","Noto Sans SC",sans-serif;
                background-color: #f4f4f4;
                margin: 0;
                display: flex;
                justify-content: center;
                align-items: center;
            }
            .container {
                max-width: 800px;
                background-color: rgba(255, 255, 255, 0.1);
                border-radius: 12px;
                backdrop-filter: blur(10px);
                padding: 30px;
                margin: 0;
            }
            h1 {
                text-align: center;
                color: #333;
                margin-bottom: 10px;
            }
            input[type="text"] {
                box-sizing: border-box;
                width: 100%; 
                padding: 12px;
                border: 1px solid #ccc;
                border-radius: 6px;
                margin: 0 auto 20px; 
                font-size: 16px;
                display: block; 
                transition: border-color 0.3s;
            }
            input[type="text"]:focus {
                border-color: #555;
                outline: none;
            }
            .button-container {
            border: medium; /* 去掉边框 */
            border-radius: 4px;
            background-color: #EEEEEE; 
            display: flex;
            justify-content: space-between;
            margin-bottom: 20px;
            color: #fff;
            }
            button {
            flex: 1; /* 使按钮平分可用空间 */
            margin:  10px; /* 添加左右间距 */
            padding: 10px;
            color: #fff; /* 按钮文字颜色 */
            border: none; /* 去掉边框 */
            border-radius: 4px; /* 圆角边框 */
            cursor: pointer; /* 鼠标悬停时变成手指图标 */
            transition: background-color 0.3s; /* 添加过渡效果 */
            }
            button:hover {
            background-color: #0056b3; /* 悬停时变色 */
            color: #fff;
            }
            ul {
                list-style-type: none;
                padding: 0;
            }
            li {
                display: flex;
                flex-direction: column;
                position: relative;
                overflow: hidden;
                margin: 10px 0;
                border-radius: 6px;
                background-color: #f9f9f9; 
                transition: background-color 0.3s, transform 0.3s;
                padding: 15px;
                box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
            }
            li:hover {
                background-color: #eeeeee;
                transform: translateY(-2px);
            }
            img {
                width: 20px; 
                height: 20px; 
                margin-right: 10px; 
            }
            .subtitle {
                color: #888; 
                font-size: 14px; 
                margin-top: 5px; 
            }
            .title {
                font-size: 18px;
                font-weight: 600;
            }
            a {
                text-decoration: none;
                color: inherit;
                display: block; 
                height: 100%; 
            }
            @media (min-width: 768px) {
                .container {
                    margin: 5vh 0; 
                }
            }
        </style>
    <script type="module" src="https://linkpark.site/markdown.js" onload="loadMarkdown()"></script>
    </head>
    <body>
    <div class="container">
    <h1>linkpark<span style="color:#007bff">.</span>site</h1>
    <p style="color:#333;padding: 5px;word-break: break-all; font-size:12px">本页面为个人收藏列表页。从未有意冒用各网站商标,如果您认为您的内容或权益受到侵犯,请联系 m@linkpark.site 。本页面不收集任何信息。</p>
    <input type="text" id="search" placeholder="搜索列表项..." oninput="filterList()">
    <!-- 按钮容器 -->
    <div class="button-container">
    <button onclick="setSearchValue('划水')">划水</button>
    <button onclick="setSearchValue('设计')">设计</button>
    <button onclick="setSearchValue('ai')">ai</button>
    <button onclick="setSearchValue('开发')">开发</button>
    <button id="randomButton">无聊</button>
    </div>
    
    <hr style="border-style: dashed; border-color: #ccc;">
    <ul id="itemList"></ul>
    </div>
    
    <canvas id="colorCanvas" style="display:none;"></canvas>
    
    <script>
        
        async function loadMarkdown() {
        try {
            const response = await fetch('https://linkpark.site/links.md');
            if (!response.ok) {
                throw new Error('网络响应不是 OK');
            }
            const text = await response.text();
            const html = marked.parse(text);
            
            const container = document.createElement('div');
            container.innerHTML = html;
    
            const table = container.querySelector('table');
            const itemList = document.getElementById('itemList');
            itemList.innerHTML = '';
    
            if (table) {
                const rows = table.querySelectorAll('tr');
    
                for (let i = 1; i < rows.length; i++) {
                    const cols = rows[i].querySelectorAll('td');
                    if (cols.length >= 4) {
                        const imgSrc = cols[0].querySelector('img')?.src; 
                        const title = cols[1].innerText; 
                        const description = cols[2].innerText; 
                        const link = cols[3].querySelector('a')?.href; 
    
                        // 将 <a> 标签放在 <li> 标签外部
                        const newLi = document.createElement('li');
                        newLi.innerHTML = `
                                <div style="display: flex; align-items: center;">
                                    <img src="${imgSrc}" alt="icon">
                                    <span class="title">${title}</span>
                                </div>
                            <div class="subtitle">${description}</div>
                        `;
                        
                        // 创建链接并将其包裹在 <li> 外部
                        const anchor = document.createElement('a');
                        anchor.href = link;
                        anchor.appendChild(newLi);
                        itemList.appendChild(anchor);
                    }
                }
            }
        } catch (error) {
            console.error('加载 Markdown 失败:', error);
        }
    }
    
    
    function filterList() {
        const searchInput = document.getElementById('search').value.toLowerCase();
        const items = document.querySelectorAll('#itemList li');
    
        items.forEach(item => {
            const text = item.textContent.toLowerCase();
            item.style.display = text.includes(searchInput) ? '' : 'none';
        });
    }
    
    // 设置搜索框的值
    function setSearchValue(value) {
        document.getElementById('search').value = value;
        filterList(); // 更新过滤列表
    }
    
    function redirectTo(url) {
        window.location.href = url;
    }
    
            // 图片链接列表
            const imageUrls = [
                'https://linkpark.site/1.jpg',
                'https://linkpark.site/2.jpg',
                'https://linkpark.site/3.jpg',
                'https://linkpark.site/4.jpg',
                'https://linkpark.site/5.jpg',
                'https://linkpark.site/6.jpg',
                'https://linkpark.site/7.jpg',
                'https://linkpark.site/8.jpg',
                'https://linkpark.site/9.jpg',
                'https://linkpark.site/10.jpg'
            ];
    
            // 随机选择一个链接
            const randomImageUrl = imageUrls[Math.floor(Math.random() * imageUrls.length)];
            document.body.style.background = `url('${randomImageUrl}') no-repeat center center fixed`;
            document.body.style.backgroundSize = 'cover'; // 让背景图覆盖整个屏幕
    
            const canvas = document.getElementById('colorCanvas');
            const ctx = canvas.getContext('2d');
    
            function getDominantColor(image) {
                const width = image.width;
                const height = image.height;
                canvas.width = width;
                canvas.height = height;
                ctx.drawImage(image, 0, 0, width, height);
    
                const imageData = ctx.getImageData(0, 0, width, height);
                const data = imageData.data;
    
                let r = 0, g = 0, b = 0, count = 0;
    
                for (let i = 0; i < data.length; i += 4) {
                    r += data[i];     // Red
                    g += data[i + 1]; // Green
                    b += data[i + 2]; // Blue
                    count++;
                }
    
                r = Math.floor(r / count);
                g = Math.floor(g / count);
                b = Math.floor(b / count);
    
                return `rgb(${r}, ${g}, ${b})`;
            }
    
            const img = new Image();
            img.crossOrigin = "Anonymous"; // 解决跨域问题
            img.src = randomImageUrl; // 使用随机选择的图片链接
            img.onload = () => {
                const dominantColor = getDominantColor(img);
                document.querySelectorAll('button').forEach(button => {
                    button.style.backgroundColor = dominantColor; // 设置按钮背景色
                    button.style.color = '#ffffff'; // 设置按钮文字颜色为白色
                });
            };
    </script>
    <script type="module" src="https://linkpark.site/linkpark.js""></script>
    </body>
    </html>