2021年4月20日 星期二

Windows 命令提示的 ssh 功能

早上在上 GCP 線上課程時聽老師說現在 Win10 的命令提示字元視窗已經具備 ssh 功能, 所以不需要 Puttty 也可以進行 ssh 遠端連線, 聽完馬上連線鄉下那台 Pi 3, 確實可用 :

開啟命令提示字元視窗後輸入 ssh 出現 usage 提示訊息表示已具備 ssh 功能 :

Microsoft Windows [版本 10.0.19041.928]
(c) Microsoft Corporation. 著作權所有,並保留一切權利。

C:\Users\User>ssh   
usage: ssh [-46AaCfGgKkMNnqsTtVvXxYy] [-B bind_interface]
           [-b bind_address] [-c cipher_spec] [-D [bind_address:]port]
           [-E log_file] [-e escape_char] [-F configfile] [-I pkcs11]
           [-i identity_file] [-J [user@]host[:port]] [-L address]
           [-l login_name] [-m mac_spec] [-O ctl_cmd] [-o option] [-p port]
           [-Q query_option] [-R address] [-S ctl_path] [-W host:port]
           [-w local_tun[:remote_tun]] destination [command]

查看信箱中 Pi 每小時發送的最新外網 IP 為 1.254.23.172, 前面冠上 Pi 3 的使用者名稱 pi 與 @ : 

C:\Users\User>ssh pi@1.254.23.172    
The authenticity of host '1.254.23.172 (1.254.23.172)' can't be established.
ECDSA key fingerprint is SHA256:vt1QdJr4cBlAzcqsvRZaqbee04gAuygn4M4CHn5X100.
Are you sure you want to continue connecting (yes/no)? y   (要回答 yes, 不能只用 y)
Please type 'yes' or 'no': yes    
Warning: Permanently added '1.254.23.172' (ECDSA) to the list of known hosts.
pi@1.254.23.172's password:    (輸入密碼)
Linux raspberrypi 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Linux raspberrypi 4.14.79-v7+ #1159 SMP Sun Nov 4 17:50:20 GMT 2018 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Mar 23 20:30:39 2021 from 1.172.127.60
pi@raspberrypi:~ $ pwd    
/home/pi
pi@raspberrypi:~ $

雖然不錯用, 但我覺得還是 Putty 功能較多較好用, 例如 Putty 可以設定 log 紀錄操作過程, 也可以直接圈選複製螢幕內容, 而命令提示字元視窗則較陽春.

2021年4月19日 星期一

如何設定 EditPlus 執行以 Python 程式

EditPlus 編輯器輕量且介面簡潔, 不管是編輯 C, Java, PHP, 還是 Python 程式我都是用此軟體. 今天找到下面這篇文章, 可以設定在 EditPlus 內執行 Python 程式, 不需要另開命令提示字元視窗 : 


設定方法如下 :

1. 點選 Tools 功能項底下的 Configure User Tools ... :




2. 按右上角的 "Group Name" 鈕, 在彈出視窗的 New 欄位填入群組名稱例如 Python, 按 OK :




3. 按 Add Tool 鈕, 選 Program, 在底下的 Menu Text 欄位填入功能表上遇顯示的名稱, 例如 Run Python, 在 Command 欄位填入本機 Python 執行檔位置; 在 Argument 欄位填入 $(FileName), 在 Initial Directory 欄位填入 $(FileDir), 在 Action 欄位勾選 Capture output, 在 Save 欄位勾選 All Open Files, 然後按 OK 即可 :





經過以上設定後就可以開啟一個 Python 檔案試試看, 這時在 Tools 功能表底下就會出現我們在上面設定中於 Menu Text 欄位中所填入的 Run Python, 點選它就會執行開啟中的 Python 程式 : 





雖然現在為了上傳 MicroPython 程式改用 Thorny, 但我覺得 EditPlus 還是很好用. 

2021年4月18日 星期日

互動藝術創作平台 openprocessing.com

最近在玩 p5.js 玩出興趣了, 在 "p5.js 快速上手" 這影片中得知有 openprocessing.com 這個互動藝術創作平台, 可以在上面製作互動藝術作品, 加入會員可儲存作品與同好分享, 但當我點首頁的 join 按鈕請請帳號, 卻發現填寫欄位被遮住無法填寫 :




但如果改用手機瀏覽加入會員之網頁就不會有這問題, 可以順利填寫姓名, email, 以及密碼 :





此網站應該是紐約大學維護的, 在 "Discover" 頁面收納了非常多學生作品 : 


例如下面這個名為 "Woobly Swarm" 的作品就很有創意 : 





載入後乃一片黑空空如也, 用滑鼠點擊頁面會迸出非常多互相碰撞的球, 越點球越多, 球與球之間的互動空間也越擠, 充滿了物理特色, 我很喜歡.

2021 年第 16 周記事

好快, 又一周了. 最近好幾天沒看到住家大樓的管理組長上班, 詢問主委才知組長已辭職, 組長待我們家甚好, 若有掛號包裹, 我下班一進電梯就用對講機通知, 看我從大門進來也會按鈕預先幫我開門, 真是一位貼心又盡責的組長, 這麼熟居然沒告知 (今年才偶然知道原來她是高樹阿姨小女兒婆家那邊的大嫂). 聽主委說是因為大樓有些住戶很刁, 弄得組長大嘆不如歸去, 這我也有同感, 有些住戶真的很無禮也很無禮, 遇到這我也很無言. 

今天上市集經過種子行買了 30 株空心菜與兩株絲瓜苗 (每株 20 元), 黃白玉米各 10 株回來種, 雖然現在水情吃緊, 但鄉下家屬水源地, 用水還是不愁的. 綠波蘿剛收完, 以後不再種此菜, 因味道偏苦不爽口, 差大陸妹甚遠, 可惜現在大陸妹不好種. 現在我菜園主力試茄子與空心菜. 

鄉下小雖貓周二下午產子, 爸說是三隻, 它把小貓仔都刁到側門出去的小餐廚內哺乳. 原想這三隻小貓將來怎處理, 週四打電話時爸就說一早起來開側門就發現三隻小貓仔全給咬死了散置在餐櫥外的地上, 大腿處皆有撕裂傷口, 只好拿去菜園埋了. 爸說小雖貓看起來很沒勁, 叫它吃飯都不來. 我週六回到鄉下飯後調監視器影像, 卻發現正對小餐櫥的車棚攝影機紅外線夜視功能喪失, 僅白天可看到影像, 回看周三晚上至周四早上都一片黑壓壓, 又沒聲音, 所以也不知三隻小貓仔是給甚麼咬死的. 決心找時間來更換車棚攝影機, 並添加側門一支小米的. 

今年大門口與車庫旁這兩棵波蘿蜜結果大噴發, 特別是車庫旁這棵每年都果實碩大, 本周爸已摘兩顆送到農會寄台北果菜市場拍賣, 一顆過熟在樹上裂開只好自行處理, 摘出七八包果肉塞滿冰箱上層, 今晚回高雄得待些出去請峰大師與仲仔幫忙消耗掉才行. 農會說不要太熟採摘, 因為怕運送過程被壓傷, 近九分熟就可以摘了. 據國中同學阿潤師說他去年給農會收一公斤有到 50 元, 之前掮客來代收一公斤最多 10 元, 價差 5 倍賺翻了, 難怪這麼熱心來收.



 
傍晚幫爸採下一顆大波蘿蜜, 很重需要兩個人才有辦法讓它安全落地, 一個人割, 另一個人托住, 若沒托好摔落地面保證裂開. 好不容易塞進紙箱過磅, 總重 27.5 公斤, 若能賣到每公斤 50 元, 則這顆價值 1375 元! 目前樹上還有 20 多顆, 哇, 今年波蘿蜜進帳粗估可達 3 萬元以上, 快逼近一分田的田租了, 而且這還是無本經營, 無農藥, 無肥料. 

下午看天候似乎要下雨了趕緊去種菜苗, 沒想到才剛到菜園就下起來了, 哇, 太好了, 終於有雨了, 戴著斗笠在雨中種菜感覺還不錯. 然後拿梯子到路邊給芒果樹套袋, 過年正好是花期都沒下雨, 花開得非常茂盛, 但結果率卻甚低, 我今天買了一包 100 張袋子幾乎包完, 但往年路邊這幾棵要用掉兩包約 200 張, 我猜應該是授粉出問題, 今年蜜蜂跟果蠅竟出奇的少, 大氣變化不只是格陵蘭冰棚融化而已, 昆蟲似乎也在消失中 ~~~.




本周閒暇時間都在玩 p5.js 功能測試, 越玩越有趣, 沒想到工程師也能透過 p5.js 跟藝術扯上邊. 但我還有要事要做 (今年主要任務是 Python 與機器學習), 預計下周再花點時間弄完動態圖之後就要暫時收兵啦, 互動藝術等要事辦完再來大玩特玩一番. 

"對待生命, 你不妨大膽一點, 因為我們終究要失去它" (尼采). 

試做芋香米粉

今年春節後咱單位難得恢復喝春酒, 在福華吃了芋香米粉念念不忘那滋味, 默默記下米粉湯裡吃到的配料, 回家上網查詢食譜, 覺得做法不難, 參考 :


材料表 :
  1. 新竹米粉 1 包
  2. 乾木耳 數片
  3. 乾蝦仁 1 把
  4. 五花肉 1 小塊
  5. 芋頭塊 (用火鍋料的即可)
  6. 蒜苗 1~2 條
  7. 芹菜 1 把
  8. 油蔥酥 1 湯匙
  9. 白胡椒粉
備料 :
  1. 乾木耳浸軟後切條備用 (去除根莖)
  2. 乾蝦仁浸軟後備用
  3. 蒜苗切段後備用
  4. 芹菜切細後備用
  5. 五花肉切薄片或切細條備用
  6. 米粉浸水軟化瀝乾備用
作法 :
  1. 起油鍋, 木耳與蝦仁先下鍋炒香, 再放入蒜苗, 五花肉續炒. 
  2. 等肉片八分熟加水至超過佐料再高一些, 放入芋頭塊開大火煮滾換中火.
  3. 用筷子戳芋頭, 若已軟放入米粉, 加鹽, 油蔥酥, 芹菜, 白胡椒粉等調味, 約煮 2~3 分鐘讓芋頭香入味即可.
中午試做結果非常滿意, 味道有到福華的七成滋味 :








等母親節姐姐回來高雄再做一次唄. 

2021年4月17日 星期六

Chart.js 新版 v3.1.0 釋出

去年 9 月對 chart.js 2.9.3 版做過初步測試後就擱一邊了, 最近發現 Chart.js 持續發展更新, 現在已經釋出 3.1.0 版了, 在效能方面比第二版有長足的改進, 而且也重寫了動畫功能, 參考 : 


本系列之前的文章參考 :


新的 v3.1.0 版函式庫下載網址為 :


下載 chart.js-3.1.0.tgz 解壓縮後, 將其中 dist 子目錄下的 Chart.min.js (180 KB) 或 Chart.js (382 KB) 放在專案目錄下即可. 

也可以直接用 CDN 供檔 :


CDN 模板網頁 :

<!DOCTYPE html>
<html>
  <head>
    <title></title>
    <meta charset="utf-8">
    <meta http-equiv="cache-control" content="no-cache">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <script src="https://cdn.jsdelivr.net/npm/chart.js@3.1.0/dist/chart.min.js"></script>
  </head>
  <body>
    <script>
      //your codes
    </script>
  </body>
</html>

等搞定 p5.js 後再來玩 Chart.js, 官網教學文件參考 :


好站 : p5.js 快速上手 (互動藝術創作)

今天在 Youtube 找到一個介紹 p5.js 的影片 :





這是一個互動藝術程式創作線上課程的募資招生影片, 這位老師展示了 p5.js 的神奇魔力, 看完影片就會迫不及待想要立刻動手用 p5.js 來玩藝術創作. 例如老師於影片中展示的看似外星生物的動態圖作品居然只用了 29 行 p5.js 程式碼 :




這門課目前已在 HaHao 上架 :


這位老師叫做吳哲宇, 是墨雨設計的老闆, 也是藝術創作工程師, 曾留學紐約大學學習多媒體與互動程式創作 (creative coding), 其作品結合藝術與工程, 大大地顛覆了我對傳統對視覺傳達與平面設計的印象 :


藝術更需要工程師, 數學家, 以及物理學家, 看來我要借一本電玩物理學來讀讀了.

2021年4月16日 星期五

p5.js 學習筆記 (五) : Javascript 語法摘要

熟悉前幾篇的 p5.js 基本繪圖技巧後便可進一步來學習繪製動態圖形. 之前我們都只是呼叫 p5.js 的內建函式來繪圖, 完全不需要用到 Javascript 語法來控制, 但對於較複雜或動態的圖形時則需要用到 Javascript 的判斷與迴圈等語法功能, 本篇摘要整理 Javascript 語法, 做為學習 p5.js 動態圖形繪製前複習之用. 

本系列之前的文章參考 : 


以下測試使用之參考文件 : 

# https://p5js.org/reference/ (教學文件)
# https://editor.p5js.org (線上編輯器)

Javascript 教學文件參考 :



1. 基本語法 :

Javascript 語法摘要整理如下表 : 


 語法 說明 範例
 註解不會被執行的說明文字 //這是單行註解
 /*這是多行註解
    繼續註解
    註解結束*/
 識別字有分大小寫, 只能用字母, 底線, 前號, 與數字, 但首字元不能是數字 var c2c;
 var $2a;
 var _foo$;
 基本型態數值 (整數, 浮點數)
字串 (單雙括號均可)
布林 (true/false)
 var i=2; var a=3.14159; var a=6.626e-34;
 var a="foo"; var a='bar'; alert(a.length)  //字串長度
 var a="Hello" + "world";  //字串用 + 串接
 var a=true; var a=false;
 基本物件使用 new 運算子建立之
物件 (有 prototype). 

 var obj=new Object();           //Object 物件
 var s=new String("123");      //字串物件
 var b=new Boolean("true");  //布林物件
 var n=new Number("123");  //數值物件
 var arr=new Array(3);           //陣列物件
 var r=new RegExp("[Jj]avascript", "g");   //正規式物件
 var date=new Date();           //日期物件
 var f=new Function("a", "b", "return a+b");   //函式物件
 也可用對應之包裹器函式建立物件 (去掉 new 即可)
 全域屬性
 與方法
不須建立物件即可使用 infinity : 無限大  
 NaN : 非數值  
 undefined : 未定義
 isNaN() : 檢查 a 是否為非數值 (true/false)
 isFinite(a) : 檢查 a 是否為有限值 (true/false)
 運算子算術運算子
關係運算子
邏輯運算子
位元運算子
指定運算子
條件運算子 
 +,  -,  *,  / (四則運算), % (餘數), ++ (遞增),  -- (遞減)
 >,  <,  <=,   >=,  ==(值),  !=,  === (值與型),  !=== (值或型)
 && (且),  || (或),  ! (非)
 & 且,  | 或, ^ XOR, ~ 非, << 左移,  >> 右移,  >>> 有號右移
 =,  +=,  -=,  *=,  /=,  %=, &=,  |=,  <<=, >>=,  >>>=
 r=b? x: y  (若 b 為 true 則 r=b 否則 r=y)
 判斷if (條件式1) {
    敘述1;
    }
else if (條件式2) {
    敘述2;
    }
else {
    敘述4;
    }
條件式為 true 時執行
(0, none, undefined, 空字串, NaN 為 false)
 //判斷成績等級 A~E
 var score=parseFloat(prompt("請輸入成績:"));
 if (score < 60) {var grade="E";}
 else if (score < 70 && score >= 60) {var grade="D";}
 else if (score < 80 && score >= 70) {var grade="C";}
 else if (score < 90 && score >= 80) {var grade="B";}
 else {var grade="A";}

 分支switch (運算式) {
  case 值1 : {
         敘述1;
         break;
         }
  case 值2 : {
         敘述2;
         break;
         }
  default : {
         預設敘述;
          }
   }
運算式的值可以是 :
1. 數值 2. 字串 3. 布林
當 case 均不符時執行 default, 每個 case 必須以 break 結束.
  var today=new Date();
  var day=today.getDay();
  switch (day) : {
    case 0: {var weekday="週日";  break;}
    case 1: {var weekday="週一";  break;}
    case 2: {var weekday="週二";  break;}
    case 3: {var weekday="週三";  break;}
    case 4: {var weekday="週四";  break;}
    case 5: {var weekday="週五";  break;}
    case 6: {var weekday="週六";  break;}
    default: {var weekday="錯誤!";}
    }
  
 迴圈//for 迴圈
for (初始; 條件; 更新) {
  敘述;
  }
for (鍵 in 物件) {
  敘述;
  }
for (索引 in 陣列) {
  敘述;
  }
for (元素 of 陣列) {
  敘述;
  }
//while 迴圈
while (條件式) {
    敘述; //至少執行0次
    } 
//do 迴圈
do {
    敘述; //至少執行1次
    }
while (條件式);
  //for 迴圈 : 計算 1+2+3+...+10
  var total=0;
  for (var i=0; i<=10; i++) {
    total += i;
    }
  //走訪物件項目
  var obj={'a': 1, 'b': 2, 'c':3};
  for (k in obj) {     //for in 迭代鍵
     var v=obj[k];
     console.log(k + ":" + v);
     }
  //走訪陣列元素   //for in 迭代索引  
  var arr=[1, 2, 3];
  for (idx in arr) {
     console.log(arr[idx]);
     }
  //走訪陣列元素   //for of 迭代元素 (只能用在陣列/字串)
  var arr=[1, 2, 3];
  for (e of arr) {
     console.log(e);
     }
  //while 迴圈  : 計算 1+2+3+...+10
  var total=0;
  var i=0;
  while (i <= 10) {
     total += i;
     ++i;
     }
  //do 迴圈 : 計算 1+2+3+...+10
  var total=0;
  var i=0; 
  do {
    total += i;
    ++i;
    }
  while (i <= 10);  
 函式 function 名稱([參數]) {
   敘述;
   [return 傳回值;]
   }
 參數=原生型態 : 傳值
 參數=物件/陣列 : 傳址
 function sum(a, b) {
    return a+b;
    }
 var s=sum(1, 2);
 物件 {鍵1:值1,  //屬性
  鍵2:值2,  //屬性
  ...
  function:{  //方法
     運算式;  
     }
  }
 obj={a:1, b:2, c: 3}
 var obj={
   firstName:'foo', //屬性
   lastName:'bar', //屬性
   getFullName: function() { //方法
   return this.firstName + ' ' + this.lastName;
   };
 陣列arr.length 陣列長度
建立陣列可在中括號 [ ] 內放以逗號隔開之元素 (literal 法), 或用 new Array(n) 建立 n 個元素之空陣列, 但若傳入 1 個以上整數, 這些整數卻是元素. 
new Array() 只能建立一維陣列, 二維陣列必須使用迴圈. 
 //一般陣列
 var arr=['a', 'b' ,'c'];   //建立一個 3 元素之陣列
 var arr=new Array(); //建立不定長度之空陣列
 var arr=new Array(3);    //建立一個長度為 3 的空陣列
 arr[0]='a'; //新增元素
 arr[1]='b'; //新增元素
 arr[2]='c'; //新增元素
 var arr=new Array(1, 2, 3);   //建立內容 [1, 2, 3] 之陣列
 var arr=new Array('a', 'b','c');  //建立一個陣列 ['a','b','c']
 //二維陣列
 var arr=[[1, 2], [3, 4]]    //建立 2*2 陣列
 var arr=new Array(2);
 for (var i=0; i<2; i++) {   //建立 2*2 空陣列
   arr[i]=new Array(3);
   } 
 arr[0][0]=1; arr[0][1]=2; arr[1][0]=3; arr[1][1]=4;
 //關聯式陣列
 var fruit={"apple":"蘋果", "papaya":"木瓜"};
 alert(fruit["apple"]);  //蘋果


條件運算子有兩種寫法, 一是運算結果指派給單一變數的, 例如 :

r=(a >= 60) ? "pass" : "fail"

另外一種是問號後面有兩個運算式的, 例如 : 

(a >= 60) ? r="pass" : r="fail"

for in 可用在陣列與物件, 迭代的對象是陣列索引或物件之鍵 (key, 屬性); for of 迴圈只能用在陣列, 迭代的對象是陣列元素. 陣列的 forEach() 方法也可以用來走訪陣列, 迭代之對象為元素. 


2. 輸出入函式 :

Javascript 用來輸出資料的方式有下列四種 (可用來除錯或輸出) :


 Javascript 輸出方式 說明
 alert(str) 在輸出視窗中顯示變數 str 之值
 document.write(str)  在網頁內容 (body) 輸出變數 str 之值
 document.getElementByID(myID).innerHTML(str) 將 id=myID 的網頁元素內容以 str 取代
 console.log(str) 在瀏覽器主控台輸出變數 str 之值


從使用者取得資料的輸入方式有兩種 :


 Javascript 輸入方式 說明
 prompt(msg [, default]) 彈出輸入視窗, msg=提示訊息, default=預設值, 傳回值為字串型態
 confirm(msg)  彈出確認視窗, msg=詢問訊息, 傳回值為 true (確定)/false (取消)


注意, prompt() 的傳回值是字串, 在進行計算前應該呼叫下列函式進行轉換 :


 型態轉換函式 說明
 parseInt(s) 將傳入參數轉成整數, 傳回整數或 NaN, 例如 parseInt("3.14")
 parseFloat(s) 將傳入參數轉成浮點數, 傳回浮點數或 NaN, 例如 parseFloat("3.14")


3. 字串操作 :

Javascript 內建包裹函式 String() 可將其他物件轉成字串物件, 其 length 屬性表示字串長度 (字元數), 常用的方法如下表 :


 字串物件的方法 說明
 toLowerCase() 將字串中的英文字母轉成小寫
 toUpperCase() 將字串中的英文字母轉成大寫
 charAt(index) 傳回字串索引 index (0 起始) 之字元
 charCodeAt(index) 傳回字串索引 index (0 起始) 之字元的 unicode 編碼
 fromCharCode(c) 傳回 unicode 編碼為 c 的字元, 例如 "".fromCharCode(65) 傳回 'A'
 indexOf(str [, index]) 傳回從 index 開始找尋子字串 str 第一次出現的位置, 未找到傳回 -1
 lastIndexOf(str) 傳回從字串尾端向前找尋子字串第一次出現之位置, 未找到傳回 -1
 match(str) 從頭開始搜尋子字串 str, 找到傳回 str, 否則傳回 null
 search(str) 與 indexOf() 功能相同, 但 search() 可傳入正規式, indexOf() 不可
 replace(str1, str2) 將字串中的子字串 str1 全部以 str2 取代, 傳回結果字串
 split(str) 以子字串 str 分割字串, 成功傳回陣列, 失敗傳回字串本身
 substr(index,length) 從索引 index 開始取出長度 length 的子字串傳回
 substring(a, b) 從字串索引位置 a 開始至 b-1 取出子字串傳回 (a, b 不可為負)
 slice(a, b) 從字串索引位置 a 開始至 b-1 取出子字串傳回 (a, b 可為負)
 concat(str) 將子字串 str 串接到字串後面之後傳回
 repeat(n) 將字串重複 n 次後傳回 (ECMA 6)


注意, 用 split() 以跳行為界拆分字串時可用 split("\n"), split("\n\r")  或 split("%0D%0A"). 

另外還有如下與網頁文字格式相關的字串物件方法 (有些在 HTML5 已不支援) :


 字串物件的方法 說明 HTML5
 anchor() 傳回錨點標籤 :  <a>字串</a> O
 big() 傳回放大字型文字標籤 : <big>字串</big>  X
 blink() 傳回閃爍文字標籤 : <blink>字串</blink> X
 bold() 傳回粗體文字標籤 : <b>字串</b> O
 fixed() 傳回打字機格式文字標籤 <tt>字串</tt> X
 fontcolor(color) 傳回字型文字標籤 : <font color="color">字串</font> X
 fontsize(size) 傳回字型文字標籤 : <font size="size">字串</font> X
 italics() 傳回斜體文字標籤 : <i>字串</i> O
 link(url) 傳回超連結標籤 : <a href="url">字串</a> O
 small() 傳回縮小字型文字標籤 : <small>字串</small> O
 strike() 傳回刪除文字標籤 : <strike>字串</strike> X
 sub() 傳回上標文字標籤 : <sub>字串</sub> O
 sup() 傳回下標文字標籤 : <sup>字串</sup> O


4. 陣列操作 :

Javascript 最常用的資料型態為陣列, 其 length 屬性表示元素之個數, 陣列物件之方法如下 :


 陣列物件的方法 說明
 push(e) 將元素 e 放入陣列尾端 (新增元素)
 pop() 取出陣列最後一個元素傳回並從陣列中刪除該元素
 shift() 取出陣列第一個元素傳回並從陣列中刪除該元素, 其餘元素往前移
 unshift(e1, e2, ...) 將元素 e1, e2, ... 依序放入陣列最前面 (從索引 0), 原來元素往後挪
 slice(a, b) 將陣列索引 a 至索引 b-1 之元素 (不含索引 b) 組成子陣列傳回
 splice(a, n) 將陣列索引 a 開始的 n 個元素刪除, 其餘元素往前移
 join(str) 將陣列全部元素以 str 字串串接後傳回 (字串)
 toString() 將陣列全部元素以逗號 "," 串接後傳回, 等於 join(",")
 sort([f]) 將陣列全部元素依字串值 (或比較函式 f 之傳回值) 遞增排序
 reverse([f]) 將陣列全部元素依字串值 (或比較函式 f 之傳回值) 遞減排序
 indexOf(e) 傳回元素 e 的索引, 若 e 不存在傳回 -1
 forEach(function(e){}) 透過匿名函式走訪陣列元素


5. 數學函式 :

Math 物件是 Javascript 較特殊的內建物件, 它沒有建構函式, 而是直接用 Math 調用其屬性與方法 (Math 類似 Java 中的靜態類別), 其屬性定義了常用之數學常數如下表 : 


 Math 物件之屬性 說明
 Math.E 自然指數 e=2.718281828459045
 Math.LN2 2 的自然對數=0.6931471805599453
 Math.LN10 10 的自然對數=2.302585092994046
 Math.LOG2E e 以 2 為底之對數=1.4426950408889633
 Math.LOG10E e 以 10 為底之對數=0.4342944819032518
 Math.PI 圓周率=3.141592653589793
 Math.SQRP1_2 1/2 的平方根=0.7071067811865476
 Math.SQRT2 2 的平方根=1.4142135623730951


Math 物件的方法 :

 Math 物件的方法 說明
 Math.max(a, b) 傳回 a, b 中較大者
 Math.min(a, b) 傳回 a, b 中較小者
 Math.abs(a) 傳回 a 之絕對值
 Math.pow(a, b) 傳回 a 的 b 次方
 Math.sqrt(a) 傳回 a 的平方根
 Math.round(a) 傳回 a 的四捨五入到整數
 Math.ceil(a) 傳回 a 的無條件進位到整數
 Math.floor(a) 傳回 a 的無條件捨去到整數
 Math.sin(a) 傳回 a 的正弦值
 Math.cos(a) 傳回 a 的餘弦值
 Math.tan(a) 傳回 a 的正切值
 Math.asin(a) 傳回 a 的反正弦值
 Math.acos(a) 傳回 a 的反餘弦值
 Math.atan(a) 傳回 a 的反正切值
 Math.exp(a) 傳回 a 的自然指數值
 Math.log(a) 傳回 a 的自然對數值 (以 e 為底)
 Math.random() 傳回 0~1 的隨機數 (精度 : 小數點後 16 位)


常用的數學技巧 : 

常用對數 (以 10 為底) =Math.LOG10E * Math.log(a)
0~100 之亂數=Math.floor(Math.random() * 100)
四捨五入到小數點後一位=Math.round(a * 10)/10
四捨五入到小數點後兩位=Math.round(a * 100)/100   
四捨五入到小數點後三位=Math.round(a * 1000)/1000
求商=Math.floor(a/b) 


6. 正規表達式 :

Javascript 的正規式有兩種表示法 :
  • 斜線表示法 : 正規式用前後斜線包圍, 例如 var reg=/Javascript/i;
  • 建構式表示法 : 呼叫內建函式 var reg=RegExp("Javascript", "i"), 
其中 i 為比對方式, 共有三種 :
  • i : 不分大小寫
  • g : 全部比對
  • ig 或 gi : 不分大小寫全部比對
正規表示法定義如下之特殊字元用來表示特定之字元與其排列方式 : 


 特殊字元 說明 範例
 . 比對換行 \n 以外的任何字元 a.b 匹配 a1b, acb 
 ^ 比對字串的開始位置 ^ab 匹配 abc, 不匹配 cab
 $ 比對字串的結束位置 ab$ 匹配 cab, 不匹配 abc
 * 比對前一個字元或分組出現 0 次以上 ab* 匹配 a, ab, abb, abbb
 + 比對前一個字元或分組出現 1 次以上 ab+ 匹配 ab, abb, abbb
 ? 比對前一個字元或分組出現 0 或 1 次 ab? 匹配 a, ab, 不匹配 abb
 {m} 比對前一個字元或分組剛好出現 m 次 ab{2} 匹配 abb, 不匹配 abbb
 {m,} 比對前一個字元或分組至少出現 m 次 ab{2,} 匹配 abb, abbb, 不匹配 ab
 {m, n} 比對前一個字元或分組出現 m~n 次 ab{2, 3} 匹配 abb, abbb, 不匹配 abbbb
 \ 跳脫後面的特殊字元, 以一般字元處理 a\+ 匹配 a+bbb
 [] 匹配括弧內的任一字元 [abc] 匹配 12a34, 7cb54a
 [-] 匹配 - 前後範圍內之任一字元 [a-z] 匹配任一小寫字母
 [^] 匹配不是 ^ 後面所列舉之任一字元 [^a-d] 匹配任一不是 a, b, c, d 之字元
 () 匹配括號內正規式者為一群組 a(.+)b 匹配 a2b, 不匹配 ab
 \d 匹配數字, 等於 [0-9] [\d] 匹配任一數字字元
 \D 匹配非數字, 等於 [^0-9] [\D] 匹配任一非數字字元如 W, a, ...
 \w 匹配字母, 數字, 底線, 等於 [a-zA-Z0-9_] \w 匹配 a, A, 0, _
 \W 匹配非 \w, 等於 [^a-zA-Z0-9_] \W 匹配 !, @, + 等
 \s 匹配空白字元, 等於 [\f\r\n \t\f] (含空格) [a\sb]+ 匹配 a bc 中的 a b
 \S 匹配非空白字元, 等於 [^\f\r\n \t\f] [a\S]+ 匹配 a bc 中的 abc
 \b 匹配英文字的邊界 \bm\w 匹配 monday 之 mo
 \B 匹配非英文字的邊界 \w\Bm 匹配 mommy 之 mm 
 \cX 匹配控制字元 X \cM 匹配 Cntl+M
 \xhexXX 匹配 16 進制 ASCII 編碼 XX 之字元 \xhex41 匹配字元 A
 \ooctalOO 匹配 8 進制 ASCII 編碼 OO 之字元 \ooctal81 匹配字元 A
 \n 匹配換行字元 
 \r 匹配回車字元 (carriage return) 
 \t 匹配定位字元 (Tab) 
 \v 匹配垂直定位字元 
 \f 匹配換頁字元 (form feed) 


這些特殊字元中 ^ 與 ? 都各有兩種不同用法, 容易混淆 :
  • 正規式的多重量詞 * 或 + 預設是貪婪比對, 亦即會比對出最多字元, 但只要在重複量詞 * 或 + 後面添加? 即可改成懶惰比對, 即匹配字元越少越好.
  • ^ 字符放在中括號內表示 Not (非, 否定) 意思, 但在中括號外則表示字串的開始位置.
正規式的搜尋比對可用 RegExp 物件或 String 物件的方法, 但取代則需使用 String 物件之 replace() 方法 :


 RegExp 物件方法 說明
 reg.test(str) 用 RegExp 物件 reg 比對字串 str, 比對成功傳回 true, 失敗傳回 false
 reg.exec(str) 用 RegExp 物件 reg 比對字串 str, 將匹配的所有子字串以陣列傳回

 String 物件方法 說明
 str.search(reg) 用 RegExp 物件 reg 比對字串 str, 傳第一次出現位置之索引 (否則 -1)
 str.match(reg) 用 RegExp 物件 reg 比對字串, 將匹配的所有子字串以陣列傳回
 str.replace(reg, str1) 用 RegExp 物件 reg 比對字串, 將匹配的部分以 str1 取代


市圖還書 3 本

本周市圖還書 3 本 : 

如何切換桌上型網頁與行動網頁

上個月湘雲老師委託我幫她設計個人網站, 以便放置客家話語音處理研究資料, 但前陣子我還在忙自己的進度沒時間動手, 只協助填寫學校的一些申請表單而已, 一個月過去也該著手處理了. 先構思網站架構, 弄出雛形了再遠端連線安裝伺服器.

由於現在使用手機比使用電腦上網的頻率來得高, 所以初步決定桌上型以及行動網頁分開, 桌上型可能使用 jQuery UI 或 Bootstrap, 行動網頁則使用 jQuery Moble. 也有可能全部使用 Bootstrap 來做. 先實驗一下分開的做法, 即連線首頁時要能自動分辨客戶端所使用之裝置, 以決定要切換到桌上型還是行動網頁. 

我參考了下面這兩篇文章 : 

# JS判斷使用者用PC還是手機來瀏覽網頁

解決方案其實很簡單, 就是使用正規式去比對 navigator.userAgent 屬性值是否含有 "Android", "iPhone" 或 "iPad" 等字串來判定客戶端為行動裝置. 作者的設想周密, 列了非常多行動裝置種類, 但現在市場就是 Android 與 iOS 的天下, 所以我覺得不需要那麼多, 只要考慮 Android 與 iOS 系統就好. 網站首頁 index.htm 可以這麼寫 :

<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Test</title>
</head>
<body>
  <script>
    if (navigator.userAgent.match(/Android/i)|| 
       navigator.userAgent.match(/iPhone/i) ||
       navigator.userAgent.match(/iPad/i)) {
      window.location.href="mobile/index.htm";
      }
    else {window.location.href="desktop/index.htm";}
  </script>
</body>
</html>

做法就是呼叫字串的 match() 方法去比對正規式, 若含有 "Android", "iPhone" 或 "iPad" 等字串就將 location 物件的 href 屬性設為位於 mobile 子目錄下的行動網頁首頁 index.htm, 其內容為 :

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Test</title>
</head>
<body>
  這是行動首頁
  <script>
  </script>
</body>
</html>

否則網頁就導至 desktop 子目錄下的桌上型網站首頁 index.htm, 其內容為 :

<!doctype html>
<html>
<head>
  <meta charset="utf-8">
  <meta http-equiv="cache-control" content="no-cache">
  <meta name="viewport" content="width=device-width,initial-scale=1">
  <title>Test</title>
</head>
<body>
  這是桌上型首頁
  <script>
  </script>
</body>
</html>

整個網站的目錄結構如下 :




我將雛型架構上傳到 GitHub 網站測試可正常切換桌上型與行動網頁 :


我分別用三星 Note8, iPad2, 以及筆電瀏覽器存取結果如下 : 


三星 Note8 Chrome 瀏覽器


蘋果 iPhone 8 Safari 瀏覽器


蘋果 iPad2 Safari 瀏覽器



Acer Swift 5 Chrome 瀏覽器