采用Mavic Air2进行手杆拍摄

1 前言

在我们刚碰手无人机的时候,我们更多只知道从上方俯视下方来进行拍摄,或者是远望来看无人机的拍摄。那其实系统层面来讲,无人机可以拍摄怎样的智能画面呢?下面就来看看整体的过程

2 大师镜头如何手杆刷锅

针对无人机的飞行,那一键傻瓜式的无人机飞行模式肯定是最容易实现的。那是否就只有智能模式呢,答案是否定的。下面就来罗列一下有什么操控手法可以拍摄不一样的画面,发挥无人机的全部潜力

这里也要科普一下一些专业名词:

  1. 油门杆:控制无人机 向上飞行
  2. 俯仰杆:控制无人机 向后飞行

2.1 希区柯克变焦

点击此处可以观看具体的教程

希区柯克变焦又叫做滑动变焦(Dolly Zoom),是电影拍摄中一种很常见的镜头技法。

希区柯克变焦有三大核心要素:摄像机的方向、推拉的速度、摄像机镜头的焦距。这三大要素决定了一个希区柯克变焦镜头的感觉,比如推拉速度快=惊吓、震惊,推拉速度慢=恐怖、游移;摄像机方向可以选择正视角,也可以用斜角。

希区柯克变焦一般分为两种:外退内进(Dolly-out & Zoom-in)和外进内退(Dolly-in & Zoom-out)。外退内进指的是摄像机往后退,同时焦距往前进;外进内退则反之,摄像机往前进,同时焦距往后退。

无人机的操作要领:

  1. 修改飞机的飞行模式,修改成平稳模式(P档),从而获取平稳的速度。以“美国手”摇杆模式为例,操控后退(右杆向后波动)
  2. 操控时,通过FN+左波轮实现平滑的变焦,从而让目标物体在视野里大小整体变化不大

2.2 渐远操控模式

心中有目标物,靠近目标物进行拍摄,再进行以下的操作:

  1. 俯仰杆打满
  2. 油门杆不能打太快

image-20211007161538235-3611484

2.3 远景环绕

在对目标物体进行环绕的过程,不断转动机身的yaw轴,使机头始终朝向目标物。

image-20211007211341519

可能有同学会想,那想要逐步去靠近目标物,突出主题可以怎样做?那可以采取下面的操作模式,给机身一些向前的方向,使机身想着目标物前进

image-20211007211801280

2.4 抬头前飞

先让镜头朝下正扣,正扣的快捷键是双击fn键。此处的操作分两步:

  1. 打满俯仰杆量
  2. 加一点点油门杆
  3. 波动左波轮,让镜头缓慢抬起朝向90度。ps:此处可以进入“云台高级设置”=》“云台缓冲速度”,修改成5-10的范围,那云台的转动速度将会变得慢慢抬起,你可以把左波轮打满

2.5 扣拍旋转

主要是用来给扣拍增加一些动感,操作过程如下:

  1. 双击FN键,让云台垂直向下
  2. 波动油门杆向上飞行
  3. 波动左杆量往左 或者 右 方向。使机身旋转起来

2.6 冲天

冲天的操作,更为简单:

  1. 波动油门杆向上飞行
  2. 波动左波轮,让镜头向下移动,尽量让目标物在FPV中相对不变的位置

3 为什么会写这个文章?

对于视频上的教学,我相信大家看过一定都明白了,但是如果没有去尝试练习一下,是否你还记得。而练习的时候,如果要重新看一次视频,那需要5分钟,但是如果是文档上的记录,是否你可以快速就想起来呢?

无人机的操作,真的很过瘾,没想到能操作那么遥远的距离,也没想到能拍摄如此美丽的风景,此处带上我的一个东澳岛的照片

DJI_0774

Photo_6554372_DJI_772_jpg_9017869_0_202110516032_photo_original

日志规范

1 背景

我们大家都知道写日志是很重要的,但是要怎么写日志合适,什么节点该打日志,其实并没有人告诉我们。靠的是每一个各自的领悟能力,这里我们需要去完善这部分,让日志能传承,积累,发展下去。让我们(开发,测试,技术支持)一起知道一套规范,Follow一套规范。低成本,高效一起协助定位问题,提高软件的质量。

基于此,我们会疑惑,每次上报的问题,技术支持/测试 只有一个透传数据的任务,第一层接触的开发就需要去过滤,复现问题,确定问题应该找哪个部门来解决。借此引发,我们是否应该在日志的纬度能够去规避这个问题,让更多参与的人能直接看出问题是在哪里的?

2 日志规范

我们的日志里面有什么?
经过沟通,期望能统一 Android、iOS上日志的规范,让大家(开发、测试、技术支持)形成一个统一的规范,减少沟通和维护的成本

2.1 分析需求

期望日志能记录什么,能给我们带来什么样的内容?

  1. tag:可以用于标记系列的日志Id【可用于筛选出一个功能其流程是怎样产生的】
  2. Function: 函数名,具体日志是在哪里产生的
  3. line: 具体日志是在文件的哪一行产生的
  4. 当时软件、硬件环境是怎样的。到底遇到了什么问题?
  5. 问题是怎么产生的,应该找谁去解决问题

2.2 一个日志文件 开始与结束

目前的策略,采取的是一次APP进入到前台的时候,则会划分一个日志文件。可以简化日志的大小,也可以直接看到一次处于前台APP发生了什么事情。所有的日志将采取一个文件,这么做的一个好处,可以看到在时间维度上都发生了什么事情。而如果想要知道某一个功能具体的情况,可以通过 2.1 里所指的tag来划分出要的日志信息

2.3 应该写入什么

日志这部分是一个case by case的场景,无法一开始就能决定所有的日志要怎么打印才是对。那我们反思,什么信息是有用的:

  1. 环境信息
  2. 过程和出错日志,该找谁解决

2.3.1 环境信息

我们的研发过程,对于复现,或者发现是哪一个版本的固件才存在的问题,我们需要知道相关固件各个版本,软件版本,设备信息。此时可以使用日志将内容打印

2.3.2 过程和出错日志,该找谁解决

往往我们出现问题是某一个具体的功能,此时可以通过tag来完成筛选一个功能的日志信息。那日志又应该怎么打印?

我们从(What,When,How)来思考问题:

  1. What:我们应该打印什么?此处我的经验告诉有几个地方可以打印:
    1. 功能流程触发,可以知道这个功能开始了
    2. 功能出错,可以知道当时出错的原因
      出错这里会划分多个维度的:
      1. 因为V1协议返回的异常【此时可以带上告知看日志的人,需要找哪个模块的固件定位】
      2. 因为状态校验不通过【此时可以带上告知看日志的人,需要找此功能的SDK研发定位】
      3. 因为当下的条件不满足引起无法触发功能【此时可能是上层调用的顺序问题,可以提出建议需要调用什么接口之后再使用此接口的建议】
  2. When:我们的日志要遵循一个规则,不能疯狂打印,这样会有打印的效率,建议只打印以下条件的
    1. 如果这个动作是一次性,只有用户驱动才会触发,可以打印
    2. 在满足条件1的情况下,出现判断错误的时候,需要打印
  3. How:对于流程过程,可以采取 info 等级的日志。对于出现异常,但是不影响流程的日志,使用warning。对于出现异常,但影响流程功能的采取error

以上我们打印出了一个功能的过程,与出错原因了。那还需要一个日志,那就是具体这个日志可以找谁解决问题。

这里我们将要求开发在打印出错定位的日志时,带上具体可能是谁引起的错误,(开发、测试、技术支持)应该找谁来解决这个问题。

2.3.3 日志等级的划分与作用

日志等级控制,在不同的配置环境下,打印不同等级的日志
对于日志部分,我们可以划分以下几个等级:

等级 作用 Release环境 Debug
fatal 非常严重的问题,需要使用此等级来打印 可以 可以
error 出现异常错误的等级 可以 可以
warning 警告,虽然可以继续执行,但是建议消除 可以 可以
info 打印相关信息 可以 可以
debug 调试使用的等级 禁止 可以
verbose 调试使用的等级 禁止 可以

2.3.4 一行日志的例子

上面讲了这么多,那一行日志应该是怎样?这里举个例子

1
20:19:30.0300 function:line [E][Camera_Shoot][Custom Information][Please find the SDK developer]

一行的日志有以下的信息:

  1. 时间戳【例子中的 20:19:30.0300】:只需要 时,分,秒,毫秒的单位。哪年哪月那日由日志文件已经带上了,这里无需,可以简化日志量
  2. 具体的函数和行【例子中的 function:line】:给开发可以知道是在哪一行打印这个日志的。行数有时可以用于确定与出问题当时的代码是否一致
  3. 日志等级【例子中的 [E]】:这个日志是用来说明什么的,这块靠的更多是开发的sense。如果你明确要定位哪一个问题,可以通过第4点的tag,加上这个等级,可以直接筛选出一个功能所有的错误信息。比如例子可以筛选出 [E][Camera_Shoot]
  4. 功能的Tag【例子中的 [Camera_Shoot]】:可用于搜索一个功能的整个流程是怎么跑的
  5. 自定义内容【例子中的 [Custom Information]】:这块全由开发决定,主要是用于定位问题在哪里
  6. 建议问题可能要找谁解决【例子中的 [Please find the SDK developer]】:因为我们的日志是考虑 技术支持/测试 也可以参与进来指派问题给谁

3 快捷工具

3.1 使用tag划分日志

请按照一下的步骤完成筛选你要的日志部分:

  1. 安装 Visual Studio Code
  2. 安装 Visual Studio Code插件Filter Line
  3. 打开你想要从中筛选出来的完整日志文件(即夹杂各种信息)
  4. 使用快捷键 Command + Shift + P,搜索
  5. 输入你想要筛选日志行里面的目标关键词
  6. 即可得到你要的功能整个过程的日志信息

UML(一)初探

1 前言

UML[1]是一种开放的方法,用于说明、可视化、构建和编写一个正在开发的、面向对象的、软件密集系统的制品的开放方法。
UML是一门通用的语言,在对于人与人之间的交流上,能提供跨编程语言的作用。在设计阶段,功能落地阶段,测试阶段,维护阶段,能起到提高效率的作用。

使用UML能为我解决什么问题?这里我罗列一下我遇到的场景:

  1. 在一个较大的功能(可能要1个月才能完成)来到的时候,在没有使用UML的时候,我可能会开发过程中,会发现我可能一开始做设计的时候没有考虑的点。或者我曾经想到过的点,到我真正编程的时候,就忘记了这个小点。在此过程,我需要不断反复修复不同地方的小点。
  2. 当我开发这个功能的时候,可能我是要跟不同的同事合作(比如合作的同事是做 与我不同平台的 开发语言),此时我需要面对面通过一些画图来讲解我的功能设计。因为大家的开发语言不一致,对方要看我的源码是不太现实的
  3. 当测试需要介入时,他们需要了解我们的内部逻辑,才能做好白盒测试[2]的测试用例设计。此时也不能直接让对方看代码,只能靠口口相传
  4. 可能过了很久很久以后,有同事帮忙去定位模块的功能 Bugs,或者迭代优化。对于那位接手的同事,只能面对一片没有注释的源码,估计他只能在地下画圈圈了

应对上面4个场景,使用了UML之后,会怎样:

  1. 可以通过UML的元模型建立功能模型,对象模型,动态模型,反思自己在设计这个代码的时候,是否具备完备性。人的记忆是有限的,当设计完一个子模块,跳到另一个子模块设计的时候,可能就对上一个模块的记忆会出现模糊。而拥有已经写好的UML,可以让人快速建立对上一个子模块的记忆(UML每一个记录的细节点,都可以成为那位开发的记忆触发点)。当真正进行开发的时候,开发可以按照UML来进行相关的开发,尽可能保证所有的细节都被保留。
  2. 当进行技术评审时,可以拿出UML,进行整个流程的讲解。让对方知道自己是怎么跑流程/功能。由于UML是统一性语言,对方能很快get到设计者的思路想法。Reviewer可以根据自己的经验给出一些建议,能让大家的沟通成本,思想的传递做得更好(PS:相对文字和图形,人脑对图形的接受能力显然更强)
  3. 跟第二点一样,对于测试同事,也可以很快传达自己的思路
  4. 从维护角度,通过UML和必要的文字描述,可以辅助接手的同事快速知道代码不同地方的作用。如果有了相关的UML,在代码的类头部也可以加入注释,把文档的link带上。

1.1 它能为我带来什么好处

从我目前几个月的使用情况来讲:

  1. 前期设计上:对我在做功能设计的时候,可以低成本画出功能上是怎么运作,每一步是怎么做的,是否有遗漏没有考虑到的地方
  2. 合作上:可以使用它跟合作的开发介绍这个功能是怎样,让对端理解我的设计,提出意见
  3. 测试上:可以让测试知道其内部的运作模式是怎样的(可用于技术评审上讲解功能展示,这里注意要补充一些必要的文字,如果单纯丢文档,可能信息不足,对于测试同事会懵逼),能做出相关的白盒测试用例。
  4. 维护上:人员的流动,业务的交接,这是无法避免。对于接手业务的同事来讲,必要的文档,能让他们更快去理解原来功能的设计
  5. 跨部门支援:当别的部门想直接使用本部门已经完备的功能,这是可以通过这部分的文档,快速让对方知道要怎么接入

2 目前我对UML的理解

在了解有什么UML之前,可以先思考一下,在哪里用到UML,怎么使用UML。这里有一个概念要介绍一下。

  1. 建模:指通过对客观事物建立一种抽象的方法用以表征事物并获得对事物本身的理解,同时把这种理解概念化,将这些逻辑概念组织起来,构成一种对所观察的对象的内部结构和工作原理的便于理解的表达

以我目前使用到的场景,有以下三个场景:

  1. 了解需求后,根据经验与了解到的事情,把关键的要素罗列出来,通过活动图描述整体走下来的过程。让参与者达成一致,避免大家理解的差异
  2. 对具体的一个功能,其内部逻辑的交互过程通过时序图描述出来。有什么作用,请看下面两点
    1. 自我回述查看是否哪里的一个拐点我理解不足,是否我需要去了解更多
    2. 可以跟他人沟通,让双方达成一致的观点,或者对方可以补充我思考不足的地方
  3. 跨部门合作的适合,明确双方的一个交互活动图,明确双方的职责在什么地方。与第一点相似,但是这里偏向双方的技术栈是不同,可以通过统一语言,让双方明白交互物,输入/输出是什么。

3 我常用的UML类型

我比较常用的UML有以下几种:

  1. 时序图
  2. 类图
  3. 活动图
  4. 组件图
  5. 状态图

不常用的UML图有以下:

  1. 对象图
  2. 部署图

以下将展示一下上面讲到的图的例子

3.1 时序图

时序图[4]:通过描述对象之间发送消息的时间顺序显示多个对象之间的动态协作。

以下是一个例子

3.2 类图

类图[5]:显示了模型的静态结构,特别是模型中存在的类、类的内部结构以及它们与其他类的关系等。

以下是一个例子

3.3 活动图

活动图[6]: 阐明了业务用例实现的工作流程。

以下是一个例子

3.4 组件图

组件图[7]:表示组件是如何互相组织以构建更大的组件或是软件系统的。

以下是一个例子

3.5 状态图

状态图[8]:描述一个实体基于事件反应的动态行为,显示了该实体如何根据当前所处的状态对不同的事件做出反应。

以下是一个例子

3.6 对象图

对象图[9]: 显示了一组对象(类的实例)和他们之间的关系。

以下是一个例子

3.7 部署图

部署图[10]:用来显示系统中软件和硬件的物理架构。

以下是一个例子

4 总结

以上是我为什么会投入去了解和使用UML的原因,基本的例子给大家看看各种图的样式。后面会讲解我针对不同的UML的日常使用理解与结合PlantUML[11]是如何使用的介绍。工具能让我在一些不必要的消耗上减少,focus更多的精力在工具无法解决的领域


  1. 维基百科对UML的解释 ↩︎

  2. 白盒测试:百度百科 ↩︎

  3. Thinking in UML,作者:谭云杰,可以在微信读书上找到 ↩︎

  4. 时序图百度百科 ↩︎

  5. 类图百度百科 ↩︎

  6. 活动图 百度百科 ↩︎

  7. 组件图 维基百科 ↩︎

  8. 状态图 百度百科 ↩︎

  9. 对象图 百度百科 ↩︎

  10. 部署图 百度百科 ↩︎

  11. PlantUML官网 ↩︎

markdown-it-alerts语法支持

1 前言

在我们使用VNote[1]写博客的时候,里面有一个功能叫警告,具体的效果可以查看这里 Bootstrap Alerts。

2 环境的准备

由于hexo本身并不自带markdown-it渲染器,所以需要将需要进行替换。

  1. 可以点击查看这里的替换教程,插件的官网方面:点击查看官网的github
  2. markdown-it渲染器本身是不支持alerts语法,所以此时需要安装markdown-it-alerts插件
  1. 由于markdown-it-alerts的插件只是寻找到对应markdown语法进行替换,css样式部分它并不负责,所以需要到网站官网去下载样式,点击下载Bootstrap样式。也可以将样式里面大部分删除,只剩下 alert 相关的CSS样式。

3 环境的配置

这里我会划分成两步:

  1. 加载Alerts所需的CSS样式
  2. 优化markdown-it-alerts插件

3.1 加载Alerts所需的CSS样式

对于加载额外的样式,可以使用hexo提供的辅助函数(Helpers)

  1. 将样式存放,即将样式放到hexo根目录/source/css/bootstrap.css
  2. 让主题加载这个新添加的样式,寻找到网页head总定义位置,一般在(hexo根目录/themes/你用的主题/layout/_partial/head.ejs),如果还是没有找到,可以看看是否在hexo根目录/themes/你用的主题/layout/layout.ejs。在head.ejs里面添加以下的一句代码
1
<%- css('/css/bootstrap.css') %>

此时就会有alerts的样式,开始下一步

3.2 优化markdown-it-alerts插件

markdown-it-alerts与VNote[1:1]在Alerts方面还是有所区别,这里就会导致一些尴尬,在VNote[1:2]写完,不能在hexo里面直接用。查看以下图表

此时需要进入到 markdown-it-alerts 插件进行语法分析修改,保证与VNote一致的语法分析。进入博客根目录/node_modules/markdown-it-alerts/index.js,打开进行修改成以下的内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
'use strict';

var container = require('markdown-it-container');

module.exports = function alerts_plugin(md, options) {
var containerOpenCount = 0;
var links = options ? options.links : true;
init();
return;

function setupContainer(name) {
md.use(container, name, {
render: function (tokens, idx) {
if (tokens[idx].nesting === 1) {
containerOpenCount += 1;
return '<div class="alert ' + name + '" role="alert">\n';
} else {
containerOpenCount -= 1;
return '</div>\n';
}
}
});
}

function isContainerOpen() {
return containerOpenCount > 0;
}

function selfRender(tokens, idx, options, env, self) {
return self.renderToken(tokens, idx, options);
}

function setupLinks() {
var defaultRender = md.renderer.rules.link_open || selfRender;

md.renderer.rules.link_open = function (tokens, idx, options, env, self) {
if (isContainerOpen()) {
tokens[idx].attrPush(['class', 'alert-link']);
}

return defaultRender(tokens, idx, options, env, self);
};
}

function init() {
setupContainer('alert-primary');
setupContainer('alert-secondary');
setupContainer('alert-success');
setupContainer('alert-info');
setupContainer('alert-warning');
setupContainer('alert-danger');
setupContainer('alert-light');
setupContainer('alert-dark');

if (links) {
setupLinks();
}
}
};

从此VNote与hexo的alerts语法分析就一致了,可以相互使用,开始快乐的写博客吧!!!

4 效果


  1. VNote是一个更懂程序员和Markdown的笔记软件,可以查看官网了解更多。 ↩︎ ↩︎ ↩︎

时间管理工具Toggl

1 前言

我曾遇到过不知道自己一天工作下来,我具体做了什么,时间用在了什么地方。多而杂,频繁切换上下文。这个时候我接触到了Toggl这款软件

2 基本环境

这款软件,它主要可以从几个维度去统计你做的事情:

  1. Description:具体做的事情描述
  2. Project:这个事情所在的项目维度
  3. Tags:属于哪个维度的工作(这里后续再详细讲解一下我的用法)

这个软件支持多个平台,比如有以下:

  1. Toggl 网页版
  2. Toggl 桌面版
  3. Toggl 安卓端
  4. Toggl iOS端

2.1 如何记录

平时我在做一件事情的时候,会先使用Toggl 桌面版(Mac版本),开启一次记录,这里有两种方式:

  1. 开启完全全新的任务
  2. 延续上一次未完成的任务

2.1.1 全新任务的开启

开启全新的任务,可以使用快捷键 Command + N。这里客户端不会让你填写信息,此时你需要再使用Command + E,可以编辑当下进行的任务。

  1. Description:常规的填写,这里我会尽量简化信息,但是也要保证我下次查看的时候能够知道当时做什么。
  1. Project:这个是比较大的维度,跟你做的具体项目上挂钩,你可以知道你为了某个项目具体的投入与产出比情况。此选项可以多选,我平时一般只是规划成一个项目,对于后续查看Reports时,会相对比较方便。
  2. Tags:打标签这个也可以多选。对于我来讲,我会从别的维度去查看自己的。比如你做一个项目的时候,会划分 开会,方案设计,方案落地等等,此处可以看你把时间大头放在什么地方。

2.1.2 延续上一次任务

对于因为一些原因打断了原来的任务,此时需要再次投入继续完成,此时可以在list里面找到那一项,点击右侧的开始按钮。

3 回顾分析

我平日里,会从 周/月/季度 的角度回顾总结我自己的工作中时间上的耗时,在网页版的Reports可以查看到我自己在其中的投入情况,以上的事情是否很繁琐与麻烦呢?做的意义是什么,这里我罗列一下我的看法:

  1. 比如从tags上刷选,可以看到具体是什么事情blocks住我,让我的计划并没有按照我的想法执行。此时可以向上反馈,请求上级能通过什么方式帮助到自己。
  2. 当填写公司工时系统时,可以通过网页版复制粘贴到工时系统
  3. 当进行 月度/季度 总结的时候,也可以通过这个查看到自己做过的每一个事情,具体的信息遗留,提供更多有力的证据去证明自己曾经的输出。

::: danger
这里我想讲那么一点,管理不是只有上级管理下级,还有向上管理,需要让上级知道你做得怎样,不要期望上级是你肚子里的虫子,他能了解你的一切。这是一件对你自己工作输出负责的事情。

:::

4 日常小技巧

对于不同的客户端,我有不同的使用场景,这里可以罗列一下我日常的使用方式:

  1. Toggl 网页版:用于填写工时,查看Reports时来查看
  2. Toggl 桌面版:由于网页版长久打开看起来存在内存泄漏,或者打开时会有时间上的损耗,所以一般使用客户端,能尽可能减少电脑的负荷。也是日常用于记录的工具
  3. Toggl 安卓端/Toggl iOS端:一般是用于电脑不在身边但是需要记录,或者离开电脑忘记关闭计时器时使用的。

5 回顾总结

时间总是不断流逝,严谨对待自己的每一分每一秒,回顾与总结,我相信我们都会变得越来越好

网页浏览全键盘操作

1 前言

对于此篇文章,大家可以从以下两个角度来看:

  1. 大家是否有很多网页存储在自己的收藏夹,时不时要去翻看呢?
  2. 大家在浏览网页的时候,是否不太喜欢用鼠标,但是又不得不用?

如果都没有这方面的烦恼,那可以跳阅本文章哟!!

2 Alfred用法

Alfred是一款非常高效,可以代替系统自带的Spotlight软件。是一款拥有非常历史悠久历史的软件,我记得我开始接触它的时候,是在2013年的时候。具体你想了解,可以点击此处进入它的官网了解它更多。在这里我更多讲解一下我的用法。

大家是否有遇到我一样的场景,比如以下:

  1. 喜欢收藏很多页面到自己Safari收藏夹内。(当然这里会分门别类,以前就没分得很细,导致很多都要找很久才找回来)
  2. 文件放到iCloud里面,也划分很多位置,层层嵌套的文件夹。

每次想到好像我是有收集的这个信息的时候,我就要从这些成千上万的内容里面去找到当初我的收藏。阿,好累。此时Alfred就可以帮助到我了

::: info
这里说一说,我平时喜欢spotlight的快捷键关闭了,将其快捷键改成了打开Alfred,完全替代系统
:::

2.1 利用Alfred找到Safari收藏的网页

  1. 点击Alfred软件的Preferences...
  2. 选择Features中的Web Bookmarks.

此时Alfred就有权限访问你收藏夹内的内容。打开Alfred,搜索关键字,回车就可以快速打开你想要的网站。这里需要记住网站的开头,貌似模糊搜索支持一般般

2.2 利用Alfred找到本地文件

可能有人会提问,找到本地文件有什么特别的吗?Spotlight也支持呢!!!

这里官方提供两个命令方式:

  1. 访达/Finder打开文件所在的文件夹,打开Alfred输入窗口,比如以下的命令。
1
find 文件名前部分
  1. 打开文件。打开Alfred输入窗口,比如以下的命令。
1
open 文件名前部分

3 Safari插件Vimari

它是一款可以让你的双手在浏览Safari的时候,不用鼠标就可以操作的插件。官网地址,可以在这里查看
你可以在Mac Store上下载这款软件,解放你的鼠标。
如果你有学过Vim,我相信你1分钟内就能解决。没学过也不影响,因为它并不会很复杂。

我自己记住的方式:

  • 上下左右这几个操作多几次就差不多了
  • gg: 我们玩游戏的时候,常常一句我们gg了,要重新来了,代表滚到页面的开始
  • G:这个跟gg关联在一起记忆,没有太多的方法
  • u/d:是一对比起 j k 操作一行行来要更加方便
  • q/w: 代表前一个标签页/后一个标签页,比使用系统的Ctrl + Tab要舒服多了,记住在自己键盘的左上角
  • x:联想到我们关页面的 x 标志
  • t:就不太好用了,这个不会将聚焦点放到新建的标签页网页Link位置,这里还是用系统的快捷键反而合适。Ctrl + t
  • r: 联想到单词reload,总体来将还是挺好的。

4 总结

活用工具,让自己更加Focus在工具无法解决的问题,我相信会见到越来越棒的自己

使用Valine在Hugo添加评论功能

1 背景

对于我们在写搭建github.io的博客的时候,由于Hugo本身是静态网站,并不是动态网站。那我们可能就无法知道到底我们写的博客有多少浏览量,还有如果文章写的有问题,大家无法告诉你要怎么更改。所以我在这里引入了Valine。它是一款基于LeanCloud无后端的评论系统,很方便集成的。以下的内容是告诉你如何在Hugo中集成Valine评论系统。

1.1 最终的愿景

我们希望通过Valine能达到以下的两个效果

  1. 统计出浏览量,知道到底我们写的文章有多受欢迎
  2. 附带评论的功能,可以收到来自外部的反馈。得到很好的交流作用

2 开始集成

我们是要适配一款基于LeanCloud无后端的评论系统,那意味着我们需要先到LeanCloud平台上进行注册,那我们看下下一个操作

2.1 LeanCloud配置

2.1.1 创建应用

点开LeanCloud,然后进行注册的操作,进入控制台,点击创建应用,如下图

image-20191214095704295

2.1.2 创建存储器

创建好后,进入刚刚创建的应用配置页面,进入到存储=》结构化数据,创建两个Class,如下图

  1. Comment:是一个记录评论相关信息的class
  2. Counter:是一个记录文章的访问量的class
image-20191214100028492

2.1.3 安全配置

此处需要配置你的域名,防止因为一些爬虫,或者恶意软件导致你的流量虚假暴增,最终支付昂贵的收费。请看以下的配置过程

image-20191214100523986

题外话题,可能有人关心这个收费是怎样。目前采用的是开发版本,在1G的流量内是免费的。超出的部分,每天每超出1G的量支付0.1元。据目前的查看,3周大约只要550KB,所以用量可以说是能接受的范围。以上的解说是2019-12-14日。具体以官方价位为准,请点开这里查看

2.1.4 获取APP ID和APP Key

APP ID和APP Key是作用于你的请求时,用于校验身份使用的。可以在配置页面此处找到,请记住,后续的操作需要使用到

image-20191214103055359

2.2 如何配置Valine参数

我们需要将上面LeanCloud拿到的APP ID和APP Key转化为Valine的配置参数

可以看看我的配置参数

1
2
3
4
5
6
7
8
9
10
params:
valine:
enable: true
appId: 你的APP ID
appKey: 你的APP Key
notify: false
verify: false
avatar: "robohash"
placeholder: "谢谢你的支持"
visitor: true
  • enable:用于决定是否开启评论的功能,暂时记录的一个flag。
  • notify:评论回复邮件提醒,请参考配置
  • verify:验证码服务。
  • avatar:头像,更多的信息请查看头像配置
  • placeholder:评论框占位提示符
  • visitor:文章访问量统计

更多的详情可以查看:https://valine.js.org/configuration.html

将以上第二行以下的内容放到你的config.yaml配置文件中params的下一层级,如果你的配置文件是别的格式(例如toml/json)请自行转化格式的书写

2.3 如何在HTML页面添加

先看一下以下的一段HTML代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<!-- valine -->

{{- if .Site.Params.valine.enable -}}

<!-- id 将作为查询条件 -->
<span id="{{ .URL | relURL }}" class="leancloud_visitors" data-flag-title="{{ .Title }}">
<span class="post-meta-item-text">文章阅读量 </span>
<span class="leancloud-visitors-count">1000000</span>
<p></p>
</span>
<div id="vcomments"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>
<script type="text/javascript">
new Valine({
el: '#vcomments' ,
appId: '{{ .Site.Params.valine.appId }}',
appKey: '{{ .Site.Params.valine.appKey }}',
notify: {{ .Site.Params.valine.notify }},
verify: {{ .Site.Params.valine.verify }},
avatar:'{{ .Site.Params.valine.avatar }}',
placeholder: '{{ .Site.Params.valine.placeholder }}',
visitor: {{ .Site.Params.valine.visitor }}
});
</script>

{{- end }}

以上的一段HTML就是完成评论区的作用,以下是效果图

image-20191221150427334

我们来分章节解析不同的模块的作用

2.3.1 评论功能的开关

2.1中的最终形态的HTML中,添加了这个语句

1
2
3
{{- if .Site.Params.valine.enable -}}

{{- end }}

它的作用是所有的文章是否开启评论区的作用

此时有人想问,在哪里去控制开关呢?

看到.Site.Params可以联想到博客里面有个config.yaml的配置文件(Hugo的配置文件有三种yaml/toml/json),在配置文件中,如果你根据2.2章节的操作后,会有以下的一个配置

1
2
3
4
params:
valine:
# 此处就可以操作评论功能是否开启
enable: true

如果填写了true,则开启所有的文章的评论功能,反之,填写了false,则关闭所有的文章的评论功能

2.3.2 评论区界面渲染

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- id 将作为查询条件 -->
<span id="{{ .URL | relURL }}" class="leancloud_visitors" data-flag-title="{{ .Title }}">
<span class="post-meta-item-text">文章阅读量 </span>
<span class="leancloud-visitors-count">1000000</span>
<p></p>
</span>
<div id="vcomments"></div>
<script src="//cdn1.lncld.net/static/js/3.0.4/av-min.js"></script>
<script src='//unpkg.com/valine/dist/Valine.min.js'></script>
<script type="text/javascript">
new Valine({
el: '#vcomments' ,
appId: '{{ .Site.Params.valine.appId }}',
appKey: '{{ .Site.Params.valine.appKey }}',
notify: {{ .Site.Params.valine.notify }},
verify: {{ .Site.Params.valine.verify }},
avatar:'{{ .Site.Params.valine.avatar }}',
placeholder: '{{ .Site.Params.valine.placeholder }}',
visitor: {{ .Site.Params.valine.visitor }}
});
</script>

以上的一个JavaScript是负责渲染评论区的界面代码,评论区的不同样式与功能的配置,可以关注到代码里面有.Site.Params.valine,这里就是获取了在2.2章节中记录的valine配置信息。可能大家有以下的两个问题:

  1. 我应该怎样修改已有的配置?

    可以通过config.yaml去修改你想要的配置,以上的HTML是存放到模版(请看2.3.3章节了解详情)。对于HTML中的不要用hardcode,这样以后的维护将到处都有

  2. 是否还有更多有趣的配置我不了解?

    valine还有其他的配置,可以点击此处

2.3.3 在哪里添加Valine的HTML代码

Hugo是一个基于主题模版去渲染文章,那我们的HTML代码就需要放到模版中。

第一步,寻找文章模版存放的位置。一般来讲,是存在在根目录/themes/你的主题名/layouts/_default/single.html

第二步,打开文件,大概的结构可能是这样

1
2
3
4
5
6
7
8
9
10
11
12
13
{{- define "main" -}}

{{- partial "navbar.html" . -}}
{{- partial "navbar-clone.html" . -}}
<!-- 这里插入Valine的HTML代码 -->
{{- partial "footer.html" . -}}

<!-- Back To Top Button -->
<div id="backtotop"><a href="#"></a></div>

{{- partial "sidebar.html" . -}}

{{- end -}}

这里是将一个文章拆分了不同的html,将其拼接成最终的博客网站。

为什么要这么做?我的猜想:是为了可复用性。

想想一个博客网站,有多个页面,但是顶部和底部的导航栏一般都是同样的样式,如果是通过拷贝的方式,一个导航的改变,将需要到处修改。

如果是要reference的方式,只有一份源码,所有的页面都依赖这一份,一改则影响所有的页面的渲染

第三步,在第二步的例子代码中注释的添加2.3章节中整体的评论区valine代码。这样就可以实现本文下方的评论功能

3 查看数据

首先需要先登陆到leancloud的网站,点击这里,登陆你的账号。然后进入结构化的数据,就可以看到每个文章的一个请求数据

image-20191221161307115

使用Typora书写Hugo博客

1. 背景

如果未了解Hugo是什么,请查看此篇文章,如何使用Hugo搭建博客

是否有考虑过,如果直接使用hugo来写博客,每次只能打开网页来查看markdown的最终效果。

比如你可能需要引用一个照片,但是此时照片需要放到 hugo/static。如果你想做到可以正常看到照片,还需要设置static的相对路径,好麻烦

此篇文章是解决你在书写上的cost。

我们最终想做到是使用 typora 书写后的文章,只要执行发布即可完成

2. 如何使用Typora书写Hugo博客

首先我们先要使用命令创建一个博客的markdown

2.1 创建Markdown

请使用以下的命令创建博客

1
> hugo new 一级目录/文章标题/index.md

可能有人疑惑,为什么这里,不使用文章标题作为markdown文件的名字,而要抽离出一个文件夹名字

出于两个原因:

  1. 照片资源
  2. 文件集中

2.1.1 照片资源

对于很多第三方的markdown添加照片的时候,路径默认只是 图片文件夹/图片名。那里面照片最终的HTML照片的路径将 <img src=“图片文件夹/图片名” alt=“Hugo-File-Tree” />。此照片的搜索路径将使用当前文章的域名路径。比如当前文章的路径是 https://{server address}/turtorial/使用Typora书写Hugo博客/。那照片搜索的路径将变成 https://{server address}/turtorial/使用Typora书写Hugo博客/图片文件夹/图片名

以下是我们Hugo中文件存在的情况,但是我们没有创建一个叫“使用Typora书写博客”的文件夹,那照片其实是找不到的。

实际上,照片的路径是 https://{server address}/turtorial/图片文件夹/图片名

我们文章,照片的搜索路径是 https://{server address}/turtorial/使用Typora书写Hugo博客/图片文件夹/图片名

错误的文件目录

Hugo官方的建议是使用markdown输入的路径格式前面加个 /,比如 /图片文件夹/图片名,这样最终照片的寻找路径会变成 https://{server address}/图片文件夹/图片名

也是为什么官方建议把图片,js,css资源放到static文件夹,因为static文件夹内的资源文件会copy到 https://{server address} 根目录下

详细可点开此链接,查看官方文档

官方的文档的确是可以解决以上的问题,但是会导致markdown与引用的照片资源分离,其实这样不利于编写。这里教导的方式,你用typora写好后,把文章放到 hugo/content/一级菜单/文章文件夹 即可完成整个发布

最终的文件目录效果要如下建立:

正确的照片路径

2.1.2 文件更集中

如果建立好一个文件夹,那关于此文章的所有的资源都将放在 文章文件夹 中。比如你后来可能改了一些图片,不致于需要到处找引用的照片资源在哪里,你需要去删除,与替换掉资源。

2.2 配置typora引用的照片处理

对于Typora是提供了引用照片如何处理功能。当你引用一个与markdown不在一个文件夹目录下的资源时,typora可以帮你建立特定规则的文件夹,并拷贝照片到 特定规则的文件夹。

你可以进入Typora的 偏好设置 =》 图像,选择以下的配置项

image-20191124111117356

此时只要你拖动照片到markdown文章时,Typora会自动帮你创建文件夹与copy一份照片到指定文件夹的目录下。

3. 如何发布

将文章拷贝到Hugo/content/一级菜单的目录,执行以下命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
> cd Hugo文件夹目录
> hugo

| EN | RU
+------------------+----+----+
Pages | 12 | 3
Paginator pages | 0 | 0
Non-page files | 26 | 0
Static files | 22 | 22
Processed images | 11 | 0
Aliases | 1 | 0
Sitemaps | 0 | 0
Cleaned | 0 | 0

Total in 227 ms

然后把public文件夹,push到远端的github repository

完成最终的发布

Hugo搭建博客

[

Hugo是什么

Hugo是由Go语言实现的静态网站生成器。简单、易用、高效、易扩展、快速部署。

为什么使用Hugo

版本兼容性更好

之前是有用过Jekyll,过了一段时间会有一些升级问题。配置过于复杂,不集中。

使用Hugo,你可以集成多个主题,主题之间的切换,只是在config.yaml / config.toml 里修改主题即可。

这是由于主题的原始文件是存放在themes,而内容与资源文件是有单独的位置存放。做到数据与模版隔离的

Hugo-File-Tree

怎样使用Hugo

以下的例子是使用以下主题作为例子 hugo-refresh

环境的安装

官方提供hugo的命令工具,我们可以使用以下的命令来安装hugo的命令工具

1
2
3
4
5
6
7
8
9
> brew install hugo

// 命令行会自动输出以下内容
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core and homebrew/cask).
==> Downloading https://homebrew.bintray.com/bottles/hugo-0.54.0.mojave.bottle.tar.gz
Already downloaded: /Users/bep/Library/Caches/Homebrew/downloads/ba894b1dba33feb6be39bf955a7e84f8f40dd8f558f5058e569a0bc21ecc5c19--hugo-0.54.0.mojave.
bottle.tar.gz

再者输入以下的命令,查看是否hugo的工具已经可以投入使用

1
> hugo version

创建你的博客工程项目

使用以下的命令,可以创建出一个博客工程项目。可以先用cd进入到你要存放的位置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// vince的部分 类似一个文件夹名,你可以自定义自己的博客工程根目录名称
> hugo new site vince

// 以下是命令行的输出
Congratulations! Your new Hugo site is created in /Users/vince.zheng/Documents/github/Vince.

Just a few more steps and you're ready to go:

1. Download a theme into the same-named folder.
Choose a theme from https://themes.gohugo.io/ or
create your own with the "hugo new theme <THEMENAME>" command.
2. Perhaps you want to add some content. You can add single files
with "hugo new <SECTIONNAME>/<FILENAME>.<FORMAT>".
3. Start the built-in live server via "hugo server".

Visit https://gohugo.io/ for quickstart guide and full documentation.

安装主题

我们需要完成以下几步:

  1. 进入博客的根目录
  2. git初始化
  3. 添加主题的仓库到git的submodule里
  4. 添加主题设置到hugo工程的配置文件(博客的根目录有个config.yaml是博客的基本配置文件)
1
2
3
4
5
6
7
8
9
10
11
12
13
// 第一步:进入博客的根目录
cd vince【此处填写你自己博客工程的名称】

// 第二步:git初始化
git init

// 第三步:添加主题的仓库到git的submodule里
// 命令的是这样组装:git submodule add 【主题的git下载地址】 【最终存放主题的位置,`themes/`这个前缀是必须的,hugo会从`themes/`目录下寻找主题的文件】
git submodule add https://github.com/PippoRJ/hugo-refresh.git themes/hugo-refresh

// 添加主题设置到hugo工程的配置文件(博客的根目录有个config.yaml是博客的基本配置文件)
// 先普及:博客的配置文件存放(根目录/config.yaml),主题的例子配置文件存放(根目录/themes/主题目录/exampleSite/config.toml or 根目录/themes/主题目录/exampleSite/config.yaml)
// 将主题里面的默认配置文件拷贝到博客的配置文件

创建第一篇文章

hugo提供一个命令可以执行创建文章的markdown


官方的Quick Start例子
1
hugo new posts/my-first-post.md

此方法会导致如果想换总菜单的logo变得异常困难,yaml里面的路径的根目录是文章的名字再拓展的


建议采用以下的方式

1
> hugo new 一级目录(会在主页右上角展示,建议用于分大类上)/文章的标题(会自动创建成文件夹)/index.md

此时就会创建出你需要的markdown文件用于发布文章。存放在 Hugo工程目录/content/一级目录/文章标题/index.md


我的例子 比如我的一篇文章地址路径:vince/content/一级目录/文章标题/index.md

文章的进阶了解

一篇文章的文件存放目录

可能你会疑惑:下图中logo照片如何设置,请看YAML设置的例子

一篇文章的目录结构

YAML设置

YAML内供多种属性的设置。常用的属性有哪些呢?请看下方


YAML是什么,在哪里? [YAML是什么可以点开此链接查看。](https://www.ruanyifeng.com/blog/2016/07/yaml.html) YAML所处的位置,在文章开头,被两行`---`所包围

YAML配置项目


YAML例子
1
2
3
4
5
6
title: "Hugo搭建博客"
date: 2019-11-17T11:55:53+08:00
draft: true
tags: ["Hugo", ]
summary: "教你如何从0到1搭建hugo博客"
summaryImage: logo/hugo-logo.png

如何发布

发布到Github

使用你的github账号,创建一个工程。比如我在GitHub上的用户名叫jsonseng。那博客我需要创建一个叫 jsonseng.github.io 的工程。然后将此工程关联到本地目录的Repository

可以通过执行下面的命令

1
2
3
4
5
6
7
8
> cd Hugo工程目录
> git submodule add `Repository地址` public

// 执行发布操作,此时会把所有的文件导出到 public 目录
> hugo

> cd public
> // 执行git操作,把内容push到GitHub上

过几分钟后,可以打开你的博客地址(地址:https://你的用户名.github.io )

TiledLayer

iOS TiledLayer性能报告

设备 LSTiledLayer平均耗时 CATiledLayer平均耗时 时间减少占比 处理器
iTouch5 9.3.5 0.1569 0.304 54.11% A5
iPad mini 9.3.5 0.1395 0.6558 78.73% A5
iPad Air 10.2.1 0.1337 0.2848 53.05% A7
iPhone 6s 10.2.1 0.0515 0.1091 52.80% A9
iPhone 7 10.2.1 0.0409 0.0928 55.93% A10

==项目地址==

优点(相比CATiledLayer)

1、兼容更多的API

​ 内部是使用最简单的CALayer作为其组成原理,最基础的组成。这里说的兼容更多的API,想要举例的是iOS7 drawViewHierarchyInRect,此API在实际真机使用上,“只有一开始渲染的第一屏幕可以截获到图片”,如果滚动一定距离后,进行截图就存在截取到的是一张漆黑的照片。但是对于CATiledLayer本身针对大图滚动情况下的性能优化,必然存在需要滚动的情况。如果开发时,需要快速截图,用此方法只能截取到黑屏照片。

​ 本身截图是一个很耗内存,CPU的操作。drawViewHierarchyInRect虽然官方没有明说,但是经过多次使用,会发现它相比renderInContext要更为合理,renderInContext是会触发drawRect把内容绘制到指定的context,其实相当于重新绘制一次,而drawViewHierarchyInRect并不会触发drawRect,从此可猜测是从显存中获取图源信息渲染成图片。而且==此API可以在子线程获取图片,简直神器。==

2、绘制方面情况

下面图表基于此绘制的计算时间

IMG_1408

平均绘制时间

平均减少时间占比

==内部使用合适的算法,高速回收已使用的模块,使内存申请控制在最节省的范围内。超出屏幕的会立即被回收使用到新的区域绘制。合理的并发线程,让CPU尽可能的发挥==

缺点(相比CATiledLayer)

1、内存增长

​ 凡事有好必然带来相应的坏,CATiledLayer内部的实现可能使用压缩的图片,从contents为CAImageProvider上猜测。但是使用LSTiledLayer,由于内部是CALayer,最基本的元素,由于产生了寄缩图,可以想象成为未压缩的图片。如果每块的大小在256 x 256,每一个父层Layer的scale为1的情况下,根据数据统计,在Retina显示屏下,基本满屏的LSTiledLayer,相比系统CATiledLayer内存要多1.5MB。非Retina情况下,1MB左右。

敬请期待

​ 后续会加入主线程切换绘制,CATiledLayer,在为了绘制流畅的同时不影响用户操作,此时引入了次线程绘制,延迟显示。但是对于某些交互情况下,用户并一定高频交互,更加注重视觉时,如果延迟显示,可能存在增加用户焦虑等待的情绪。比如一打开屏幕的时候,想立即看到内容效果。如果此时引入了主线程绘制,是否会让一切更友好,适当的时候改回子线程绘制。所以在接口上,引入线程切换的功能。