为什么自己要写一个主题

一开始我是很排斥 WordPress 的,不过后面发现,WordPress 插件齐全而且主题极其丰富,除了后台访问速度慢真的没什么缺点。去年,多年不写代码的我手痒起来了,觉得为自己写一个只属于自己的主题应该很棒——于是我草草看完 PHP 文档就开始写了。WordPress 提供了很多 Hooks,所以在写主题时要实现某个功能很容易找到解决方案,这也是我觉得 WordPress 很棒的一点。

wordpress-973439_640

小站经历

这个小站去年就建好,然后被我扔着吃灰。直到上个月域名过期了,腾讯云打来电话取消我的备案我才想到还有这个小站的存在……只可惜已经晚了,我也懒得再备案了,于是把站迁移到了 $2.5 的 vultr 上,用了点奇淫技巧给 2.5美刀的小鸡上了 IPv4。我原本想继续使用 Docker 部署,后面发现宝塔面板真香!至于这个网站到底要拿来做什么,我写什么放上去,这都是后话,我只是单纯地想给自己写个博客主题,顺便敲敲代码过过瘾而已。

没有设计的苦恼

最开始我使用的是简单的线条分割的三栏式布局,略微支持所谓的响应式,写了不少媒体查询。本来这样就已经结束了,直到后来我开始关注移动端。我发现这种简单的线条分割的方式,在 PC 端看起来似乎勉强可以接受,只要图片和配色得当应该也还看得过去。但是在移动端,这种布局显得混乱不堪。文字过多,色彩过于喧宾夺主,以及缺少明确的区块分割等等问题在移动端完全暴露了出来。这时候我正在做夜间模式,发现夜间模式效果在移动端也非常的混乱。

screenshot

怎么办?只有改版了,所以怎么改?我做了很多尝试,最后只好求稳使用了大色块进行内容的分割,同时也用上了圆角矩形。背景颜色和高亮色也做了变换,不再使用红色作为高亮色(虽然我很喜欢红色),背景颜色做了略微加深。最后就成了这样!

Snipaste_2020-12-23_21-33-20

因为大色块和原本线条风格的 Header 完全不搭,只好重写 Header 的样式,导航的文字也由居中改成了居左。但是文字居左又带来一个问题,就是右边显得太空了。我头像是居中,下面的文字又居左,会显得不搭。于是我加了 hover 效果和右边的箭头图标。

不过,还没有完……

我决定再做一个横向 Header 效果,同时完善了一下夜间模式,防止审美疲劳,所以版面又成了这样。

Snipaste_2020-12-23_21-31-08

夜间模式变成了这样。

image-20201227095849287

完成的功能

1.页面

我自己完成了一个时间线页面,一个友链页面和关于页面。这3个页面是单独的文件,我不想让我主题每个页面都千篇一律的样子,所以单独拿出来写了。当然单独实现这些页面其实不复杂,只需要建立 page-about.php, page-timeline.php, page-friends.php 这些模板然后分开写就行了。比如说时间线页面:

image-20201227103419337

2.目录功能

目录功能是我很早已经就已经完成的了,由于没有好的参考,只好自己用遍历的方式在 Web 端实现。

interface catalogElement {
  el: HTMLElement | Element;
}
interface catalogReturns {
  length: number;
  [index:number] : { $1th: any, $2th: any}
}
function initCatalog(el:catalogElement['el']):catalogReturns {
  /**
   * 假定处理过后的hArr 如下:
   * [
   *    {tag: "h3", text: "一级1"},
   *    {tag: "h5", text: "二级1-1"},
   *    {tag: "h5", text: "二级1-2"}
   *    {tag: "h3", text: "一级2"},
   *    {tag: "h6", text: "二级2-1"},
   *    {tag: "h6", text: "二级2-2"},
   *    {tag: "h3", text: "一级3"},
   *    {tag: "h3", text: "一级4"}
   * ]
   *
   */
  if (!el) throw "el is not a HTMLElement";
  let hArr = [];
  let els;
  if (!el.querySelectorAll) {
      els = el.children;
  } else {
      els = el.querySelectorAll("h1, h2, h3, h4, h5, h6");
  }
  for (let i = 0; i < els.length; i++) {
      // 遍历所给元素el 的所有子节点中是标题标签的节点
      if (els[i].nodeType === 1 && /H\d/i.test(els[i].nodeName)) {
          // let name = els[i].getElementsByTagName('a')[0].getAttribute('name');
          let name = els[i].getAttribute('name');
          hArr.push({tag: els[i].nodeName.toLowerCase(), text: els[i].innerText, name: name, el: els[i]});
      }
  }
  if (hArr.length <= 0) {
      return []
  }
  let titles = []; // 存放目录的数组,包含1级和2级目录
  let level1tag = hArr[0].tag; // 第一次出现的h标签就是第一层标题对应的标签: 比如第一次出现的是<h3>
  let level2tag = '';          // 第二层级的标题对应的标签; 比如可能是任何大于h3的标签,如<h4>,<h5>,<h6>
  let $2th:any = []; // 二级标题数组
  for (let i = 0; i < hArr.length; i++) {
      let obj = { // 每一个第一级标题下面对应了一组第二级标题
          $1th: {}, // 第一级标题
          $2th: [] //  第二级标题
      };
      if (hArr[i].tag === level2tag) {
          $2th.push(hArr[i]); // 如果当前标题2级标题, 那么将该2级标题push 到 $2th, 并且跳过后面的代码;如果下一个标题还是2级标题, 则继续push并跳过
          hArr[i].el.classList.add('catalog-title');
          hArr[i].el.classList.add('ct-level2');
          continue
      } else if (hArr[i].tag === level1tag) {
          // 动态确定第二层标题对应的标签 level2Tag; 可能是任何大于<h3>的标签, 如h4, h5, h6
          for (let j = i + 1; j < hArr.length; j++) {
              if (hArr[j].tag > level1tag) {
                  level2tag = hArr[j].tag;
                  break
              }
          }
          obj.$1th = hArr[i];
          hArr[i].el.classList.add('catalog-title');
          hArr[i].el.classList.add('ct-level1');
          $2th = []; // 如果检测到1级的标题, 则置$2th 为空
      } else {
          // 第三级 及 深层次的目录标题直接忽略
          continue
      }
      obj.$2th = $2th;
      titles.push(obj);
  }
  return titles
}

3.为主题添加支持

我看很多主题在后台都可以自定义,我看着着实羡慕,于是自己也开始着手做了做。前面说到的 Hooks 在这里就很有用了,WordPress 真香!WordPress 提供了 add_theme_support的钩子函数,于是我参考文档用这个函数让主题支持了一些功能;包括:自定义Logo、缩略图支持、缩略图大小调整和自定义背景图片等

/**
 * 添加主题支持
 */
function theme_setup() {
    add_theme_support('custom-logo', array(
        'width'          => 500,
        'height'         => 500,
        'flex-width'     => false,
        'flex-height'    => false
    ));
    add_theme_support( 'post-thumbnails', array('post'));
    add_image_size( 'custom-tb-size', get_option('mingof_tb_img_width',600), get_option('mingof_tb_img_height',400));
    add_theme_support('custom-background',array(
        'default-image'=>'',
        'default-position-x'=>'center',
        'default-position-y'=>'center',
        'default-size'=>'cover',
        'default-attachment'=>'fixed'
    ));
    add_theme_support( 'title-tag' );
}
add_action('after_setup_theme', 'theme_setup');

当然这还不够,我还想实现切换“主题色”的功能,还想实现切换“横向 Header” 和“纵向 Header“ 的功能。所以我找到了 WordPress 的 add_action 文档。

add_action( 'customize_register', 'mingof_customize_register');
/**
 * 注册自定义功能
 * @param $wp_customize
 */
function mingof_customize_register( $wp_customize ) {
    // 这里注册设置
    $wp_customize->add_setting( 'mingof_style_options[highlight_color]', array(
        'default'        => '#738fa3',
        'type'           => 'option',
        'capability'     => 'edit_theme_options',
        'transport'      => 'refresh'
    ));
    $wp_customize->add_setting('mingof_style_options[highlight_color_in_dark_mode]',array(
        'default'=>'#b18983',
        'type'=>'option',
        'capability'=>'edit_theme_options',
        'transport'=>'refresh'
    ));

    // 这里注册 control
    $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'highlight_color', array(
        /*名字*/
        'label'        => __( '高亮色(主题色)', 'mingof' ),
        /*section属于……*/
        'section'    => 'colors',
        /*对应的settings*/
        'settings'   => 'mingof_style_options[highlight_color]',
    )));
    $wp_customize->add_control( new WP_Customize_Color_Control( $wp_customize, 'highlight_color_in_dark_mode', array(
        'label'        => __( '夜间模式高亮色', 'mingof' ),
        'show_opacity'=>true,
        'section'    => 'colors',
        'settings'   => 'mingof_style_options[highlight_color_in_dark_mode]'
    )));
}

最终效果就是这样。

image-20201227102126519

image-20201227102758010

image-20201227102820187

最后

主题完工了,一阵空虚……我好像不怎么爱写博客T^T