闻心阁

一蓑烟雨看苍生,半壶浊酒笑红尘

Terminology——超炫的Linux终端

使用上了Linux之后,许多事情都要与终端打交道。不知不觉也已经用了好几个终端了。比如Manjaro自带的xfce-terminal、深度终端、Terminator等等,我这种初学者对于终端使用的也就是能敲个命令而已,也就没太在意。但是自从使用了Terminology之后...老夫第一次看见这种玩法。

安装

Manjaro安装相当简单,直接一条命令。

yaourt -S terminology

使用截图

Terminology自带的效果已经让我觉得很不一样了,自定义设置之后,更是炫。我的一个小截图送上:

这只是静态的效果,动态的自己安装体会。

无法输入中文

在使用fcitx的时候可能会遇到中文无法输入的问题。我的解决方法是:编辑.xprofile文件,加入如下代码:

export XIM_PROGRAM="fcitx"
export XIM="fcitx"
export XIM_ARGS="-d"
export GTK_IM_MODULE="fcitx"
export QT_IM_MODULE="fcitx"
export ECORE_IMF_MODULE="xim"
export XMODIFIERS="@im=fcitx"

使用SVG绘制饼图

年前的时候有个需求,要实现一个动态画大饼的效果。地址:退票潮来袭 捡漏最佳时间到

本来并不想做,都要过年了。结果设计师说他见过很多网页都有这效果应该很简单~咱是前端,人家都做出来的效果,那咱也能。。

画大饼原理

要是简单的画个饼倒是好说,SVG的path一下就行,但是要画的饼还会动,就要点小技巧。参考了一下d3.js,梳理出大约的原理是这样的:

使用这种方法做的饼就比较容易动了,我只要控制线长度就好。

动起来

这里还是用到了利用了SVG中pathstroke-dasharraystroke-dashoffset 属性(真是两个好用的属性。。),要动起来借助一下CSS3的animation属性。简单的贴一下代码:

.pie3 {
  stroke: #c7e0ff;
  fill:rgba(0,0,0,0);
  stroke-width: 70;  
  stroke-dasharray: 0,184.725492,0,35.185808;
  stroke-dashoffset: 0; 
}
.pie3Move{
  animation: pie3 3s 1 ease both;
}
@keyframes pie3 {
  50%,100% {
    stroke-dasharray: 0,184.725492,35.185808;
  }
}

相关问题

本来画的还挺快乐的,结果代码提交之后发现Android很卡,IOS相当流畅。又是搞GPU加速,又是更改图层的定位方式,可Android一直在那卡。后来去请教了 伟伟哥哥 ,先是用requestAnimationFrame尝试了一下,仍旧卡。后来 伟伟哥哥 使用了Canvas又实现了一版,无论在Android和IOS,都丝一般的顺滑~,我Fork下的代码地址:http://codepen.io/sailor103/pen/NdMQvQ

使用SVG实现动态签名效果

之前看过的svg动画的相关内容,想起了之前在flash中常见的一种动画--动态写文字。语言乏力,大约就是这么个样子:Flash模仿制作毛笔写字效果动画实例教程,所以就想用svg实现这么一个效果。

实现成这个鬼样子:尹全超-签名

大约思路如下

0.签名

我使用的AI导出的,鼠标画的押效果不好,有条件的直接数位板。

1.SVG动态画线

同样也找到了一篇文章:纯CSS实现帅气的SVG路径描边动画效果

利用了SVG中path的 stroke-dasharraystroke-dashoffset 属性。

这篇文章实现了一个签名的效果,不过不是我想要的。谁签名能一笔画下来。。并且无法保证笔画的有序。

2.CSS3动画结束监听

步骤1中使用CSS3完成了动态画线的效果,为了解决中的笔画有序,就需要监听CSS3中动画结束事件。可以看这篇文章:transitionend,这样我们可以画完一条线,再触发画下一条线。

3.优化时间

一条长的线条画1s,一条短的线条总不能也画1s吧,所以取第一条线做基准,后面的线条根据比例换算时间。

4.没有完成的

整个效果是依赖JS+SVG,而SVG本身是支持动画的,我的理想是实现一个.svg文件就可以实现上面的效果,希望各位大神指教一下。。

IndexedDB使用方法小结

测试了一下IndexedDB。

为什么IndexedDB

cookie 、localStorage 容量小,Web SQL Database被废。

简单使用

常用的数据库的操作方法无非增、删、改、查。在IndexedDB中实现上述4种操作:

  1. 打开数据库 --> window.indexedDB.open方法
  2. 建“表” --> createObjectStore方法
  3. 创建数据库事务并获取指定的“表” --> transaction事务方法 --> objectStore 获取“表”方法
  4. 增删改查操作 --> add添加数据方法 --> get读取数据方法 --> delete删除数据方法 --> put更新数据方法 --> openCursor 遍历数据方法

使用示例

    var db = {};
    var store = {};
    /**
     * open数据库并建“表”
     *
     * open方法是一个异步的过程
     * onsuccess 打开成功的回调
     * onerror 打开失败的回调
     * onupgradeneeded 第一次打开数据库,或数据库版本发生变化回调
     * 还有一种是blocked事件,表示上一次的数据库连接还未关闭
     */ 
    var request = window.indexedDB.open('myDB', '1');
      request.onsuccess = function(openData) {
        db = openData.target.result;
        triggerTransaction();
      };
      request.onupgradeneeded = function(upData) {
        db = upData.target.result;
        if (!db.objectStoreNames.contains('dbtable')) {
          //建表,并设置自动递增的整数作为键名
          db.createObjectStore('dbtable', {
            autoIncrement: true,
          });
        }
      };
      request.onerror = function(e) {
        console.log('open error', e);
      };
      
      /**
       * 创建事务并获取指定的“表”
       *
       * 使用transaction创建事务。
       * 创建事务也是一个异步过程,包含下面的回调。
       * abort:事务中断。
       * complete:事务完成。
       * error:事务出错。
       *
       * 使用objectStore获取指定的“表”
       * 
       */ 
      function triggerTransaction(){
        var t = db.transaction(['dbtable'], 'readwrite');
        store = t.objectStore('dbtable');
        triggerAdd();
        t.oncomplete = function(e) {
          console.log('transaction success.')
        };
        t.onabort = function(e) {
          console.log('transaction abort.');
        };
        t.onerror = function(e) {
          console.log('transaction error.');
        };
      }

      /**
       * 添加数据
       *
       * 使用add方法,有两种状态回调
       *
       * error 添加数据失败
       * success 添加数据成功
       */ 
      function triggerAdd() {
        var flag = 0;
        for (var i = 0; i < 5; i++) {
          var tmpData = {
            name: '测试数据'+i
          };
          var addRel = store.add(tmpData);
          addRel.onerror = function(e) {
            console.log('add error.');
          };
          addRel.onsuccess = function(e) {
            console.log('add successfully.');
            flag++;
            if( flag === 5 ) {
              triggerPut();
            }
          };
        }
      }
      
      /**
       * 修改数据
       *
       * 使用put方法,有两种状态回调
       * error 修改数据失败
       * success 修改数据成功
       */ 
      function triggerPut(){
        var modifyRel = store.put({
          name: '这不是测试数据'
        }, 2);
        modifyRel.onerror = function(e) {
          console.log('modify error.');
        };
        modifyRel.onsuccess = function(e) {
          console.log('modify successfully.');
          triggerDel();
        };
      }

      /**
       * 删除数据
       *
       * 使用delete方法,有两种状态回调
       * error 删除数据失败
       * success 删除数据成功
       */ 
      function triggerDel() {
        var delRel = store.delete(1);
        delRel.onerror = function(e) {
          console.log('delete error.');
        };
        delRel.onsuccess = function(e) {
          console.log('delete successfully.');
          triggerGet();
        };
      }

      /**
       * 获取数据
       *
       * 使用get方法,有两种状态回调
       * error 获取数据失败
       * success 获取数据成功
       */ 
      function triggerGet() {
        var getRel = store.get(2);
        getRel.onerror = function(e) {
          console.log('get error.');
        };
        getRel.onsuccess = function(e) {
          console.log('get successfully.');
          console.log(e.target.result);
          triggerCur();
        };
      }

      /**
       * 遍历数据
       *
       * 使用openCursor方法,有两种状态回调
       * error 遍历数据失败
       * success 遍历数据成功
       */ 
      function triggerCur() {
        var curRel = store.openCursor();
        curRel.onsuccess = function(event) {
          var cursor = event.target.result;
          if (cursor) {
            console.log(cursor.value);
            cursor.continue();
          } 
        };
        curRel.onerror = function(e) {
          console.log('opencursor error');
        };
      } 

上述代码实现了IndexedDB的调用过程,实现了插入、修改、删除、遍历的过程,运行结果可以通过Chrome的控制台查看。

参考

JavaScript中forEach无法遍历空位

说一个小坑吧。

之前在看《JavaScript高级程序设计》的时候,看到这样一句话:“它只是对数组中的每一项运行传入的函数,这个方法没有返回值,本质上与使用for循环迭代数组一样。”(P97)

于是就测试用了一下:

var arr0 = [0,0,0,0,0];
arr0.forEach(function( item,index,array ){
  array[index] = index * 2;
});
console.log(arr0);

结果:

[0, 2, 4, 6, 8]

是对的,我又这样使用了一下:

var arr1 = new Array(5);
arr1.forEach(function( item,index,array ){
  array[index] = index * 2;
});
console.log(arr1);

结果:

[]

好像哪里不对,于是这样写:

var arr2 = new Array(5);
arr2[0] = 0;
arr2[1] = 0;
arr2.forEach(function( item,index,array ){
  array[index] = index * 2;
});
console.log(arr2);

结果:

[0, 2]

这样写呢?

var arr2 = new Array(5);
arr2[0] = 0;
arr2[1] = 0;
arr2[2] = undefined;
arr2.forEach(function( item,index,array ){
  array[index] = index * 2;
});
console.log(arr2);

结果:

[0, 2, 4]

最后在MDN上的找到这样的描述:

forEach() executes the provided callback once for each element present in the array in ascending order. It is not invoked for index properties that have been deleted or are uninitialized (i.e. on sparse arrays).

分久必合,合久必分?

你一定很想知道这篇文章是要写什么的,简单来说,就是把两个博客合并了而已。

很久之前写博客的时候,那时候的域名还是sailor521.com,我经常会在上面发一些技术相关的内容。那个年代博客还没有走向平静,微博微信也仅仅刚刚兴起,于是有幸认识了蛮多的博友,大家经常互相走动,在彼此的博客上留言(现在想想还蛮怀念那段时光)。后来认识的朋友多了,访问量也稍微大了一点,大家一般会在彼此的google reader(是的,还没关)中订阅互相的博客内容,如果有更新互相走一走。这样以来,很多朋友有着不同的技术背景,甚至是没有技术背景,把一些编程之类的内容再放在博客里就不那么合适了。记得一个寒假,一狠心就把sailor521.com给卖掉了,当时的pr有3了我记得。然后把所有的文章分门别类的切到了两个博客里,也就是闻心阁(blog.yqc.im)和LabQ(lab.yqc.im)。

现在已经是各种新媒体的时代了,不管你愿意不愿意承认,博客已经没落了,除了一小部分技术宅开始使用hexo之类的写点技术博客之外,很少再看见当年的那种繁荣了。打开之前的友链,突然发现很多已经404了,即使还在的,估计也像我差不多,半死不活的在那里撑着,从之前的一天一更,到后来的每周一更,写到最后就是一年一更了,如此一来,也就没有分开的必要了,索性把两个博客直接合并了过来,使用的typecho,没有wordpress那种强大的导入导出功能,于是拾起来了好几年没有弄的sql,捣鼓了小半天,就成了现在你们看到的样子。

嗯,以后会怎样嘞?会不会关?也不一定,暂时的情况应该没有什么问题。毕竟这个域名是我最喜欢的,没有之一。也许有些碎碎念还会写,就这样。

那个柔软的好妹妹

公司的电脑换了Linux之后,重新听上了豆瓣FM(说重新,是想起了当年在惠普实习的经历,想起了大神涂伟,想起了杨老大,还有莲姐),还是老样子的FM随机播放,遇到好歌就加个喜欢。正纠结着Flux的时候,一首从未听过却又清新脱俗的节奏传入耳间,顿时神清气爽、心旷神怡,曲毕回味无穷。赶紧收藏下来,细看之,乃好妹妹乐队的《红红的太阳西边儿走》。

more >>

Easy Way to Install Nodejs on Ubuntu 16.04(Useful!!!!)

There are many methods to install on Ubuntu, such as NVM, n, PPA, complie, But if just want to install specific version, it would be easily. Just do as follow.

more >>

Make Koala Works on Ubuntu

Koala is my favorite GUI tools to complie sass and less file, when I switch the OS from Windows 7 to Ubuntu, it not works again. Why?

First of all, I thought it's Ruby's error, maybe there is no Ruby in my system, and run the command:

ruby --version

it outputs

ruby 2.3.1p112 (2016-04-26) [x86_64-linux-gnu]

so it's not Ruby's fault, and then google it I find the solution

32bit:

$ cd /lib/i386-linux-gnu/ or $cd /usr/lib/

64bit:

$ cd /lib/x86_64-linux-gnu/ or $cd /usr/lib64/

run the command

sudo ln -s libudev.so.1 libudev.so.0

it works :-)

Copyright © 2010-2017 闻心阁

返回顶部