搬砖日记 发布的文章

  • INTERNXT

https://internxt.com/temporary-email

  • TEMPAIL

https://tempail.com/

  • AdGuard Temp Mail

https://adguard.com/en/adguard-temp-mail/overview.html

  • Tempmail

https://temp-mail.io/en

  • Email on Deck

https://www.emailondeck.com/

  • TempMail.so

https://tempmail.so/

  • @mail.tm

https://mail.tm/en/

  • Temp Mail & 10 10 min mail

https://temp-mail.org/en/

https://temp-mail.org/en/10minutemail

  • Temp Mail

https://tempmailto.org/

  • guerrillamail

https://www.guerrillamail.com/

  • inboxes

https://inboxes.com/

TL;DR

通过vercel第三方库来运行php程序

效果展示

展示不了一点,我发现部署几天后开始变得非常卡,不知道为啥

所以我推荐你每天定时deploy一下,会好很多

一,注册需要的账号

你需要注册以下账号

  • github
  • vercel
  • 一个免费或者你自己搭建的mysql数据库
关于数据库,不推荐使用国内的免费数据库,因为vercel访问太慢了
或许你可以尝试db4free,或者一些免费空间提供的数据库

二,操作步骤

1. 创建git仓库

在github创建一个仓库,注意这个仓库需要是private的,也就是私密的仓库。然后clone到本地。下面为了方便,假设仓库名为blog

2. 下载typecho

下载地址:https://typecho.org/download

3. 把typecho解压到仓库文件夹内

此时文件应该存放在根目录

4. 新建api文件夹,然后在api文件夹下创建index.php文件

其中index.php文件的内容如下

<?php
$file= __DIR__ . '/..'.$_SERVER["PHP_SELF"];

if(file_exists($file))
{
   return false;
}
else
{
    require_once __DIR__ . '/../index.php';
}
#echo $_SERVER["PHP_SELF"];

5. 在仓库中创建vercel.json

内容如下

{
  "functions": {
    "api/index.php": {
      "runtime": "vercel-php@0.7.3"
    }
  },
  "routes": [{ "src": "/(.*)", "dest": "/api/index.php" }]
}

6. 在根目录创建config.inc.php

内容如下

<?php
/**
 * Typecho Blog Platform
 *
 * @copyright  Copyright (c) 2008 Typecho team (http://www.typecho.org)
 * @license    GNU General Public License 2.0
 * @version    $Id$
 */

/** 开启https */
define('__TYPECHO_SECURE__',true);

/** 定义根目录 */
define('__TYPECHO_ROOT_DIR__', dirname(__FILE__));

/** 定义插件目录(相对路径) */
define('__TYPECHO_PLUGIN_DIR__', '/usr/plugins');

/** 定义模板目录(相对路径) */
define('__TYPECHO_THEME_DIR__', '/usr/themes');

/** 后台路径(相对路径) */
define('__TYPECHO_ADMIN_DIR__', '/admin/');

/** 设置包含路径 */
@set_include_path(get_include_path() . PATH_SEPARATOR .
__TYPECHO_ROOT_DIR__ . '/var' . PATH_SEPARATOR .
__TYPECHO_ROOT_DIR__ . __TYPECHO_PLUGIN_DIR__);

/** 载入API支持 */
require_once 'Typecho/Common.php';

/** 程序初始化 */
Typecho_Common::init();

/** 定义数据库参数 */
$db = new Typecho_Db('Pdo_Mysql', 'typecho_');
$db->addServer(array (
  'host' => '数据库地址',
  'user' => '数据库用户',
  'password' => '数据库密码',
  'charset' => 'utf8mb4',
  'port' => '3306',
  'database' => '数据库名',
  'engine' => 'MyISAM',
), Typecho_Db::READ | Typecho_Db::WRITE);
Typecho_Db::set($db);

7. 注释掉会阻挡操作的内容

打开根目录下的install.php文件,注释或者删除773-775行,注释的内容大概如下。

    // if (!$writeable) {
        // $errors[] = _t('上传目录无法写入, 请手动将安装目录下的 %s 目录的权限设置为可写然后继续升级', $uploadDir);
    // }
这里如果没有删除,可能会无法初始化数据库

8. 上传代码,在vercel中编译,注意提前绑定域名

9. 第一次打开会报错

提示Database Query Error。这时你需要在你的域名||vercel提供的免费域名后添加/install.php,然后按照步骤操作。

这里如果你没有执行第7步的操作,可能会报错,建议修改之后重新提交

三,注意事项

  1. 过长的等待时间会触发vercel报错,提示This Serverless Function has timed out. 这时你或许可以考虑更换数据库
  2. 注意看第7点
  3. 一些函数官方说支持,但是会有奇怪的问题
  4. 上传二进制文件和直接修改文件的功能就别想了,在仓库中操作吧
  5. 暂时想不到了

Best Of 2024: Most Popular Movies

Best Of 2024: Most Popular TV Shows


电影

外文中文
1. Deadpool & Wolverine1. 死侍与金刚狼
2. Dune: Part Two2. 沙丘 2
3. Furiosa: A Mad Max Saga3. 疯狂的麦克斯:狂暴女神
4. Joker: Folie à Deux4. 小丑 2:双重妄想
5. Alien: Romulus5. 异形:夺命舰
6. The Substance6. 某种物质
7. Civil War7. 美国内战
8. Beetlejuice Beetlejuice8. 怪奇大法师
9. Kingdom of the Planet of the Apes9. 猩球崛起:新世界
10. Longlegs10. 长腿

电视剧

外文中文
1. True Detective1. 真探 第四季
2. The Boys2. 黑袍纠察队 第四季
3. The Penguin3. 企鹅人
4. Fallout4. 辐射
5. House of the Dragon5. 龙之家族 第二季
6. Shogun6. 幕府将军
7. Bridgerton7. 布里杰顿家族/布里奇顿
8. The Lord of the Rings: The Rings of Power8. 指环王:力量之戒
9. The Gentlemen9. 绅士们
10. 3 Body Problem10. 三体(Netflix 版)

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

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

你可以访问这里查看: 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>

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

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