分类: 主题

  • 如何为wordpress的文章添加阅读量

    要在 WordPress 上实现文章阅读统计(跟踪每篇文章的阅读次数或页面浏览量),可以借助插件或自定义代码。以下是几种常见的方法和工具,如果使用代码请注意文章内容。

    方法一:使用插件实现文章阅读统计

    1. MonsterInsights
      • MonsterInsights 是最受欢迎的 Google Analytics 插件之一,可以直接在 WordPress 仪表板中查看每篇文章的页面浏览量、访客行为、跳出率等数据。通过其 Page Insights 扩展,还可以查看单篇文章的详细统计(如页面浏览量、停留时间等)。必须绑定GA。
    2. WP Statistics
      • WP Statistics 是一个隐私友好的分析插件,符合 GDPR 要求,无需外部账户,直接在 WordPress 数据库中存储数据。它可以跟踪每篇文章的访问量,并提供详细的图表和分类分析。不过最顶上那个评论似乎说明了一些问题,我没尝试这个插件,观望一下。
    3. Post Views Counter
      • 一个轻量级插件,专门用于显示文章、页面或自定义内容的浏览次数。它支持通过 PHP、JavaScript 或 REST API 跟踪数据,并允许自定义计数器的显示位置和样式。
    4. Jetpack Stats
      • Jetpack 的统计模块提供文章的浏览量、热门内容、流量来源等数据,适合 WordPress.com 用户或安装了 Jetpack 的自托管站点。免费用户可查看过去 7 天的统计,付费计划解锁更多功能。
    5. Independent Analytics
      • 一个专为 WordPress 设计的免费分析插件,加载速度快,符合 GDPR。它可以自动记录文章的访问量,并按类别显示统计数据。
    6. 如果你恰好财力雄厚,你可以使用一些主题的pro版本自带的功能
      • 这里就不对赘述了,例如我使用的blocksy主题,在设置页面左侧点击blocksy,设置中文章元数据打开显示即可。

    方法二:插件之短码插件(推荐)

    1. Post Views for Jetpack
      • 提供短码,可以在文章、页面或小工具中显示各种统计数据。以下部分代码复制于这个插件的讨论区: https://wordpress.org/support/topic/way-to-display-views-in-blocksy-post-meta/

    这个插件如何在blocksy中使用?请在你的function.php中添加以下代码 (注意把[sbs_views] 修改为你上面短码插件中约定的短码):

    add_filter( 'blocksy:archive:render-card-layer', function ( $output, $single_component) {
    	if ( 'post_meta' !== $single_component['id'] ) {
    		return $output;
    	}
    	$post_views = do_shortcode( '[sbs_views]' );
    
    	$output = str_replace( '</li></ul>', '</li><li class="post-views">' . $post_views . '</li></ul>', $output );
    	return $output;
    }, 11, 2 );

    方法三:自定义代码实现阅读统计

    在你的主题的function.php中添加以下代码:

    // 记录文章浏览量
    function set_post_views($postID) {
        $count_key = 'post_views_count';
        $count = get_post_meta($postID, $count_key, true);
        if ($count == '') {
            $count = 0;
            delete_post_meta($postID, $count_key);
            add_post_meta($postID, $count_key, '0');
        } else {
            $count++;
            update_post_meta($postID, $count_key, $count);
        }
    }
    
    // 在单篇文章页面记录浏览量
    function track_post_views($postID) {
        if (!is_single()) return;
        if (empty($postID)) {
            global $post;
            $postID = $post->ID;
        }
        set_post_views($postID);
    }
    add_action('wp_head', 'track_post_views');
    
    // 显示文章浏览量
    function get_post_views($postID) {
        $count_key = 'post_views_count';
        $count = get_post_meta($postID, $count_key, true);
        if ($count == '') {
            delete_post_meta($postID, $count_key);
            add_post_meta($postID, $count_key, '0');
            return "0 Views";
        }
        return $count . ' Views';
    }

    在需要使用的地方添加:

    echo get_post_views(get_the_ID());

    如果需要在blocksy主题中使用:

    add_filter( 'blocksy:archive:render-card-layer', function ( $output, $single_component ) {
        if ( 'post_meta' !== $single_component['id'] ) {
            return $output;
        }
    
        $output = str_replace( '</li></ul>', '</li><li class="post-views">' . get_post_views(get_the_ID()) . '</li></ul>', $output );
        return $output;
    }, 10, 2 );

    注意上面所有的代码部分,可能会造成不可回溯的内容。

    部分可能会在你数据库的前缀_postmeta表中创建很多key为post_views_count 的数据,介意的话可以使用第三方插件或者自己手动修改。另外注意,有的主题不允许修改functions.php的代码,你复制代码保存失败时,可以按 ctrl+ shift + v 粘贴。

  • 从Typecho安全平移到WordPress

    这里不比较Typecho与Wordpress的好坏。实际上优缺点都很明显。但如果你没有其他想法,只是想单纯写写内容,Notebook才是最棒的选择。我只是想把加的各位朋友的友链放在除了友链页以外的其他页面,那貌似只能放在sidebar了,所以选择了一个双栏的杂志主题。后来想了想,直接换wordpress得了。

    1. 导出数据

    数据导出当然使用的是ByTyp,但是我记得之前第一次安装是有什么问题的,貌似是PHP版本不对还是什么东西,忘记了,不过我记得我修改了一些东西。如果你会有这个问题并且你发现搜索不到解决方案,你可以点下面的按钮下载我的备份:

    2. 备份

    备份你需要做以下备份

    • 下载Typecho的所有文件内容
    • 下载Typecho的数据库备份文件
    • 尝试新建数据库并导入数据库备份文件查看是否可以导入
    • 使用Typecho的备份功能下载备份文件
    • 检查以上备份

    3. 安装Wordpress和导入数据

    因为我后端使用的是宝塔,所以有一键部署。我的域名是banzhuanriji.com,我新建的网站绑定的域名为abc(这里你自己设置).banzhuanriji.com,然后所有的操作都是在这个网站上进行的。

    工具-导入-立即安装,安装完成后会显示【运行导入器】,然后选择上面ByTyp导出的文件即可,选择接受用户即可。

    4. 修改域名

    1. 检查上面的备份内容
    2. wordpress后台,设置-常规:WordPress 地址(URL)和 站点地址(URL)修改为你的地址
    3. 修改网站文件夹名称,也就是删除原来的 banzhuanriji.com,把abc.banzhuangriji.com,修改为banzhuanriji.com
    4. 重启Nginx

    5. 安装需要的插件

    我是所有都设置好之后才修改域名的,现在我点击主题的自定义,就会先显示几条错误提示,再显示自定义网页页面。错误内容如下:

    
    Warning: Undefined array key "mp_featuredimg_1" in /www/wwwroot/banzhuanriji.com/wp-includes/class-wp-customize-widgets.php on line 1130
    
    Warning: Trying to access array offset on value of type null in /www/wwwroot/banzhuanriji.com/wp-includes/class-wp-customize-widgets.php on line 1130
    
    Warning: Undefined array key "mp_featuredimg_1" in /www/wwwroot/banzhuanriji.com/wp-includes/class-wp-customize-widgets.php on line 1131
    
    Warning: Trying to access array offset on value of type null in /www/wwwroot/banzhuanriji.com/wp-includes/class-wp-customize-widgets.php on line 1131
    
    Warning: Undefined array key "mp_featuredimg_1" in /www/wwwroot/banzhuanriji.com/wp-includes/class-wp-customize-widgets.php on line 603
    
    Warning: Trying to access array offset on value of type null in /www/wwwroot/banzhuanriji.com/wp-includes/class-wp-customize-widgets.php on line 603

    貌似是Blocky插件的问题,到现在我都不知道怎么解决…

    6. 其他

    关于安装的插件和主题,有兴趣的话可以查看关于页面。

    如果你没有想使用Wordpress,那么我推荐你使用Tp2MD,可以导出到Markdown文件,你经过简单的修改可以直接在一些hexo,hugo,nextjs或者astro等可以使用Markdown文件的博客系统。

  • 一些免费的图床整理和对比

    因为我有SM.MS账号,所以一直是登录使用。最近才发现SM.MS禁止了游客上传图像,今天试的imgdd上传出现了问题。正好闲来无事整理一下现在可用的免费图床。

    图像处理:

    https://ic.yunimg.cc/

    可选择多种文件尺寸和图像质量,并可在线预览对比图像质量后保存。

    https://imagestool.com/webp2jpg-online/

    几乎全能图像在线转换压缩处理工具

    图床

    以下为图床列表,示例图片文件大小为1.01Mb左右(1041 kb,1065532 字节),你可以按F12,在开发人员工具中选择网络-停用缓存,然后按F5刷新页面,查看图片下载速度。

    只做收集使用,没有任何利益关系。请注意备份您的数据

    (更多…)

  • 冷饭加鸡肋,越炒越无味

    2025年3月14日更新:

    没想到ruanyifeng这周和我写一个话题的内容。

    https://www.ruanyifeng.com/blog/2025/03/weekly-issue-341.html

    TL;DR

    我不认为低代码平台+ai会变香


    最近在 X 上又刷到有人吹低代码平台,说它“未来可期”。作为一个写了十几年代码的老程序员,我实在忍不住想吐槽。2025 年 3 月的今天,低代码仍然在炒,但我怎么看都觉得它像个老掉牙的故事——多年前就有人做过,有人退场,活下来的也没多风光。开发者真要为它担心失业?我看未必。

    低代码的炒作历史

    低代码并不新鲜。十年前就有一堆“零代码”“低代码”平台冒出来,喊着“拖拖拽拽就能做应用”。OutSystems、Mendix 这类老面孔仍在,国内也涌现了不少平台,但看看,有多少已经悄无声息地退出了市场?活下来的,像 Appian 或者钉钉宜搭,日子也不算滋润。我认识一哥们儿用低代码搭了个库存系统,业务一调整就改不动,最后还是找我重写。

    根据Gartner 2024年报告,全球低代码市场规模增速已从2021年的23.6%下降至7.2%

    Forrester 报告中的结论:低代码项目平均维护成本比传统开发高 2.3 倍。

    AI的加入与现实

    最近,低代码平台开始加入 AI,宣传上功能似乎变强了,能自动生成 UI、调优逻辑等。听起来很吸引人,但我一想,这不扯吗?“好用”不是一开始就该有的吗?AI 是新添的没错,但作为一个开发工具,基础功能好用才是最基本的要求。加了 AI 就吹得天花乱坠,好像以前不好用是理所当然似的。更别提 AI 生成的内容,改起来还是老样子——要么直接用,要么手动调整,跟十年前改代码没啥两样。AI 救不了低代码的命,最多也就是个噱头。

    对开发者的影响

    有人说低代码抢初级开发者的饭碗。确实,简单的表单和内部工具能拖几下搞定,初级程序员可能有点压力。但对我这种习惯复杂逻辑的人来说,低代码根本动不了我。那些“80% 简单需求”它能凑合,剩下 20% 的高性能、高定制化活儿,还得靠我们。

    低代码还老给我添乱。客户用它搞个半成品,跑来让我修 bug、调性能,比从头写还费劲。我见过公司拿低代码做了个原型,上线后卡得要死,最后还得重构。省了点时间,却留下一堆烂摊子,这算啥“革命”啊?

    收费模式的高数题

    再说说低代码的收费模式,真是让人无语。免费版的基础功能弱得可怜,比如最多建几个表、连个像样的 API 都不行,想干点正事儿就得掏钱。收费功能层级森严,基本每个平台都有“基础版”“专业版”“企业版”之类的分级,价格一级比一级离谱。举个例子,我试过一个平台,免费版连导出数据都不行,想加个自定义插件,得升到每月几百块的专业版。更别提什么“无限用户”“高级支持”了,全锁在最贵的套餐里。这哪是工具啊,简直是圈钱的套路机器。

    未来?别指望它翻天

    低代码的粉丝总爱说未来会更智能,靠 AI 翻身。我听了只想笑。AI 是牛,但低代码加了 AI 就能写分布式系统?能优化算法?我看悬。这么多年,低代码的套路我都看透了:炒一波概念,忽悠一波企业用户,然后慢慢淡出视线。活下来的,要么靠大厂撑腰(比如微软的 Power Apps),要么苟在小众市场,风光不到哪去。

    什么“低代码 + 传统开发共存”的说法,我也懒得信。企业用低代码无非图快图便宜,可业务一复杂,它就成鸡肋,重写成本还更高。我宁可从头写个扎实的系统,省得回头返工。

    结论:低代码的未来

    在我眼里,低代码就是个“伪命题”。炒了这么多年,没真干掉谁,也没见哪个平台成了行业霸主。加个 AI 也救不了它,免费功能鸡肋,收费还一套一套的。开发者要失业?除非你只会写“Hello World”。对我来说,低代码顶多是个玩具,玩玩行,想靠它吃饭,我看悬。

    所以,别被低代码的宣传唬住了。想在这行混好,还是老老实实练功——算法、架构、DevOps,这些真本事才是我们的护身符。低代码?让它继续炒吧,我码我的代码。

  • 在final中添加评论

    一,创建文件

    下面的文件均创建在主题文件夹中。

    1. 创建样式代码 comments.css (你可以把下面的内容放到style.css中)

    .comment-container form{
        border: 0px;
        padding: 20px;
        border-radius: 10px;
        margin-top: 20px;
        margin-bottom: 20px;
        background-color: #f0f0f0;
    }
    
    .clearfix::after {
        content: "";
        display: table;
        clear: both;
    }
    
    #comments {
        list-style-type: none;
        padding: 0;
    }
    
    .comment-body {
        padding: 15px 20px;
        list-style-type: none!important;
        border-radius: 10px;
        margin: 2.5rem 0px;
        background-color: #f0f0f0;
    }
    
    .comment-header {
        display: flex;
        align-items: center;
        margin-bottom: 10px;
    }
    
    .avatar {
        height: 2.5rem;
        width: 2.5rem;
        border-radius: 50%;
        margin-right: 10px;
    }
    
    .comment-author {
        font-weight: bold;
        color: #333;
    }
    
    .comment-by-author {
        color: #007bff;
    }
    
    .comment-by-user {
        color: #28a745;
    }
    
    .comment-content {
        background-color: #f0f0f0;
        border-radius: 10px;
        padding: 5px 20px;
        background-color: #fefefe;
        margin-bottom: 10px;
    }
    
    .comment-meta {
        font-size: 0.8em;
        color: #888;
    }
    
    .comment-reply {
        cursor: pointer;
        color: #007bff;
    }
    .comment-reply:hover {
        text-decoration: underline;
    }
    
    .comment-child {
        margin-left: 30px;
    }
    
    .comment-list{
        padding: 0px;
        margin: 20px 0px 0px 0px;
        font-size: 0.9rem;
    }
    
    .form-control {
        width: 100%;
        padding: 15px;
        margin-bottom: 20px;
        border: 0px;
        background-color: #fefefe;
        box-sizing: border-box;
    }
    
    .submit {
      color: #090909;
      padding: 0.7em 1.7em;
      font-size: 18px;
      border-radius: 0.5em;
      width: 100%;
      background: #ffffff;
      cursor: pointer;
      border: 0;
    }
    
    .response {
        color: #888;
    }
    
    .lists-navigator {
        text-align: center;
        margin-top: 20px;
    }
    
    textarea {
        height: 10rem; 
        resize: none; 
        outline: none; 
    }
    
    form input,form textarea{
        font-family: 'Noto Sans SC',consolas,monospace;
        font-size: 0.8rem;
        border-radius: 10px;
        background: #ffffff;
    }

    创建 comments.php

    1. 以下为我的代码,请注意第一行的引用代码。引用的样式代码为上面的CSS样式.

    如果你已经放置到style.css中,你可以删除下面代码的第一行代码。

    如果你已经创建css文件,直接复制下面的内容即可。

    <link rel="stylesheet" href="/usr/themes/final/comments.css">
    <hr>
    <h3>评论</h3>
    <?php
    function threadedComments($comments, $options) {
        $commentClass = '';
        if ($comments->authorId) {
            if ($comments->authorId == $comments->ownerId) {
                $commentClass .= ' comment-by-author';
            } else {
                $commentClass .= ' comment-by-user';
            }
        }
    
        $commentLevelClass = $comments->levels > 0 ? ' comment-child' : ' comment-parent';
        $depth = $comments->levels +1;
    
        if ($comments->url) {
            $author = '<a href="' . $comments->url . '"target="_blank"' . ' rel="external nofollow">' . $comments->author . '</a>';
        } else {
            $author = $comments->author;
        }
    ?>
    
    <li id="li-<?php $comments->theId(); ?>" class="comment-body<?php
    if ($depth > 1 && $depth < 3) {
        echo ' comment-child ';
        $comments->levelsAlt('comment-level-odd', ' comment-level-even');
    }
    else if( $depth > 2){
        echo ' comment-child2';
        $comments->levelsAlt(' comment-level-odd', ' comment-level-even');
    }
    else {
        echo ' comment-parent';
    }
    $comments->alt(' comment-odd', ' comment-even');
    ?>">
        <div id="<?php $comments->theId(); ?>">
            <?php
                $host = 'https://gravatar.loli.net';
                $url = '/avatar/';
                $size = '80';
                $default = 'mm';
                $rating = Helper::options()->commentsAvatarRating;
                $hash = md5(strtolower($comments->mail));
                $avatar = $host . $url . $hash . '?s=' . $size . '&r=' . $rating . '&d=' . $default;
            ?>
            <div class="comment-view" onclick="">
                <div class="comment-header">
                    <img class="avatar" src="<?php echo $avatar ?>" width="<?php echo $size ?>" height="<?php echo $size ?>" />
                    <div style="display: grid;">
                        <span class="comment-author<?php echo $commentClass; ?>"><?php echo $author; ?></span>
                        <time class="comment-time"><?php $comments->date('Y-M-j'); ?></time>
                    </div>
                </div>
                <div class="comment-content"> <?php $comments->content(); ?></p>
                </div>
                <div class="comment-meta">
                    <span class="comment-reply" data-no-instant><?php $comments->reply('Reply'); ?></span>
                </div>
            </div>
        </div>
        <?php if ($comments->children) { ?>
            <div class="comment-children">
                <?php $comments->threadedComments($options); ?>
            </div>
        <?php } ?>
    </li>
    <?php } ?>
    
    <div id="<?php $this->respondId(); ?>" class="comment-container">
        <div id="comments" class="clearfix">
            <?php $this->comments()->to($comments); ?>
            <?php if($this->allow('comment')): ?>
            <form method="post" action="<?php $this->commentUrl() ?>" id="comment-form" class="comment-form" role="form" onsubmit ="getElementById('misubmit').disabled=true;return true;">
                <?php if(!$this->user->hasLogin()): ?>
                <div style="display: flex; gap: 10px;">
    
                <input type="text" name="author" maxlength="12" id="author" class="form-control input-control clearfix" placeholder="您的称谓(可选)" value="" required>
                
                <input type="url" name="url" id="url" class="form-control input-control clearfix" placeholder="站点地址(可选)" value="" <?php if ($this->options->commentsRequireURL): ?> required<?php endif; ?>>
                
                <input type="email" name="mail" id="mail" class="form-control input-control clearfix" placeholder="邮箱(可选)" value="" <?php if ($this->options->commentsRequireMail): ?> required<?php endif; ?>>
                
                </div>
                
                <?php endif; ?>
    
                <textarea name="text" id="textarea" class="form-control" placeholder="地址:https://banzhuanriji.com/
    标题/称呼:搬砖日记
    副标题/自我介绍:我的生活记录
    icon/头像:https://banzhuanriji.com/img/icon.svg (可选)" required ><?php $this->remember('text',false); ?></textarea>
    
                <button type="submit" class="submit" id="misubmit">提交你的友链/评论</button>
                <?php $security = $this->widget('Widget_Security'); ?>
                <input type="hidden" name="_" value="<?php echo $security->getToken($this->request->getReferer())?>">
            </form>
            <?php else : ?>
                <span class="response">评论区暂时被关闭了</span>
            <?php endif; ?>
    
            <?php if ($comments->have()): ?>
    
            <?php $comments->listComments(); ?>
    
            <div class="lists-navigator clearfix">
                <?php $comments->pageNav('←','→','2','...'); ?>
            </div>
    
            <?php endif; ?>
        </div>
    </div>

    二,使用

    在你需要的地方添加 <?php $this->need('comments.php'); ?>

  • 仿照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