工作上遇到需要在浏览器展示PDF文件,于是找到了Mozilla开发的PDF.js。玩了一下,结论是,直接使用其自带的示例是简单的方法。

PDF.js的官网:https://mozilla.github.io/pdf.js/
github项目页面:https://github.com/mozilla/pdf.js

主要是没找到有用的开发文档,而自己也不会Node.js的开发。所以尝试自己写的页面,只能利用HTML 5的canvas展示PDF内容。官方自带的示例,会把PDF转换成HTML,并且有显示目录、缩略图、打印、等各种实用的功能,媲美很多完整的PDF阅读软件。

这里记下写过的页面,可以翻页、放大缩小:

<h4>显示PDF</h4>
<p>
    <button id="prePage">上一页</button> <input type="text" id="curPage" value="" readonly /> <button id="nextPage">下一页</button>
    <br />
    <button id="zoomIn">+</button> <input type="text" id="zoomScale" value="1" readonly /> <button id="zoomOut">-</button>
</p>
<p>
    <canvas id="the-canvas" style="border: 1px solid black; direction: ltr;"></canvas>
</p>

<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
<script src="/js/pdfjs/pdf.js"></script>
<script>
//加载PDF按钮
pdfjsLib.GlobalWorkerOptions.workerSrc = '/js/pdfjs/pdf.worker.js';//自己的路径

var loadingTask = pdfjsLib.getDocument('/pdfjs/docker.pdf'); 
var pdfDoc = null;
var totalpage = 0;
var curPage = $("#curPage");
var zoomScale = $("#zoomScale");

loadingTask.promise.then(function (pdf) {
    //加载指定界面(第一页)
    pdfDoc = pdf;
    totalpage = pdfDoc.numPages;
    getPage(1);
});

function getPage(pageNum) {
    if(pageNum < 1) {
        pageNum = 1;
    } else if(pageNum > totalpage) {
        pageNum = totalpage;
    }
    setCurPageNum(pageNum);
    pdfDoc.getPage(pageNum).then(function (page) {
        //var scale = 1;
        var viewport = page.getViewport({ scale: getZoomScale() });
        var canvas = document.getElementById('the-canvas');
        var context = canvas.getContext('2d');
        canvas.height = viewport.height;
        canvas.width = viewport.width;
        var renderContext = {
            canvasContext: context,
            viewport: viewport,
        };
        page.render(renderContext);
    });
}

function makeThumb(page) {
    // draw page to fit into 96x96 canvas
    var vp = page.getViewport(1);
    var canvas = document.createElement("canvas");
    canvas.width = canvas.height = 96;
    var scale = Math.min(canvas.width / vp.width, canvas.height / vp.height);
    return page.render({canvasContext: canvas.getContext("2d"), viewport: page.getViewport(scale)}).promise.then(function () {
        return canvas;
    });
}

function loadThumb() {
    var pages = []; while (pages.length < pdfDoc.numPages) pages.push(pages.length + 1);
    return Promise.all(pages.map(function (num) {
        // create a div for each page and build a small canvas for it
        var div = document.createElement("div");
        document.body.appendChild(div);
        return pdfDoc.getPage(num).then(makeThumb).then(function (canvas) {
            div.appendChild(canvas);
        });
    }));
}

function getCurPageNum() {
    return parseInt(curPage.val());
}
function setCurPageNum(pageNum) {
    return curPage.val(pageNum);
}
function getZoomScale() {
    return parseFloat(zoomScale.val());
}
function setZoomScale(scale) {
    return zoomScale.val(scale);
}
$("#prePage").click(function(){
    var pageNum = getCurPageNum() - 1;
    getPage(pageNum);
})
$("#nextPage").click(function(){
    var pageNum = getCurPageNum() + 1;
    getPage(pageNum);
})
$("#zoomIn").click(function(){
    var scale = getZoomScale();
    scale = Math.round((scale + 0.2) * 100) / 100;
    scale > 2 && (scale = 2);
    setZoomScale(scale);
    getPage(getCurPageNum());
})
$("#zoomOut").click(function(){
    var scale = getZoomScale();
    scale = Math.round((scale - 0.2) * 100) / 100;
    scale < 0.6 && (scale = 0.6);
    setZoomScale(scale);
    getPage(getCurPageNum());
})
</script>

最近接触了两款开源、跨平台、支持多种SQL数据库的数据库管理工具,值得记录一下。

DBeaver
官网:https://dbeaver.io/
2020年疫情期间,在家办公,想找个数据库管理工具,可以在Linux上访问SQL Server数据库,于是遇到DBeaver。界面像Eclipse,容易上手;基于Java,可以跨平台使用;使用JDBC,几乎支持所有数据库。在Linux上,几乎是万能的数据库管理工具了。

HeidiSQL
官网:https://www.heidisql.com/
在Windows上安装MariaDB 10.4.12时,发现自带了HeidiSQL数据库管理工具。界面及操作都跟MySQL Workbench相似,清晰明了,而且支持各种SQL数据。比较意外的是,其基于Delphi开发,所以Linux上需要利用Wine运行。

顺德双皮奶,作为代表家乡的特色甜品小吃,一直深受本人喜爱,只是会吃不会做。近来几乎每天都买水牛奶给孩子补充营养,于是尝试做一下,原来也很简单。主要是以前错误以为第一层奶皮需要技巧弄上去,实际是物理原理,脂肪会浮在水面上。所以,只要弄到水牛奶,再简单弄一下就能吃到双皮奶了。

材料(两碗份量):

  • 水牛奶:250g
  • 蛋清:50g(大概一只鸡蛋的蛋清)
  • 糖:12g(可根据口味增减)

做法:

  • 1,水牛奶煮开,平均倒入两个碗内。放凉,让第一层奶皮形成。
  • 2,轻轻拨开奶皮,倒出牛奶,并让奶皮留在碗里。
  • 3,鸡蛋分离出蛋清和蛋黄。倒出的牛奶,加入蛋清和糖,搅拌均匀至混合。
  • 4,牛奶和蛋清混合物,用筛网过滤一下(去除杂质,让口感更滑),再平均倒回两个碗里。
  • 5,碗上盖上小碟子(或者保鲜膜、锡纸之类,还是小碟子比较环保)。待蒸锅水沸后,放上去蒸7到10分钟(我是8分钟)。
  • 6,蒸好后,放凉到接近体温再食用。夏天可以放冰箱冷藏后食用。

Google Camera(简称gcam)自推出以来,一直是最喜爱的摄影应用(可惜后来变成Pixel机型专属应用)。幸好有开发者移植到其它机型,特别是像红米Note 4X那种渣拍照的手机,极大提升了拍照能力。近来在红米K30 5G上也装上了gcam,并默认开启了“动态照片(Motion Photo)”功能。本来没啥影响,只是拍出来一堆文件名以MVIMG开头或者扩展名前带有“.MP”的照片,昨天好奇研究了一下,才发现就是动态照片。

动态照片,简单来说,就是把拍照前几秒录下视频,并把视频与拍出来的照片整合在一起,生成一个jpg文件。目前发现两种格式:文件名后面带有“.MP”的,在EXIF信息里会说明mp4文件在整个jpg文件中位置;文件名以“MVIMG_”开头的,jpg文件里有个“ftypmp4”标识,该标识后面的数据就是mp4文件。

其实动态照片也没什么坏处,但是找了一圈也找不到可以直接浏览动态图片的Android应用。如果是看不到的视频,那保存在照片中,有什么意义?还浪费了存储空间,也不利于分享、传输。最后找了个工具,叫GoMoPho,把所有拍摄的动态照片都转为普通jpg文件。其实就是把动态文件切割为jpg和mp4两个文件,我保留了jpg并删除了mp4。GoMoPho的相关网址如下:

Google motion photos video extractor.
https://github.com/cliveontoast/GoMoPho

GoMoPho虽然只有命令界面,但是支持上面提到的两种动态照片,而且已移植到多种操作系统,还能支持批量处理文件夹的文件。

这是个简易葡挞食谱。网上的视频看到的,简易的地方是,利用比葡挞皮更容易买到的手抓饼来做。试着做了一下,并修改了材料份量,效果还不错。

1. 材料(做6个的份量)

  • 原味手抓饼 1块
  • 鸡蛋 1个
  • 牛奶 80克
  • 白糖 15克

2. 做法

  • 1)制作挞皮。手抓饼解冻,卷起来,平均切成6份。搓圆,摊在蛋挞模具上,做成碗状。
  • 2)制作挞液。鸡蛋打散,加入牛奶和白糖,搅拌至白糖融化。然后过筛,去除杂质,带来更细滑的口感。
  • 3)挞皮倒入挞液,8分满即可。挞液会在烤的时候涨起,太满会溢出,导致挞皮容易糊。
  • 4)烤箱预热10分钟,200摄氏度中层烤20分钟。挞皮金黄,挞液有焦糖色,即可出炉。

3. 总结

  • 1)鸡蛋尽量选小的,如果是比较大的鸡蛋,要减少牛奶的份量。
  • 2)手抓饼一定要选原味的。毕竟没人想吃带葱的葡挞吧。
  • 3)出炉后,要放凉一下才能吃。主要是怕烫嘴(笑)。

今天烧烤时,顺便烤了板栗,非常成功!记录一下经验吧。

1. 材料

  • 小板栗 120g左右(一人一次的份量)

2. 做法1

  • 1)小板栗洗干净,用刀切个开口,大概二分之一周长。一般用刀砍下去,板栗没有分成两半,而是粘在刀上,就可以了。砍板栗的教程,具体可以参考李子柒于2020-10-10发布关于中秋节的视频,在12:46处(笑)。
  • 2)开水里煮10分钟。
  • 3)从水中捞出放烤盘里,烤箱预热后,以190摄氏度烤10分钟。注意不要烤糊,烤到板栗外壳干脆即可,这样更容易剥开。
  • 4)这个做法,可以用微波炉代替烤箱。但是板栗处理不好的话,容易爆炸(喷得微波炉内壁到处都是板栗碎),不推荐。

3. 做法2

  • 1)小板栗洗干净,用锡纸包好。用竹签戳一个小洞,用于排气。
  • 2)放在碳炉(烧烤炉)上,大概烤半个小时到1个小时。
  • 3)由于锡纸把板栗里的水分都锁住,所以做出来不会变得太硬,非常好吃。

4. 注意

  • 1)选用个头小的小板栗,是因为更容易熟,做起来少费点时间。
  • 2)板栗一次不能多吃。其淀粉含量比较高,多吃容易导致消化不良(例如放屁量增多)。

作为MIUI恐惧者,无奈LineageOS官方没有支持这台红米K30 5G,只能诚惶诚恐地使用欧版MIUI。直到某天发现了Resurrection Remix OS官方支持这款手机,才终于脱离MIUI。

查了资料,才知道Resurrection Remix OS是基于LineageOS的一款开源ROM,基本体验与LineageOS一致,并增加了很多设置(基本上是界面的,个人感觉用途不大),适合喜欢原生Android的用户。

LineageOS的优点基本继承了,总结一下缺点吧:

  • 1)国内支付应用,基本不能使用指纹支付。历史原因,一直遗留下来的问题。跟LineageOS一样。
  • 2)关屏后不能双击屏幕打开锁屏界面
  • 3)不能双击桌面锁屏。可以设置双击任务栏或者三大金刚键进行锁屏。
  • 4)不能拍摄6400万像素的照片。ROM自带相机和Google Camera移植版,最高都只支持1610万像素。不过即使是MIUI的自带相机,拍出来的6400万像素照片基本直出(纯粹自我安慰)。
  • 5)刚开始使用,比较耗电。做了一些优化后,后面变得相对省电一点。不过,这手机本身也不怎么省电。
  • 6)长时间使用的应用,容易自动退出。比如Chrome开个视频后,很大几率会自动关掉并回到桌面。可能是电源管理自动优化吧。

总的来讲,曾经的LineageOS用户可以放心刷,也没有遇到影响日常使用的bug 。

刷机过程,跟LineageOS一样。重点还是那句:刷机前先备份好数据。Recovery备份分区(刷机失败时可以还原系统) + Ti Backup备份应用(用于迁移应用及数据)。

1. 下载相关数据

2. 刷机

  • 备份数据。最好连sdcard的数据也备份一下
  • wipe手机,即Recovery格式化data分区
  • 解锁、刷recovery
  • 刷ROM
  • Recovery里Root系统
  • 刷Opengapps
  • 清cache
  • 重启进入系统

要注意,进入系统后,需要连Google验证。

3. 耗电优化的处理。当前的节电设置如下:

  • a)屏幕刷新率设为 60Hz,在“设置”->“系统”->Device-specific settings->Minimum Refresh Rate。120Hz屏幕其实很丝滑,但60Hz确实够用。
  • b)关闭 5G 网络,只用 4G 。设置移动网络的首选网络类型为“LTE/WCDMA”。当前来说,5G除了耗电比较快,没感受到什么优势。
  • c)限制应用使用电量。在电池管理器设置受限应用。目前设了 Google Play 商店。
  • d)关闭 Google 账户的自动同步功能,只开启了 Chrome 和 Gmail 。
  • e)冻结了一些不常用但不可缺的应用。冰箱、Shelter 、island 等。其中 island 的名称太中二,个人接受不了而放弃。用 Shelter 的话,如果工作空间的应用没用到 GMS,最好冻结它,并尽量安装非无依赖 GMS 的应用。

动画《放学后海堤日记》第10集,提到吃不完的竹荚鱼做成一夜干,不仅很好吃,还能提高存储时间。对这个做法很好奇,于是周末试了下,果然很惊艳!

虽然一夜干可以用新鲜鱼和冰鲜鱼,但是为了避免失败而造成的浪费,选用了太阳鱼(无细骨的淡水鱼)。最后烤制时,用了烤箱代替炭炉。

材料:

  • 太阳鱼 1条
  • 清水 500ml
  • 盐 50g

做法:

  • 1,太阳鱼削鳞,从背部开刀,去鳃、清理内脏、清理黑膜,清洗干净。
  • 2,清水和盐配成10%浓度的盐水,放入鱼,浸泡30分钟到1小时。盐水放入适当的米酒,可以去腥。
  • 3,从盐水取出鱼,用厨房纸吸干表面水份,放入冰箱过夜。
  • 4,从冰箱取出鱼,再次吸干表面水份。烤箱最高温度(我的是230°C)预热10分钟后,把鱼放最上层,烤大约20分钟,烤至表面金黄即可。烤的过程要适时翻面。鱼皮那面先朝上来烤,再翻面,可以烤出完整的鱼皮。

由于浸泡盐水和烤炙,鱼肉的水份大部分流失,使得鱼的鲜味浓缩,所以吃起来味道很棒!

由于贪便宜,上一部手机红米Note4x(代号:mido)买了3G内存+32G存储的版本,导致用了两年半就内部空间不足。即使插上128GB的TF卡,并转为内部存储,也要面对偶尔出现的SD卡错误,导致装在卡上的应用不能运行。抓狂……然后CFO的批准下,一起换了红米K30 5G(代号:picasso)。

这个时间点,要换手机,就肯定选5G网络的了。然后,考虑高性价比,能解BL锁,能刷第三方ROM,就剩下红米了。最后在K30i 5G与K30 5G之间,选择了拥有主摄6400万像素的K30 5G。低配版6GB + 128GB,目测用3年应该没问题。

关于此手机的一切说明,可以参考这个文章:
老妈钦点,我买了一部Redmi K30 5G版
https://pockies.github.io/2020/03/27/redmi-k30-5g/

按照文章的刷机操作,就是手机绑定小账号、解BL锁、刷recovery、刷欧版MIUI、折腾流氓应用。但是解锁后直接刷最新版Recovery,进去时会黑屏。参考了网上的经验分享,需要先刷旧版Recovery,然后刷ROM,再刷新版Recovery。由于该Recovery自带Magisk,所以不用单独下载。相关软件如下:

1)小米官方解锁工具
https://www.miui.com/unlock/index.html

2)非官方TWRP Recovery
https://mifirm.net/model/picasso.ttt#twrp
旧版:TWRP-3.4.0B-0209-REDMI_K30_5G-CN-wzsx150-fastboot
目前最新版:TWRP-3.4.2B-0623-REDMI_K30_5G-CN-wzsx150-fastboot

3)欧版MIUIv12
https://sourceforge.net/projects/xiaomi-eu-multilang-miui-roms/files/xiaomi.eu/MIUI-STABLE-RELEASES/MIUIv12/

简单的刷机流程是:刷旧版Recovery,格式化Data分区,刷入欧版MIUI,双清,在Recovery刷入最新版Recovery后,再进入Recovery进行root,重启进入系统。

刷完欧版ROM,我选择了冰箱(主要冻结无用的系统App,曾经买了付费版) + Island(主要是使用工作空间隔离流氓App,并且能进行冻结)结合使用。由于Shelter不能在MIUI上运行,只能暂时使用Island(缺点是没有自动冻结,用起来没有Shelter顺手)。

用了一段时间,一开始感觉是比较耗电,渐渐感觉跟红米Note4x差不多。已调低屏幕刷新率60mHz,没什么感觉。玩过Minecraft,手机发烫比较严重,耗电也比较快。

希望后面能刷上LineageOS。但是XDA-Developers上的网友说,小米官方一直没更新这手机的kernel源码,导致第三方系统不能完善。目前也就先这样了。

上周五下班前,明天去潮汕吧。于是,就在潮州度过了周六日两天。

本来的潮汕(潮州和汕头)之旅,为了避免赶路,改为呆在潮州。由于没有做好规划,浪费了不少时间。例如3次进出牌坊街(潮州最热闹的1地方)、没有住到有特色的旅馆、没有一条很好的吃货路线等。不过第一次随缘去玩,也是挺特别的。

关于交通
当前国内交通的发达,不仅体现在高铁的建设,还有多种交通工具和形式的补充。例如从潮汕站下高铁,两个人,打个顺风车到牌坊街,才20几块。超级方便舒适便宜!

还有,潮州市内遍布各种共享单车、助力车、电动车,不管回酒店,还是逛完逛完整个古城,都是很方便。不过如果骑了没有避震的车,最好不要走那些老旧的路,否则会颠簸到怀疑人生。

关于住宿
由于说走就走,我们计划先订个“7天酒店”(周六才100一晚),到了后边逛边找。但由于是周六,古城内的客栈民宿都订满了,最后还是睡了“7天”。

看了下,牌坊街的小巷子里、广济门城楼南面的城墙下,都有很多有当地特色的客栈民宿,都能很方便地游玩古城(潮州最热闹的地方了吧),而且当无所事是时,可以在大堂喝着功夫茶。当然,价格要比“7天”贵(一晚200以上吧)。

关于吃
虽然声称潮州有超级多的地方小吃,而且很有特色,但吃起来不是很香。大部分都是油炸的,而且口味有点重(偏咸),大热天的,对不上胃口。

大概参考了这篇攻略:
潮州吃不停之——24小时美食指南
https://m.mafengwo.cn/gonglve/ziyouxing/65034.html

最佳的入口,应该是环城西路与西马路交叉处附近的“镇记牛杂店”,来碗中份的牛杂粿条。因为一般到潮州都接近中午了,先稍稍填一下肚子,再沿西马路一路吃过去。

点评一下吃过的那些。

粿条。比河粉软、粘一点的粉条。对于追求爽滑的人来说,吃不惯。一般以汤底配上牛肉丸、牛杂或牛肉等。

笋粿。据说要指定季节才能吃到。就是用米粉做的皮,包着竹笋、虾米等馅料的饺子。笋带来爽脆的口感。

春卷。虾米、猪肉、绿豆做成馅料,外皮包着油炸,个人比较喜欢。偏咸。

咸水粿。米粉做的迷你“钵仔糕”,碗形,中间凹进去的地方,放着咸菜。咸菜的油能流出来,整体口感是爽口弹牙。

蚝煎。“伟舅牛肉丸”那店里吃的。生蚝的个头相对比较大,入口即化,要是能少放点盐,能1给90分以上。

海石花。外形和1口感都是啫喱,而且毫无味道,需搭配糖、芋丸、红豆、牛奶、各种水果等来做成甜品。冰冻后,很好吃。

豆花。甜品。老板说不是普通的豆腐花,但吃起来就是豆腐花。

功夫茶。古城里很多茶馆,走累了可以进去坐坐,喝口茶。

牛肉火锅。吃的是广济门附近的“阿彬牛肉火锅”,人均100,顾客超级多,但吃起来没什么惊喜。也许是吃过澳洲和牛,就感觉这牛肉没什么味道。应该是牛肉脂肪含量比较少的原因吧。

关于玩
主要就是古城内外游玩了。数不尽怕牌坊的牌坊街、感觉只是个大水塘的潮州西湖、潮州古城墙、广济门城楼、广济桥和湘子桥等,都是打卡的好地方。

总体来说,潮州是个值得一去的地方,可以发掘广东的另一面。