2019年4月29日 星期一

HTML5 : 筆順編輯工具

2019年4月29日 星期一
教育部「常用國字標準字體筆順學習網」(以下簡稱「筆順網」) 中收錄了 4808 個國字的筆順,而那些不在這 4808 個字內的國字,如果想要練習筆順怎麼辦呢?

最近因為國語課本中有個生字「粄」不在筆順網的收錄範圍內,為了它,我開發了一個小工具,可以利用它來下載有筆順的其它字,再將「粄」所需要的筆畫拼接起來,就這樣無中生有造出和筆順網相同格式「粄」的筆順資料了。

姑且就叫這個「html5_strokeeditor」 小工具為「筆順編輯工具」。這個工具的網址如下:



當然囉!因為教育部並沒有開放我們將造好的新字上載到主機儲存,所以造出的筆順還是無法使用筆順網來練習。不過,可以利用我開發的新版筆順練習工具來載入自己造的新單字。新版的筆順練習工具,網址如下:

如何利用「筆順編輯工具」造出「粄」這個字呢?

分析部件

由於我們是利用筆順網已有的字來「重組」成新的字,所以在開始「造字」前,得先來分析一下新單字需要哪些筆畫,哪些字中帶有那些筆畫。

以「粄」來說,它可拆成左側的「米」和右側的「反」兩個部件,因為要放兩部件,所以「米」可能需要稍小一點點,才不會和右偏旁的「反」重疊。

綜合上述的需求,「米」我們可以取結構上分左、中、右三部件的「糊」,再結合結構上分為左、右兩部件的「版」。「版」的「反」這個部件會稍小一點點的。這樣應該就有機會造出一個比例適當的「粄」囉!

下載筆順

根據分析部件後的結果,想要造出「粄」這個字,我們需要下載「糊」和「版」兩個字的筆順。

打開「筆順編輯工具」後,在下載的對話框中,輸入想下載筆順的字後,按「開始下載」的按鈕。

之後如果還想再下載別的字,可以按一下右下角的工具箱開關,打開工具箱以後,按一下「下載筆順」的圖示,即可出現下載筆順的對話框。


選擇筆畫

筆畫是有順序的,「筆順編輯工具」怎麼知道哪個筆畫先寫,哪個筆畫後寫呢?

因為筆順網的筆畫有其習慣上的書寫順序,而我們在造字時,其實是依習慣切分的部件,一個筆畫、一個筆畫來選取,所以一個字中,同一個部件的,筆畫順序應該會按照原有的順序。

那不同字的,哪一個要優先呢?以造「粄」這個字需要「糊」的「米」,和「版」的「反」,取出的「米」和「反」,哪一個會先寫呢?

為了解決筆順的順序,「筆順編輯工具」是以著色的方式來選取所需要的筆畫(原本白色或灰色的筆畫,按一下會被塗色,表示已選擇該筆畫;反之,已有塗色的則會被取消),同一顏色的會被當作同一組(同一部件)。此外,因為顏色是有其優先順序的(請注意「色盤」上的編號),所以最後會依顏色的順序來結合成成新單字。

底下以「粄」這個字為例,說明它是如何「造」出來的:
  1. 選取「編號 1 」的顏色。
  2. 點選「糊」中屬部件「米」的所有筆畫。
  3. 選取「編號 2 」的顏色。
  4. 點選「版」中屬部件「反」的所有筆畫。



照上述的順序來換色並點選所需要的筆畫,最後就可以讓新單字「粄」,擁有正確的全字筆順了。不但如此,連部件的設定,也一併設定完畢了。

匯出單字

在「筆順編輯工具」造好的字,可以在右下角的工具列中,找到「匯出單字」的工具。打開後,輸入新筆順是哪個單字,即可匯出一個 .json 的檔案。匯出的檔案,日後可以重新匯入,這樣就不用再重新造字了。





因為目前教育部的筆順網並無法讓我們自行擴充筆順字庫,所以目前只能將造好的筆順,用個人開發的筆順工具來展示並練習。



進階使用

筆順編輯工具除了直接將現有的筆畫或部件拼接以後,也有提供將筆畫移動、縮小和放大的功能。由於只要新增或減少新字的筆畫,移動和縮放的設定都會重置,所以建議想移動或是縮放前,得先確認所需要的筆畫都已增、刪好了,以免「前功盡棄」。

無論搬移或是縮放的功能,操作的程序都是先按一下想進行的功能鈕,然後拖曳想調整的筆畫或是按一下調整的筆畫。以縮放的功能來說,每按一下想調整大小的筆畫,都會放大或縮小為原來的 5%。

有了搬移和縮放的功能,相信大家可以創造出更多字的筆順了。

下面是製作「闁」這個字的簡單示範影片:


相關網站


更新記錄

  • 2019.05.04 加入由儲存在 localStorage 的資料載入的功能。
  • 2019.04.28 加入將造的字移動、縮放的功能。
  • 2019.04.23 可依填入的顏色區分筆畫的順序。
  • 2019.04.20 初版


HTML5 : Unscramble 重組小遊戲

Unscamble 重組小遊戲可以依字串分割設定,出題時,將句子或字詞分成好幾個部份,再以亂數把順序打亂,最後讓玩家將它們依正確的順序排好。

此外,為了避免玩家卡關,出題時也可以在題庫中加入提示用的文字、圖片或是語音。語音的部份如果不想自己錄語音檔,目前可以使用 Google 的 TTS 替代。

試玩與下載

Unscamble 可以在我的 HTML5 FUN 網站中找到,

試玩:

下載:

《範例一》是英文句子重組的遊戲

本範例會先自動播放提示的語音,以 TTS 或是MP3聲音檔來唸出全句。

操作時,先點一下要換位置的字卡,再點一下另一張字卡,兩張字卡就會交換位置。如此兩兩交換,直到正確為止。


《範例二》是英文單字重組的遊戲

本範例不會先自動播放提示的語音,玩家想聽單字的語音時,可以自己按左下角的語音播放鈕。單字提供中文的文字提示,有些甚至還有或圖片的提示。

操作時,先按住要換位置的字母卡不放,將卡片拖曳到要放的位置後,再放開卡片。如此一張張拖、放,直到正確為止。

《範例三》是中文句子重組的遊戲

本範例會先自動以 TTS 來播放全句的提示語音。

操作時,和《範例二》相同,是以拖、放卡片的方式來換位置。

製作自己的重組遊戲

2023.05.16 起,重組遊戲有支援 HTML5 FUN 烘焙機了,如果想快速設計自己的重組遊戲,建議參考並使用這個:


如果需要了解設定參數的細節,則可以繼續閱讀本文以下有關設定檔的段落。

選單設定檔與題庫設定檔

選單設定檔

 「Unscramble 重組小遊戲」在啟動以後,會先載入主設定檔「unscramble_set.js」,接著會載入預設的選單設定檔「unscramble_menu_set.js」,然後依選單設定檔製作選單供玩家選擇,玩家選好後,最後載入題庫設定檔。

選單設定檔裡面的格式很簡單
  • 每一個題庫檔會對應到一行,設定會用一對引號(單引號或雙引號均可)括住。
  • 每一行會以一個半形逗號當分隔符號,將它分為兩個欄位。
  • 每一行的第一個欄位是「項目名稱」,第二個欄位為「題庫設定檔的檔名」。

menu_items = new Array(
//------------------------------------下一行開始為選單增加項目
 '設定範例(英文句子),question_set_example-1.js'
,'設定範例(英文單字),question_set_example-2.js'
,'設定範例(中文句子),question_set_example-3.js'
//------------------------------------選單選項結束,以下請勿修改
);
以上面的設定來說,選單總共會出現三個選項:
  1. 設定範例(英文句子)
  2. 設定範例(英文單字)
  3. 設定範例(中文句子)

按下第一個選項時,程式會打開檔名為「question_set_example-1.js」的題庫設定檔,並出題給玩家玩。同樣的道理,按下第二個選項時,程式會打開檔名為「question_set_example-2.js」;按下第三個選項時,程式會打開檔名為「question_set_example-3.js」。

另外,如果選單項目很多時,可以將它們分類,並建立「次選單」,此部份的機置和我另一個作品 BINGO 是一樣的,在 Blog 中有詳細的說明,可以參考這篇:



題庫設定檔

前面提到的例子,當我們按下範例選單的第一個選單後,「Unscramble 重組小遊戲」會幫我們載入題庫檔案「question_set_example-1.js」,這個檔案是個純文字檔,建議使用純文字的編輯工具來開啟,並修改內容(個人在 Windows 上習慣使用 Notepad++,在 Mac OS X 上使用 Textwrangler ) 。

底下簡單介紹一下 Unscramble 可以自訂的參數。

在開始出題前,遊戲會出現說明畫面,底下是說明對話框相關的設定參數:
  • help_title : 對話框的標題。
  • help_description : 對話框中的說明文字。
  • help_button_caption : 對話框的按鈕。

前面提過,玩家作答時,可以直接將卡片拖曳到要放的位置;或是用按下要選的卡片,再按一下另一張卡,讓兩張卡交換位置的方式。作答的操作方式是由底下的參數所控制的:
  • card_swap_mode : 字卡交換方式。
    0 為用拖曳方式換卡片的位置。
    1 為用按一下指定要交換位置的兩張卡片。

有關對答案的方式,提供一個 enableSubmitButton 的參數,可以用來控制是否出現「送出答案」的按鈕:

  • enableSubmitButton
    true : 玩家按「送出答案」才核對答案。
    false : 卡片換位置後就自動對答案。


有關聲音播放的參數:
  • sound_enabled : 是否播放音效及語音。
    true 播放音效及語音。
    false 不播放任何聲音。
  • sound_autoPlay : 是否自動播放語音。
    true : 出題後自動播放語音。
    false : 使用者按播放鈕後才播放語音。
  • sound_autoPlayLoop : 自動播放的次數。 
  • sound_autoPlayDelay : 隔多久自動重播(單位秒)。
  • tts_enabled : 是否使用 TTS 的語音
    true : 語音採用 TTS 來發音。
    fasle : 不使用 TTS 的語音。
  • tts_is_at_index : 如果使用 TTS ,將題庫中的哪一個欄位的文字轉語音。如果值為 0 ,表示使用左側題目中的文字當要發聲的字串;如果為 1,則是以右側提示欄位中的文字來發聲。
  • tts_language : TTS 選用的語言代碼。
    en : 英文。
    zh_tw : 中文。
  • tts_base_url : TTS 的呼叫網址。

有關題庫的參數:

Unscramble 在出題時,要知道
  • 完整的題目字串是什麼?
  • 怎麼切割字串?
  • 提示是什麼?(可包括文字、圖片、語音)
照這樣看來,每一題題目,我們要:
  • 先切割成題目(第一欄位)和提示(第2, 3, 4欄位,也可不要提示)。
  • 第一欄位中的題目再切成多個字串,變成一張張的卡片。
  • 第 2, 3, 4 欄位中的提示可以是文字、圖片檔檔名或是聲音檔檔名。
照這樣分析,我們只要使用兩個「分隔符號」分別當「第一層」和「第二層」的分割器,就可以符合我們的需求了。先以 「data_seperator」指定的符號分割,再以「split_seperator 」指定的符號進行第二層的分割。

資料分割符號設定:
  • data_seperator : 用來切割題目和提示的分隔符號(第一層)。
  • split_seperator : 用來切割題目子字串的分隔符號(第二層)。
以《範例二》「question_set_example-2.js」中的設定來說明:

它的資料分割符號設定為:
data_seperator = "##";
split_seperator = "~~";
所以「題目」和「提示」、「提示」和「提示」之間是以兩個井字號「##」來切割。
這個題庫是用來進行英文單字重組的,字母和字母之間是以兩個毛毛蟲「~~」來切割。
h~~a~~p~~p~~y##快樂##images/happy.png
a~~n~~g~~r~~y##生氣
c~~r~~y##哭泣

看看第一題是測驗「happy」這個英文單字(註:截圖為 2019 年舊版的題庫格式)




兩個井字號將第一題分為題目:
h~~a~~p~~p~~y

和文字提示:
快樂
與圖片提示:
images/happy.png

題目又以兩個等號分為:「h」、「a」、「p」、「p」和「y」五個字母。
提示也以兩個井字號分為:中文意思的「快樂」,和提示圖片檔名的「images/happy.png」,兩部份。

觀察一下,後面兩題的「angry」和「cry」則都只有中譯的文字提示,沒有圖片提示。

範例二的解說影片



進階設定

如果有需要調整版面的配置,讓題目、提示文字、提示圖片和語音播放器的位置能自訂,就打開主設定檔「unscramble_set.js」依需要調整底下的座標:
  • answer_block_y : 作答區的 y 座標
  • audioPlayer_x : 語音播放器的 x 座標
  • audioPlayer_y : 語音播放器的 y 座標
  • text_hint_x : 提示文字區的 x 座標
  • text_hint_y : 提示文字區的 y 座標
  • image_hint_x : 圖片的 x 座標
  • image_hint_y : 圖片的 y 座標
調整時要注意的是,(0, 0) 的位置是在左上角。而整個版面是最大範圍:
  • X : 1024
  • Y : 768
以上是有關 Unscramble 重組小遊戲的簡單說明。

相關文章


更新記錄

  • 2024.04.01 解決字數很長時,卡片排列偏右的問題;純英文、數字的題目如果字數不超過15個字,但總寬度超過畫面寬度時,字型縮小為原來的 80%,看能不能在一行顯示而不換行。
  • 2023.08.18 題庫支援國字加注音的格式;新增一個即時切換交換字卡方式的選項開關,並調整各功能鈕的位置。
  • 2023.05.16 支援 HTML5 FUN 烘焙機的功能;題庫格式稍作調整,每一題第 2, 3, 4 欄位可以是文字、圖檔或是音檔,「split_seperator」只用來切割第一欄位的題目為卡片內容。
  • 2019.05.21 加入 split_by_length、split_by_length_substring_length:split_by_length 用來設定是否以字串長度來切割子字串,如果設為 true, 題庫第一欄位會以長度來切割;如果設為 false (預設值), 題庫第一欄位會以 split_seperator 的分隔符號來切割。split_by_length_substring_length 則是當 split_by_length 為 true 時, 每個子字串要多長。
  • 2019.05.18 加入 select_questions_in_random、number_of_questions。
    select_questions_in_random:用來控制如何由題庫選題的方式( true:以亂數選題  false:按題庫順序)。
    number_of_questions:設定在亂數選題時,最多選幾題。
  • 2019.05.15 加入 sound_autoPlayLoop、sound_autoPlayDelay ,用來控制語音自動重播的次數。
  • 2019.04.30 加入 enableSubmitButton 的選項。是否使用「送出答案」的按鈕, true : 玩家按「送出答案」才核對答案; false : 卡片換位置後就自動對答案
  • 2019.04.27 釋出。
  • 2019.04.24 明勳建議加入計時器,可在結束時知道花多少時間作答。
  • 2019.01.06 明勳建議不要自動播放語音,可以在需要時再手動播放語音;版面位置調整改為可以設定檔中自行設定。
  • 2019.01.03 測試版。








2019年4月12日 星期五

Python : 用 SimpleHTTPServer 模組建立一個臨時的網頁伺服器

2019年4月12日 星期五
電腦中有安裝 Python ,臨時需要一個 web server 來測試,怎麼辦?

Python 有個  SimpleHTTPServer 模組,用它就可以馬上建立一個臨時的網頁伺服器。哈!要是以前,我一定是去下載 Appache ,然後再重新「複習」一堆設定的設定檔。但為了一個簡單的需求,玩這麼大,還是用最簡單的方法解決就好:

底下以在 Windows 中的操作來說明建立的流程

步驟一:開啟「命令提示字元」(終端機)


步驟一:切換到要當網頁伺服器根目錄的資料夾 (ex. D:\limejs )

cd \limejs


步驟二:啟動  SimpleHTTPServer

python -m SimpleHTTPServer

如果成功,應該可以在畫面中看到底下類似的訊息

Serving HTTP on 0.0.0.0 port 8000 ...

在網頁瀏覽器的網址列中輸入底下的網址:

http://127.0.0.1:8000/

應該就可以看到該目錄中的內容了。


 SimpleHTTPServer 預設是在 8000 port (埠號),如果想更改網頁伺服器監聽的 port,例如,改在 port 80 監聽,就將啟動指令改為:

python -m SimpleHTTPServer 80

如果想關閉伺服器,就按鍵盤的 Ctrl + C 組合鍵。

這個架站皂方法實在簡單,比以前弄半天的 Appache 容易多了!





2019年4月7日 星期日

JavaScript : 讓行動載具文件不要因拖曳動作亂滑動

2019年4月7日 星期日
忘了從哪一個版本起,無論在 iOS 或 Android 上的瀏覽器玩我寫的 HTML5 小工具,按下並移動位置時,整份文件會跟著滑動,這在玩遊戲進行拖曳或畫圖時真是一大困擾。為了解決我的筆順練習工具在寫字或塗鴨時,畫面一直滑動的問題,忘了是在哪裡找到解決的方法是加入底下的程式碼:


document.addEventListener('touchstart', function(e){ return; }, { passive : false });
document.addEventListener('touchmove', function(e){ e.preventDefault(); }, { passive : false });

主要是改變網頁主體的 document 在監聽到 touchmove 事件時,可以不要執行原來滑動的行為,這樣子,使用工具時就不會滑來滑去,不勝其擾。

筆順練習工具在加了前述的語法後,畫面果然就不會亂滑動了;不過,之前想說如法泡製,來解決其它遊戲的滑動問題,將語法複製、貼上,很容易吧!哈~事情總是沒想的簡單。加了語法的遊戲在測試時可以將畫面固定得牢牢的,在利用 LimeJS 的 build -a 指令,把 JavaScript 的原始碼編譯簡化後,滑動的問題還是出現了。當時百思不得其解,試了各種方法,問題仍然存在,最後只好放棄。

昨天在 build 新版的筆順練習工具時,因為加了「-a」參數,想讓程式碼更精簡,有部份功能運作不正常;而不加「-a」參數時又可以使用。讓我聯想到為什麼舊版的筆順練習工具滑動問題得以解決,而新版的在加「-a」去 build 時,又產生滑動問題的原因了。

檢視一下前面兩行程式碼的最後一個參數:

{ passive : false }

這是一個物件,並將「passive」設為「false」,這麼簡單有什麼問題會產生呢?

關鍵就在 LimeJS 是利用 goog Closure optimization 來簡化 JavaScript 的程式碼,所謂的簡化,主要就是將變數、函數名稱 ...... 等變得愈短愈簡單。參考之前這一篇中寫到的:
想要達到程式碼的大小最小化,使用「ADVANCED_OPTIMIZATIONS」,如果沒注意物件存取資料的方式,名稱有可能被改變,導致資料傳遞時會發生失誤。

關於這一點,可以由 build 完的、最佳化後的程式碼看得出來。

1-0 原始碼中用「{ passive : false }」:

document.addEventListener('touchmove', function(e){ e.preventDefault();}, { passive : false });


1-1 未使用「ADVANCED_OPTIMIZATIONS」來 build 後變成:

document.addEventListener("touchmove",function(a){a.preventDefault()},{passive:!1});


1-2 使用「-a」(「ADVANCED_OPTIMIZATIONS」) 來 build 後變成:

document.addEventListener("touchmove",function(a){a.preventDefault()},{ef:q});


註:上面的「q」為 0,可以追到 build 完的程式碼中有「q=!1;」

很明顯的,「-a」參數一加上去,build 完的物件參數名稱「passive」已經被改為「ef」,這樣就無法正確的設定給 document 的 touchmove 事件。


再來看看最後一個參數,在名稱加上一對單引號變成:

{ 'passive' : false }

2-0 原始碼中用「{ 'passive' : false }」:

document.addEventListener('touchmove', function(e){ e.preventDefault();}, { 'passive' : false });


2-1 未使用「ADVANCED_OPTIMIZATIONS」來 build 後變成:

document.addEventListener("touchmove",function(a){a.preventDefault()},{passive:!1});


2-2 使用「-a」(「ADVANCED_OPTIMIZATIONS」) 來 build 後變成:

document.addEventListener("touchmove",function(a){a.preventDefault()},{passive:q});


註:上面的「q」為 0,可以追到 build 完的程式碼中有「q=!1;」

1-0 和 2-0 就只在變數名稱差了一對單引號,但使用引號的名稱讓 2-1、2-2 中的「passive」可以不管在什麼情形下都叫「passive」,始終不改其名。關於這一點,以後可牢牢記住才行,不然真的是除蟲除到地老天荒啊!


 
雄::gsyan © 2009. Design by Pocket