顯示具有 rps 標籤的文章。 顯示所有文章
顯示具有 rps 標籤的文章。 顯示所有文章

2009年4月23日 星期四

HSL 色彩空間的視覺效果

接下來的『相關度』和『標籤雲』都會加上 HSL 的方式來處理顏色。在改版發表之前, 可以到我的『HSL 測試頁』先體驗一下。

image 
一般的作法 線性內差 得到的『色彩漸層』中間的部分常常是 灰色
image
但是, 在 HSL 色彩空間 得到的卻是彩虹般的『紅橙黃綠藍』

.

HSL 色彩空間的注意事項

  • 設定的 minColor, maxColor 還是以 RGB 表示的
  • 直接從 .colorHSL = 0, 1, 2 選一個滿意的『視覺效果』就可以了

簡單吧 !!

.

.

好奇寶寶分隔線

是的, 使用者只需要以 RGB 來設定顏色, 程式內部會自動換算 RGB 到 HSL,

如果你還是好奇, 希望以下這些『應用面的觀念』可以幫助進一步了解 ……

  • HSL 和 RGB 色彩空間 (色座標) 有何不同?
  • HSL 和 RGB 色彩空間 為何會影響『視覺效果』?
  • HSL 色彩空間的其他細節

.

最後, 才是給程式設計者的參考資料:

  • HSL 的程式設計參考資料

.

HSL 和 RGB 色彩空間的不同

RGB 色彩空間

  • R : Red = 紅色
  • G : Green = 綠色
  • B : Blue = 藍色

image

類似『直角座標』的方式 

HSL 色彩空間

  • H : hue= 色相
  • S : saturation = 飽和度
  • L : lightness = 亮度

 image

類似『極座標』的方式

此外, 還有和 HSL 類似的 HSV (色相 hue, 飽和度 saturation, 明度 value), 詳情請看  :

096_K書

.

HSL 和 RGB 色彩空間的視覺效果

image 
一般的作法從 青色 RGB=#00FFFF 線性內差到 紅色 #FF0000, 得到的『色彩漸層』中間的部分是 灰色 #808080
image
但是, 在 HSL 色彩空間 得到的卻是彩虹般的『紅橙黃綠藍』

下面的圖示可以幫助理解,

  • 路徑 0 : 一般 RGB 的作法, 兩個顏色的內差路徑常常會經過中間灰色的部份

 

  • 路徑 1 : HSL 色彩空間, 使用角度來表示 hue (色相), 所以內差路徑會呈現『弧線』或 『螺旋線』, 而經過比較多的顏色
  • 路徑 2 : HSL 採用 極座標系統, 所以同樣兩個顏色之間的內差路徑可以有兩個方向

 

image 099_鞭

HSL 色彩空間, 使用角度來表示 hue (色相)

  • R : Red = 紅色 (0度)
  • G : Green = 綠色 (120度)
  • B : Blue = 藍色 (240度)
  • Y:Yellow = 黃色 (60度)
  • C:Cyan = 青色 /青綠色 (180度)
  • M:Magenta = 洋紅色 / 品紅色 (300度)

.

把對應的 RGB 變化也一起畫出來 (在 HSL 測試頁 可以自己輸入顏色)

image
0: 傳統 RGB 運算方式

(左圖)
在簡單的線性內差之下, RGB 一起變化, 產生的視覺效果並不理想


(下左, 下圖)
經過 HSL 的換算之後, RGB 依序變化, 就變得非常精彩 
image
1: HSL不跨過0度
image
2: HSL 經過0度 (紅/紫色)

.

HSL 色彩空間的其他細節

還有一些細節, 不見得每個人都會遇到, 下面先簡單帶過, 建議到我的『HSL 測試頁』去『實際體驗』一下, 會更有感覺, 或是隨時提出來討論

擔心被搞混的人, 就不一定要往下看囉~~

項目

測試參數

  • HSL 採用 極座標系統, 所以同樣兩個顏色之間的內差路徑可以有兩個方向, 目前的定義是
    • 1: HSL 內差路徑不跨過0度
    • 2: HSL 內差路徑經過0度 (紅/紫色)
    • 0: 傳統 RGB 運算方式

任意兩個顏色, 觀察 0, 1, 2 的不同
  • 紅色 (0度) 附近的 紅偏橙 #FFxx00 和 紅偏紫 #FF00xx, 可以產生出不一樣的效果
  • maxColor = (255, 1, 0) 或 (255, 0, 1), 搭配任意的 minColor
  • maxColor = (255, 1, 0), minColor = (255, 0, 1), 或對調
  • 非常接近的灰色 (或黑色), 可以因為 hue (色相) 的不同, 而有不同的效果
  • 任意顏色, 搭配 (33, 32, 32), (32, 33, 32), (32, 32, 33), (33, 33, 32) 或其他不同的灰/黑色

.

HSL 的程式設計參考資料


之前在處理『相關度』和『標籤雲』的顏色時, 就在思考如何呈現出 更理想的『色彩漸層』

當時所使用的方法, 效果雖然還不錯, 但設定上比較麻煩, 也不容易理解。

所以, 除了 依相關度排序的『相關文章』功能 提到 optionRGB = […] 之外, 並沒有做太多的介紹。

這些程式, 都還沒有使用 HSL 色彩空間 來處理顏色

.

後來, 有機會和『標籤文章選台器』的作者 LVCHEN 討論到這方面的問題, 提到或許可以將 色座標改用 HSL (色調,飽和度,亮度), 又不約而同找到類似的 RGB <=> HSL 轉換程式 ……

現在, 在我的程式裡看到的是『改寫的 RGB <=> HSL 轉換函數』, 產生的 HSL 只適合程式內部使用。如果要用作其他用途, 建議還是參考下面的『原出處』:

.

另外, HSL 測試頁 還用到了 JavaScript Vectorgraphics Library 來繪圖

.


(...繼續閱讀.../...CONTINUE...)

2008年9月15日 星期一

觀察 Blogger 版型 CSS 式樣 -- 實例說明

以下起源於和某網友討論到『相關文章點播台 -- RPS 1.0 beta』裡面有關 Blogger 版型的設定, 或者也可以當作『觀察 Blogger 版型 CSS 式樣』的 實例說明

底下的例子, 不見得能適用到每種版型的變化, 但希望能達到一些『給他魚吃, 不如給他釣竿, 教他釣魚』的目的。

使用的工具, 就是 網頁的原始碼, 或是 Firebug ---- 部落客『玩網頁』的『神器』

.

相關文章點播台 -- RPS 1.0 beta』裡面, 提到以下兩個參數, 都和 Blogger 的版型有關 :

  • rpsOpt.LocateBoard -- 相關文章點播台的『顯示位置』
  • rpsOpt.LocateLabels -- 定位標籤資料

.

  • post-footer 實例說明

我的單篇文章內文之後的 'post-footer' 版型是 :

<div class='post-footer'>
<p class='post-footer-line post-footer-line-1'>
image
</p>
<p class='post-footer-line post-footer-line-2'>
<span class="post-labels">
image 
</span></p>
<p class='post-footer-line post-footer-line-3'>

image
</p>
</div>

所以, 下面的參數會設定『相關文章點播台的顯示位置』在 class='post-footer' 『內部的最後面 』:

  • rpsOpt.LocateBoard = ['append', '.post-footer'];
prepend 『內部』的最前面
append 『內部』的最後面
before 『外部』的前面
after 『外部』的後面

除此 CSS (Cascading Style Sheets) 位置表示語法, 還有『.』,『#』, 和 html tag

『.』句號 class
『#』井號 id
開頭都沒加 html tag

.

以下圖示 append, prepend ... 等的位置。一般情況下 before 和 prepend 的結果會很像, append 和 after 的結果會很像。但是在 class='post-footer' 之內的 prependappend 的位置, 會繼承 'post-footer' 的式樣。

[before]
<div class='post-footer'>
[prepend]
image
[append]
</div>
[after]

.

  • 標籤格式 實例說明

我的『標籤』的版型是 :

<div class='post-footer'>
...
<p class='post-footer-line post-footer-line-2'>
<span class='post-labels'>
標籤:
<a href='http://網址/search/label/標籤1' rel='tag'>標籤1</a>,
<a href='http://網址/search/label/標籤2' rel='tag'>標籤2</a>,
<a href='http://網址/search/label/標籤3' rel='tag'>標籤3</a>,
...
</span>
</p>
...
</div>

定位標籤資料 (告訴程式『每一個標籤的 a href』) 就要寫成 :

  • rpsOpt.LocateLabels = ['.post-footer', '.post-labels', 'a'];

不見得每一層都要寫出來, 因為 <div class='post-footer'> 裡面只包了一個 <span class='post-labels'> , 不會有誤解, 不一定要特別去指定 class='post-footer-line post-footer-line-2', 所以就被我省略了。

.

  • 不一樣的版型

某個版型並沒有 'post-footer' , 而是

Posted in 標籤1, 標籤2 by 作者名

<div class="post">
... 內文 ...
<p class="postmetadata">
Posted in
<a rel="tag" href="http://網址/search/label/標籤1">標籤1</a> ,
<a rel="tag" href="http://網址/search/label/標籤2">標籤2</a> ,
by 作者名
</p>
...
</div>
<div id="comments" class="comments">
...
</div>

我會建議將參數改為

  • rpsOpt.LocateBoard = ['append', '.post'];
  • rpsOpt.LocateLabels = ['.post', '.postmetadata', 'a'];

或是

  • rpsOpt.LocateBoard = ['after', '.post', '.postmetadata'];
  • rpsOpt.LocateLabels = ['.post', '.postmetadata', 'a'];

.

先這樣, 以後再補充


(...繼續閱讀.../...CONTINUE...)

2008年7月17日 星期四

相關文章點播台 -- RPS 1.0 beta 測試

前一陣子開始改良『依相關度排序的相關文章』, 現在已經進入beta 測試。

目前取的名字叫『相關文章點播台』-- RPS 1.0 (Related Posts Surf), 相較於 之前從 Abin's Tech Note 那邊修改過來的版本, 主要的不同為 :

  • 以外掛的形式執行, 完全不用改模版, 只要一行就可以安裝
  • 增加換頁功能
  • 增加自訂設定

.

  • 安裝

真的只要一行, 就像底下這樣, 只要在載入 jQuery 之後再執行就可以。程式會找到預設的位置顯示相關文章

<script src="http://eucaly61-java.googlecode.com/svn/trunk/rps-10-mini.js" type="text/javascript"/>

然後, 如果一切順利的話, 就會看到類似底下的畫面

 2008-07-17_214909

.

  • 基本設定

如果沒有順利顯示, 或是位置不如預期, 可以加入以下的參數 :

<script type="text/javascript">

rpsOpt.LocateBoard = ['append', '.post-footer'];
rpsOpt.LocateLabels = ['.post-footer', '.post-labels', 'a'];

</script>

如果你的部落格網址太特別, 或是你想『顯示另一個 Blogger 部落格的相關文章』 , 或是調整每一頁的文章篇數:

<script type="text/javascript">

rpsOpt.blogRoot = 'http://eucaly61.blogspot.com/';
rpsOpt.Lines = 10;

</script>

.

其中 'append', '.post-footer' 表示『顯示位置』的 CSS 設定,

  • 'append', 也可以改成 'prepend''after''before', ---- 和 '.post-footer' 的關係如下所示,
  • 第一個參數如果不是上述四個, 則會視為 CSS 位置表示語法, 並預設為 'append'
  • 再來是 CSS (Cascading Style Sheets) 位置表示語法, 簡單的說, 『.』句號代表 class, 『#』井號代表 id, 開頭都沒加代表 html tag,
  • 可以設定多個 CSS 位置表示語法, 會讓定位更精準, 記得都要加上引號
  • 目前預設『必須剛好』找到一個位置, 才會顯示, 這是為了區別『單篇文章』,『首頁』和『瀏覽日期/標籤』。

如果改為 rpsOpt.LocateBoard = ['.post-footer', '.post-footer-line-1']; 則會顯示在 [B] 的位置。

[before]
<div class='post-footer'>
[prepend]
<p class='post-footer-line post-footer-line-1'>
... 張貼者: XXXX 位於 ... </p> [B]
<p class='post-footer-line post-footer-line-2'> ... 標籤:... </p>
<p class='post-footer-line post-footer-line-3'>
... 這裡不一定每個人都有內容 ... </p>
[append]
</div>
[after]

.

如果上面對了, 至少會顯示『載入中』

2008-07-17_215300

再來是定位標籤資料, rpsOpt.LocateLabels = ['.post-footer', '.post-labels', 'a']; 如果你的模版和下面不一樣, 請自行修改

  • 如果你的『標籤名稱』不是用 <a href="..."> 超連結包住,
    .... 目前暫時無解, 請期待 下一版
<div class='post-footer'>
<p class='post-footer-line post-footer-line-1'>
... 張貼者: XXXX 位於 ... </p> <p class='post-footer-line post-footer-line-2'>
<span class="post-labels">標籤:
<a href="..." rel="tag">標籤名稱1</a>,... </p>
<a href="..." rel="tag">標籤名稱2</a>,... </p>
</span>

.

  • 進階設定

<script type="text/javascript">

rpsDisp.Loading = '相關文章載入中 ...';
rpsDisp.ListHead = '約有 %PostNum% 篇相關文章,以下是第 %PostNumFrom% 至 %PostNumTo% 篇';
rpsDisp.ListLine = '%PostRank% %PostTitle% - %PostDate%';

</script>

可以任意調換順序, 或者如果不想看到日期或相關度, 也可將 %PostRank% %PostDate% 等 拿掉。

<style>
#rpsBoard {
background: #F0F0F0;
border:2px dotted #ccc;
padding: 0px 5px 5px 15px;        /*上 右 下 左*/
margin: 10px 10px 5px 0px;        /*上 右 下 左*/
}
</style>

替相關文章區塊上色 ...., 或 padding, margin 請依版面自行調整。

.

  • 除錯

有問題的話, 可以試試以下的版本, 會有除錯訊息
[+/-] show/hide debug message

<script src="http://eucaly61-java.googlecode.com/svn/trunk/rps-10-debug.js" type="text/javascript"/>

<script type="text/javascript">

rpsDebug.mode = '%blog%label%jsOK%jsOK-full%';

</script>

.

  • To Do

可能的問題, 或預計增加的功能

  • 不同模版的相容性
  • 不同瀏覽器的相容性 (FF3, IE6, IE7, ...)
  • 載成更多 json Feed, 目前每個標籤只載入 20 篇
  • 調整 相關度計算方式
  • 顯示/隱藏文章摘要

想到但不一定會做的

  • 抓取同一網頁的其他資料, e.g. feedjit "Visitors to this page also liked"
  • 顯示每篇文章的標籤
  • 選擇哪些標籤的優先權較高

.


(...繼續閱讀.../...CONTINUE...)

2008年7月2日 星期三

依相關度排序 ---- 更有看頭的『相關文章』功能

.

Correlation 前幾天, 成功實作出『Grazr格中格』的『相關文章』功能, 原本還要繼續嚐試 Google Ajax Search API 或 Google Ajax Feed API ...。不過, 最後還是決定回到『json 加 java script』, 再加上『依相關度排序』---- 希望可以就這麼定案 ----。

不過我猜, 說不定還得請大家投票來決定。

.

下面將介紹 :

  • 遺珠的『相關文章』功能
  • 原始版本的『相關文章』功能 -- Abin's Tech Note
  • 依相關度排序---- 讓『相關文章』更有看頭
  • 補充 ----『隨機文章』

另外寫了一個『不用寫程式, 不用改模版的方法』, 要先掛 jQuery, 再依文章所述安裝。目前的設計, 是要單篇文章才會顯示相關文章。對程式不熟的人, 建議使用 相關文章點播台 -- RPS 1.0 beta

有興趣『寫程式/改模版』的人, 再看下文。

.

  • 遺珠的『相關文章』功能

之所以沒使用下面這些, 來呈現『相關文章』, 有幾個原因 :

  • 無法呈現文章的相關性, 也無法處理重複文章
  • Google Ajax Search API 處理的是『關鍵字』, 而非『標籤』
  • 另外兩個某種程度上比較像『標籤文章選台器』, 而不是『相關文章』

.

不過, 還是列出它們的效果, 說不定你用得上。

Grazr-Related

『Grazr格中格』的『相關文章』功能

2008-07-01_140908
Google Ajax Feed API (Meme -- 教學與反省,
.阿欣部落.)

.

Ajax-Search
Google Ajax Search API

.

建議大家先看一下原始版本的『相關文章』做法 (加入相關文章功能, Abin's Tech Note 2007-03-05), 或者是 替Blogger加入相關文章功能(二)(挖哩勒~胡說八道, 2008-06-30)

裡面, 詳細介紹了『相關文章』的做法, 還有程式碼要安裝在模版的什麼地方。

簡單的說, ABIN 的做法如下 :

  • 集合A = 目前文章的標籤 * (每個標籤取出10 篇最新的文章, 並且不包含目前文章)
  • 集合B = 集合A 的 不重複文章
  • 相關文章 = 從 集合B 隨機取出 5 篇文章

.

  • 依相關度排序 ---- 讓『相關文章』更有看頭

再來看看我的做法, 不同之處以紅色標示 :

  • 集合A = 目前文章的標籤 * (每個標籤取出10 篇最新的文章, 並且不包含目前文章), 並記錄目前的文章有幾個標籤 (labelNum)
  • 集合B = 集合A 的 不重複文章, 並順便統計 每篇文章 在 集合A 出現的次數 (relatedStar),
  • 集合C = 將 集合B 依 文章次數 排序
  • 相關文章 = 集合C 依 文章次數, 由多到少列出, 相關度以 relatedStar / labelNum 表示

.

另外, 我還朝減少記憶體 (陣列) 使用量, 和減少迴圈次數的方向改寫, 所以直接就產生 集合B, 而且 集合C 也只是一個『索引』而已。這樣,『理論上』會跑快一點, 只是不知如何測試。

假設你已經安裝完成原始版本的『相關文章』([1][2]), 只要將 </head> 之前的程式碼整個換成我的版本, 就會有『依相關度排序』的效果。

.

其中的 optionRGB, 請改成適合的顏色設定

var optionRGB = [ {P: 100, R :208, G: 0, B: 0}, {P: 50, R: 255, G: 204, B: 0}, {P: 0, R: 0, G: 64, B: 128} ];

P = 百分比, (R, G, B) = 該百分比的顏色設定。如果介於兩個百分比之間, 則會使用中間色。也可以 增加 或 減少 顏色的組別, 但要維持 P (百分比) 由大到小排列, 還有注意語法即可。

P

R

G

B

100

208

0

0

50

255

204

0

0

0

64

128

.

如果不想使用顏色, 則將以下紅色部分刪去, 並注意 myRBG (內含 <span>) 和 </span> 是成對的。

myRBG = spanRGB(myP, optionRGB);
document.write('<h4>' + myRBG);
document.write('相關度 ' + myStars + ' ' + myP + '% 的文章 :</span></h4> <ul>' );

.

如果想用『分數』(例: 3/5 ) 來表示, 可以將灰色部份與前一行替換,

// document.write('相關度 ' + myStars + ' (' + relatedStar[r] + '/' + labelNum + ') 的文章 :</span> </h4> <ul>' );

.

再來是列出的文章總數, 目前是 20 則, 如藍色部分, 可以自行修改

for (var j=0; j<u_IdxNum && j<20 ; j++)

.

尚待努力之處

  • 看能不能再增進執行效率
  • 將程式主體搬到側邊欄, 縮短文章載入的時間, 之後再插入相關文章的結果

.

</head> 之前的程式碼如下 :

<script type='text/javascript'>
//<![CDATA[
<!-- Script functions for Related Posts: RelatedLabels(), RemoveDuplicatedPosts(), contains(), ShowRelatedPosts()-->
var relatedPostsNum = 0;
var labelNum = 0;
var maxStar = 1;
var relatedStar = new Array();
var relatedTitles = new Array();
var relatedUrls = new Array();
var relatedDates = new Array();
var u_Idx = new Array();
var u_IdxNum = 0;

function RelatedLabels(json) {
var regex1=/</g, regex2=/>/g;
var entryURL = "";
labelNum += 1;
for (var i = 0; i < json.feed.entry.length; i++) {
var entry = json.feed.entry[i];
entryURL = "";
for (var j = 0; j < entry.link.length; j++) {
if (entry.link[j].rel == 'alternate') {
entryURL = entry.link[j].href;
break;
}
}
if (entryURL != "") {
for (var j = 0; j <= relatedPostsNum; j++) {
if (relatedUrls[j] == entryURL) {
relatedStar[j]++;
if (relatedStar[j]>maxStar)
maxStar=relatedStar[j];
entryURL = "";
break;
}
}
}
if (entryURL != "") {
relatedPostsNum++;
relatedTitles[relatedPostsNum] = (entry.title.$t.replace(regex1, '&lt;')).replace(regex2, '&gt;');
relatedDates[relatedPostsNum] = entry.published.$t.substr(0,10);
relatedUrls[relatedPostsNum] = entryURL;
relatedStar[relatedPostsNum] = 1;
}
}
}

function SortRelatedPosts(PostUrl) {
for (var j = maxStar; j > 0 ; j--) {
for(var i = 0; i < relatedUrls.length; i++) {
if (relatedStar[i]==j && PostUrl != relatedUrls[i]) {
u_Idx[u_IdxNum] = i;
u_IdxNum++;
}
}
}
}

function spanRGB(myP, PRGB) {
var myR, myG, myB;
for (var i=0; i< PRGB.length; i++) {
if (myP >= PRGB[i].P) {
if (i==0) {
myR = PRGB[i].R;
myG = PRGB[i].G;
myB = PRGB[i].B;
} else {
var P0 = myP - PRGB[i].P;
var P1 = PRGB[i-1].P - myP;
var deltaP = PRGB[i-1].P - PRGB[i].P;
myR = Math.floor( (PRGB[i-1].R*P0 + PRGB[i].R*P1) / deltaP );
myG = Math.floor( (PRGB[i-1].G*P0 + PRGB[i].G*P1) / deltaP );
myB = Math.floor( (PRGB[i-1].B*P0 + PRGB[i].B*P1) / deltaP );
}
return('<span >');
break;
}
}
return('<span>');
}

function ShowRelatedPosts(PostUrl) {

var r = 0;
var i = 0;
var currStar = 0;
var myStars = "";
var myRBG;
var optionRGB = [ {P: 100, R :208, G: 0, B: 0}, {P: 50, R: 255, G: 204, B: 0}, {P: 0, R: 0, G: 64, B: 128} ];

SortRelatedPosts(PostUrl);
if (relatedTitles.length > 0) {
for (var j=0; j<u_IdxNum && j<20 ; j++) {
r = u_Idx[j];
if (currStar!=relatedStar[r]){
if (currStar != 0)
document.write('</ul>');
currStar = relatedStar[r];
myStars = "";
for (i=0; i<currStar; i++)
myStars = myStars + '★';
var myP = Math.floor(100*relatedStar[r]/labelNum);
myRBG = spanRGB(myP, optionRGB);
document.write('<h4>' + myRBG);
document.write('相關度 ' + myStars + ' ' + myP + '% 的文章 :</span></h4> <ul>' );
// document.write('相關度 ' + myStars + ' (' + relatedStar[r] + '/' + labelNum + ') 的文章 :</span> </h4> <ul>' );
}
document.write('<li><a href="' + relatedUrls[r] + '">' + relatedTitles[r] + '</a> - ' + relatedDates[r] + '</li>');
}
if (currStar != 0)
document.write('</ul>');
document.write('== 以上 ' + j + ' 則 ==, <a href="http://eucaly61.blogspot.com/2008/07/related-posts-with-correlation.html" target="_blank">相關文章及相關度說明</a>');
}
}
//]]>
</script>

.

另外寫了一個『不用寫程式, 不用改模版的方法』, 要先掛 jQuery, 再依文章所述安裝。對程式不熟的人, 建議使用 相關文章點播台 -- RPS 1.0 beta

.

  • 補充 ----『隨機文章』

至於『隨機文章』, 可以參考底下的做法, 將它的精神改寫到 ABIN 的程式裡面。

Blogger Feeling Lucky Widget (Random Post)

  • 按鈕呼叫 feelingLucky()
  • feelingLucky()

/feeds/posts/summary?max-results=0&alt=json-in-script 傳給 readLucky()

  • readLucky()

取得 文章總數, parseInt(feed.openSearch$totalResults.$t,10)
產生 亂數
將 亂數 傳給 fetchLuck()

  • fetchLuck()

/feeds/posts/summary?start-index=+亂數+&max-results=1&alt=json-in-script 傳給 showLucky()

  • showLucky

秀出文章

.


(...繼續閱讀.../...CONTINUE...)