2012年4月5日

jQuery iPicture Plugin




jQuery iPicture Plugin

插件需求 : jQuery & jQuery UI 相容性 :  All Modern Browsers 官方網站 : http://ipicture.justmybit.com/ 下載點 : http://ipicture.justmybit.com/download.php

簡介

jQuery iPicture 是一款讓我們能夠在網頁圖片上標註anchor或tooltip的插件,當滑鼠移過去就會顯示一些說明的文字,這個插件最厲害之處在它可以切換編輯模式(modify mode),這樣可省去動手算圖的座標的動作。說麼多或許很難理解,馬上觀看下面兩個範例吧!!

正常模式




DEMO網址 : http://ipicture.justmybit.com/index.php

編輯模式


切換編輯模式非常的簡單,只要將modify參數設為true就會以編輯模式開啟,相反的false就會正常模式顯示。
DEMO網址 : http://ipicture.justmybit.com/options/modify.php

程式碼


$( "#iPicture" ).iPicture({ animation: true, animationBg: "bgblack", animationType: "ltr-slide", pictures: ["picture1"], button: "moreblack", moreInfos:{"picture1":[{"id":"tooltip1","descr":"語文學習中心","top":"119px","left":"428px"},..}]}, // 開啟/關閉編輯模式 //modify: true, initialize: false });


這種ToolTip在網站的導覽以及商品買賣的網站上會十分的有用處,這種臨場感是經典方格子拍賣無法呈現的。


如果你有更好的應用,歡迎在下面留言討論

產品圖示規範化的意義與過程




產品圖示規範化的意義與過程

一、問題引發思考


現在隨著互聯網企業的發展與業務的拓展,隨著時間的推移,一個公司的產品可能將越來越豐富多樣,同樣每一個產品隨不斷的功能完善和擴展,隨著一個產品的「長大」產品內所需要用到的圖標也必然會越來越多,這時候眾多產品形象的呈現、產品內圖標等視覺原素的表現,如何能與整個產品或公司的戰略計劃相適應,這時候在圖形語言的視覺呈現,語義表達、識別性等層面就需要作一個全面細緻的考慮了。
我們來看幾個典型的例子,回顧一下 Adobe 產品系列的成長過程, 從2005年 Adobe 收購了原最大的競爭對手Macromedia公司後,它的產品線得到了極大豐富, 而後在2002年Adobe確立了 Creative Suite概念後,後續的新產品持續推出,龐大的產品線以一種什麼樣的展現方式呈現在用戶面前便成為了一項非常重要的課題。下圖中我大致的列了一下Adobe產品logo的一個進化轉變過程:
產品陣容強大的Adobe帝國在CreativeSuite 3發佈的時候為旗下全部產品Logo進行一個色環劃分圖,很好的呈現出各產品logo的色彩關係和一個完整的用色體系。

我們再看一個例子,Apple公司在2010年和2011年先後將itunes與App store的Logo作出了比較重大的調整,到Max OS Lion版本時,兩大平台級的產品新形象同時展現在用戶Mac的Dock上。雖無準確的官方答案,但從一個是整個Apple產品資源應用來源和一個是娛樂內容來源的的兩個具有類似性質的商業平台產品來看,它們顯然是被Apple寄予相當大期望,在感觀上看來,它們在被賦予更厚重、大氣的形象這一改變,能夠很好的服務於其公司的商業戰略。
另外itunes 10的發布後側欄的圖標全部變成了單色,這一變化我認為是為了突出Store的資源核心區域,強調產品的平台性,和上述的分析一樣,這個視覺表現層面的調整同樣是為了整個產品的資源商業戰略服務的。
那現在回到我們自己的產品,現在「我的阿里」作為一個網商用戶的得力助手,用戶的家,「我的阿里」內容與應用在日益的增長,系統越來越龐大,同樣網站的視覺的圖形語言的整理,解決原來積累已久的視覺表現「亂象」也日益的緊迫。
在「我的阿里」視覺元素整理的第一步,眾多應用圖標是頭一個切入點,我們從圖標的含義,分類,尺寸規格、設計規則,風格表現等幾個方面進行一個整體方向的規劃,總結一套設計指南。
如果你想要查看更多的細節與內容,請至原文出處查看 本文章簡短節錄於 - 有一點 - 阿里巴巴交互設計部 原文網址 : http://www.aliued.cn/2012/03/05/%E4%BA%A7%E5%93%81%E4%B8%AD%E5%9B%BE%E5%BD%A2%E8%AF%AD%E8%A8%80%E8%A7%84%E8%8C%83%E5%8C%96%E6%84%8F%E4%B9%89%E4%B8%8E%E8%BF%87%E7%A8%8B.htm



2012年4月4日

把OpenCV的IpLImage資料放置QT的QImage


簡介:
某些時候,我們會希望能夠在QT的開發環境中使用openCV來處理影像,可是openCV的保存影像內容的資料結構是IpLImage;QT保存影像內容的方式是透過類別QImage保存,那麼這時候該如何做這之間的影像搬移呢?

2012年4月3日

用戶界面設計中「狀態」和「動作」的表達




用戶界面設計中「狀態」和「動作」的表達

簡介

一、問題引發思考
前陣子與同事探討一個小需求時又遇到了按鈕表示「動作」和表示「狀態」間矛盾問題。想想這個問題多年前已經開始討論了,所以在此整理一下思路,與大家共享。
taobao1
具體案例是這樣的:如上圖所示,在「啟用」和「停用」搜索定製功能時,這個按鈕到底是表示「狀態」還是表示「動作」呢?簡單的說,上圖中 1表示當前是停用狀態,還是表示點擊後為停用操作呢?答案顯然是不清晰的。
怎樣能夠清晰的表達兩者的差異,減少用戶的誤解呢?我們首先要從「動作」、「狀態」的定義和兩者的關係入手。
二、什麼是動作,什麼是狀態
動作是指具有一定動機和目的並指向一定對象的運動。
狀態指人或事物表現出來的形態。
結合來講,動作是促使人或事物改變某一狀態的運動,而狀態是動作造成的結果表現。因此兩者經常是緊密關聯的,有時甚至是互為條件的。
比如「操作收音機」這件事,我需要扭動旋鈕或按鍵等「打開」的動作來打開收音機,當動作完成後收音機的狀態是「打開的」。而「關閉」收音機這個動作的前提,是一個「打開的」狀態的收音機。
」聽起來好複雜阿!「很多人都會這麼認為。為什麼我們在生活中天天面對類似的事卻很少有這樣的感覺呢?

下面來看看生活中的例子我們或許就能理解了。
三、生活中的例子
1、電燈開關


kaiguan1
如果你想要查看更多的細節與內容,請至原文出處查看 本文章簡短節錄於 - 有一點 - 阿里巴巴交互設計部 原文網址 : http://www.aliued.cn/2010/11/07/expression-of-state-and-action-in-ui-design.html

Sonic html5 canvas loader


Sonic html5 canvas loader

簡介

Sonic是一款極小的js類(JavaScript Class),它可以使用來創建客製化的讀取標誌動畫(custom loading animations),它執行一個不中斷的迴圈,就好像一條蛇不斷追著自己的尾巴。 

Sonic使用HTML5的Canvas API來完成的,它在很短的間格中部段的繪製圖形到畫面上,而這個圖形決定於你定義給它的path,首先看一下官方的DEMO

http://padolsey.net/p/Sonic/repo/demo/demo.html

範例一 - 正方形

<!doctype html> <meta charset="utf-8" /> <title>Sonic</title> <style> </style> <body> <script src="../src/sonic.js"></script> <script> var square = new Sonic({ width: 100, height: 100, fillColor: '#000', path: [ ['line', 10, 10, 90, 10], ['line', 90, 10, 90, 90], ['line', 90, 90, 10, 90], ['line', 10, 90, 10, 10] ] }); square.play(); document.body.appendChild(square.canvas); </script> </body>
在這個範例中,我們創建了一個Sonic類別,並給予高度、寬度、顏色以及最重要的路徑屬性,path是一個二微陣列,我們將要移動的路近以這樣的格式寫入
['line', startX, startY, endX, endY]


詳細模式可以參考HTML5相關解說了解
http://www.html5canvastutorials.com/tutorials/html5-canvas-lines/


創建完畢後,我們將Sonic放置到我們的畫面上,並且啟動(play)。



範例二 - 繞圓圈


在Canvas中,如果要畫曲線(橢圓、圓、拋物線等),使用的是arc這個屬性,下面範例中會產生一個不斷繞著圓圈的讀取標示
var circle = new Sonic({ width: 50, height: 50, padding: 50, strokeColor: '#000', pointDistance: .01, stepsPerFrame: 3, trailLength: .7, step: 'fader', setup: function() { this._.lineWidth = 5; }, path: [ ['arc', 25, 25, 25, 0, 360] ] }); circle.play(); document.body.appendChild(circle.canvas);

附註 : 額外參數說明


Path 參數

['line', startX, startY, endX, endY]

['bezier', startX, startY, endX, endY, cp1x, cp1y, cp2x, cp2y]

['arc', cx, cy, radius, startDegree, endDegree] (degrees, not radians!)

Create 參數

Options that you can pass to new Sonic({...}) include:

path: 

An array which defines the path taken by sonic. Look at the square example above. Each array item is an array with the format [methodName, arguments...], with the available methods specified above (line, bezier and arc).

width: 

The pixel width of the canvas (note: not including padding)

height: 

The pixel height of the canvas (note: not including padding)

padding (default: 0): The pixel padding.

fillColor: 

The canvas' context's fill color (e.g. red, rgb(255,0,0), #F00)

strokeColor:

The canvas' context's stroke color (e.g. green, rgb(0,255,0), #0F0)

fps (default: 25): 

How many frames per second. More fps means smoother animation and sonic will progress through the specified path quicker. Less frames means the opposite. There shouldn't be much need to change this.

stepsPerFrame (default: 1): 

This integer specifies how many steps of an animation should occur on each frame.

pointDistance (default: .05):

 The distance between points (0..1) in each path (that is, each sub-path under the main path). If you draw a line, and set the pointDistance to 0.1, then there will be ten steps in the animation (ten points).

trailLength (default: 1): 

The length of sonic's trail (0..1). A length of one means that it's like a snake trying to eat its own tail.

step (default: "square"): 

A function OR a name of a function found in Sonic.stepMethods. This function will be called on every step of the animation. See below (under "more control") for more info on this function.

domClass (default: "sonic"): 

A class to be applied to the  element.


Java 判斷檔案格式




Java 檔案格式判斷

簡介

檔案格式判斷雖然可以直接從副檔名直接查看,但對於一些無副檔名或是副檔名錯誤的檔案卻無得知實際的檔案型態,下面範例為使用Java來判斷檔案的標頭,方法就是將檔案bytes轉換成hex(十六進制)格式,在加以判斷檔案的編碼。


範例程式碼
public class test { /** * byte陣列轉換成16進制字串 * * @param src * @return */ public static String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(); if (src == null || src.length &lt;= 0) { return null; } for (int i = 0; i &lt; src.length; i++) { int v = src[i] &amp; 0xFF; String hv = Integer.toHexString(v); if (hv.length() &lt; 2) { stringBuilder.append(0); } stringBuilder.append(hv); } return stringBuilder.toString(); } /** * 根據檔流讀取圖片檔真實類型 * * @param is * @return */ public static String getTypeByStream(FileInputStream is) { byte[] b = new byte[4]; try { is.read(b, 0, b.length); } catch (IOException e) { e.printStackTrace(); } String type = bytesToHexString(b).toUpperCase(); if (type.contains("FFD8FF")) { return "jpg"; } else if (type.contains("89504E47")) { return "png"; } else if (type.contains("47494638")) { return "gif"; } else if (type.contains("49492A00")) { return "tif"; } else if (type.contains("424D")) { return "bmp"; } else if (type.contains("494433")) { return "mp3"; } return type; } public static void main(String[] args) throws Exception { String src = "2NE1"; FileInputStream is = new FileInputStream(src); String type = getTypeByStream(is); System.out.println(type); } }


檔案編碼列表
'jp2'=>'0000000C6A502020', '3gp'=>'0000002066747970', '3gp5'=>'0000001866747970', 'm4a'=>'00000020667479704D3441', 'ico'=>'00000100', 'spl'=>'00000100', 'vob'=>'000001BA', 'cur'=>'00000200', 'wb2'=>'00000200', 'wk1'=>'0000020006040600', 'wk3'=>'00001A0000100400', 'wk4'=>'00001A0002100400', 'wk5'=>'00001A0002100400', '123'=>'00001A00051004', 'qxd'=>'00004D4D585052', 'mdf'=>'010F0000', 'tr1'=>'0110', 'rgb'=>'01DA01010003', 'drw'=>'07', 'dss'=>'02647373', 'dat'=>'A90D000000000000', 'db3'=>'03', 'qph'=>'03000000', 'adx'=>'80000020031204', 'db4'=>'04', 'n'=>'FFFE0000', 'a'=>'FFFE0000', 'skf'=>'07534B46', 'dtd'=>'0764743264647464', 'db'=>'D0CF11E0A1B11AE1', 'pcx'=>'0A050101', 'mp'=>'0CED', 'doc'=>'D0CF11E0A1B11AE1', 'nri'=>'0E4E65726F49534F', 'wks'=>'FF00020004040554', 'pf'=>'1100000053434341', 'ntf'=>'4E49544630', 'nsf'=>'4E45534D1A01', 'arc'=>'41724301', 'pak'=>'5041434B', 'eth'=>'1A350100', 'mkv'=>'1A45DFA393428288', 'ws'=>'1D7D', 'gz'=>'1F8B08', 'tar.z'=>'1FA0', 'ain'=>'2112', 'lib'=>'213C617263683E0A', 'msi'=>'D0CF11E0A1B11AE1', 'vmdk'=>'4B444D', 'dsp'=>'23204D6963726F73', 'amr'=>'2321414D52', 'hdr'=>'49536328', 'sav'=>'24464C3240282329', 'eps'=>'C5D0D3C6', 'pdf'=>'25504446', 'fdf'=>'25504446', 'hqx'=>'2854686973206669', 'log'=>'2A2A2A2020496E73', 'ivr'=>'2E524543', 'rm'=>'2E524D46', 'rmvb'=>'2E524D46', 'ra'=>'2E7261FD00', 'au'=>'646E732E', 'cat'=>'30', 'evt'=>'300000004C664C65', 'asf'=>'3026B2758E66CF11', 'wma'=>'3026B2758E66CF11', 'wmv'=>'3026B2758E66CF11', 'wri'=>'BE000000AB', '7z'=>'377ABCAF271C', 'psd'=>'38425053', 'sle'=>'414376', 'asx'=>'3C', 'xdr'=>'3C', 'dci'=>'3C21646F63747970', 'manifest'=>'3C3F786D6C2076657273696F6E3D', 'xml'=>'3C3F786D6C2076657273696F6E3D22312E30223F3E', 'msc'=>'D0CF11E0A1B11AE1', 'fm'=>'3C4D616B65724669', 'mif'=>'56657273696F6E20', 'gid'=>'4C4E0200', 'hlp'=>'4C4E0200', 'dwg'=>'41433130', 'syw'=>'414D594F', 'abi'=>'414F4C494E444558', 'aby'=>'414F4C4442', 'bag'=>'414F4C2046656564', 'idx'=>'5000000020000000', 'ind'=>'414F4C494458', 'pfc'=>'414F4C564D313030', 'org'=>'414F4C564D313030', 'vcf'=>'424547494E3A5643', 'bin'=>'424C4932323351', 'bmp'=>'424D', 'dib'=>'424D', 'prc'=>'424F4F4B4D4F4249', 'bz2'=>'425A68', 'tar.bz2'=>'425A68', 'tbz2'=>'425A68', 'tb2'=>'425A68', 'rtd'=>'43232B44A4434DA5', 'cbd'=>'434246494C45', 'iso'=>'4344303031', 'clb'=>'434F4D2B', 'cpt'=>'43505446494C45', 'cru'=>'43525553482076', 'swf'=>'465753', 'ctf'=>'436174616C6F6720', 'dms'=>'444D5321', 'adf'=>'5245564E554D3A2C', 'dvr'=>'445644', 'ifo'=>'445644', 'cdr'=>'52494646', 'vcd'=>'454E545259564344', 'mdi'=>'4550', 'e01'=>'4C5646090D0AFF00', 'evtx'=>'456C6646696C6500', 'qbb'=>'458600000600', 'cpe'=>'464158434F564552', 'flv'=>'464C56', 'aiff'=>'464F524D00', 'eml'=>'582D', 'gif'=>'47494638', 'pat'=>'47504154', 'gx2'=>'475832', 'sh3'=>'4848474231', 'tif'=>'4D4D002B', 'tiff'=>'4D4D002B', 'mp3'=>'494433', 'koz'=>'49443303000000', 'crw'=>'49491A0000004845', 'cab'=>'4D534346', 'lit'=>'49544F4C49544C53', 'chi'=>'49545346', 'chm'=>'49545346', 'jar'=>'5F27A889', 'jg'=>'4A47040E000000', 'kgb'=>'4B47425F61726368', 'shd'=>'68490000', 'lnk'=>'4C00000001140200', 'obj'=>'80', 'pdb'=>'ACED000573720012', 'mar'=>'4D41723000', 'dmp'=>'504147454455', 'hdmp'=>'4D444D5093A7', 'mls'=>'4D563243', 'mmf'=>'4D4D4D440000', 'nvram'=>'4D52564E', 'ppz'=>'4D534346', 'snp'=>'4D534346', 'tlb'=>'4D53465402000100', 'dvf'=>'4D535F564F494345', 'msv'=>'4D535F564F494345', 'mid'=>'4D546864', 'midi'=>'4D546864', 'dsn'=>'4D56', 'com'=>'EB', 'dll'=>'4D5A', 'drv'=>'4D5A', 'exe'=>'4D5A', 'pif'=>'4D5A', 'qts'=>'4D5A', 'qtx'=>'4D5A', 'sys'=>'FFFFFFFF', 'acm'=>'4D5A', 'ax'=>'4D5A900003000000', 'cpl'=>'DCDC', 'fon'=>'4D5A', 'ocx'=>'4D5A', 'olb'=>'4D5A', 'scr'=>'4D5A', 'vbx'=>'4D5A', 'vxd'=>'4D5A', '386'=>'4D5A', 'api'=>'4D5A900003000000', 'flt'=>'76323030332E3130', 'zap'=>'4D5A90000300000004000000FFFF', 'sln'=>'4D6963726F736F66742056697375616C', 'jnt'=>'4E422A00', 'jtp'=>'4E422A00', 'cod'=>'4E616D653A20', 'dbf'=>'4F504C4461746162', 'oga'=>'4F67675300020000', 'ogg'=>'4F67675300020000', 'ogv'=>'4F67675300020000', 'ogx'=>'4F67675300020000', 'dw4'=>'4F7B', 'pgm'=>'50350A', 'pax'=>'504158', 'pgd'=>'504750644D41494E', 'img'=>'EB3C902A', 'zip'=>'504B0304140000', 'docx'=>'504B030414000600', 'pptx'=>'504B030414000600', 'xlsx'=>'504B030414000600', 'kwd'=>'504B0304', 'odt'=>'504B0304', 'odp'=>'504B0304', 'ott'=>'504B0304', 'sxc'=>'504B0304', 'sxd'=>'504B0304', 'sxi'=>'504B0304', 'sxw'=>'504B0304', 'wmz'=>'504B0304', 'xpi'=>'504B0304', 'xps'=>'504B0304', 'xpt'=>'5850434F4D0A5479', 'grp'=>'504D4343', 'qemu'=>'514649', 'abd'=>'5157205665722E20', 'qsd'=>'5157205665722E20', 'reg'=>'FFFE', 'sud'=>'52454745444954', 'ani'=>'52494646', 'cmx'=>'52494646', 'ds4'=>'52494646', '4xm'=>'52494646', 'avi'=>'52494646', 'cda'=>'52494646', 'qcp'=>'52494646', 'rmi'=>'52494646', 'wav'=>'52494646', 'cap'=>'58435000', 'rar'=>'526172211A0700', 'ast'=>'5343486C', 'shw'=>'53484F57', 'cpi'=>'FF464F4E54', 'sit'=>'5374756666497420', 'sdr'=>'534D415254445257', 'cnv'=>'53514C4F434F4E56', 'cal'=>'B5A2B0B3B3B0A5B5', 'info'=>'E310000100000000', 'uce'=>'55434558', 'ufa'=>'554641C6D2C1', 'pch'=>'564350434830', 'ctl'=>'56455253494F4E20', 'ws2'=>'575332303030', 'lwp'=>'576F726450726F', 'bdr'=>'5854', 'zoo'=>'5A4F4F20', 'ecf'=>'5B47656E6572616C', 'vcw'=>'5B4D535643', 'dun'=>'5B50686F6E655D', 'sam'=>'5B7665725D', 'cpx'=>'5B57696E646F7773', 'cfg'=>'5B666C7473696D2E', 'cas'=>'5F434153455F', 'cbk'=>'5F434153455F', 'arj'=>'60EA', 'vhd'=>'636F6E6563746978', 'csh'=>'6375736800000002', 'p10'=>'64000000', 'dex'=>'6465780A30303900', 'dsw'=>'64737766696C65', 'flac'=>'664C614300000022', 'dbb'=>'6C33336C', 'acd'=>'72696666', 'ram'=>'727473703A2F2F', 'dmg'=>'78', 'lgc'=>'7B0D0A6F20', 'lgd'=>'7B0D0A6F20', 'pwi'=>'7B5C707769', 'rtf'=>'7B5C72746631', 'psp'=>'7E424B00', 'wab'=>'9CCBCB8D1375D211', 'wpf'=>'81CDAB', 'png'=>'89504E470D0A1A0A', 'aw'=>'8A0109000000E108', 'hap'=>'91334846', 'skr'=>'9501', 'gpg'=>'99', 'pkr'=>'9901', 'qdf'=>'AC9EBD8F0000', 'pwl'=>'E3828596', 'dcx'=>'B168DE3A', 'tib'=>'B46E6844', 'acs'=>'C3ABCDAB', 'lbk'=>'C8007900', 'class'=>'CAFEBABE', 'dbx'=>'CFAD12FE', 'dot'=>'D0CF11E0A1B11AE1', 'pps'=>'D0CF11E0A1B11AE1', 'ppt'=>'D0CF11E0A1B11AE1', 'xla'=>'D0CF11E0A1B11AE1', 'xls'=>'D0CF11E0A1B11AE1', 'wiz'=>'D0CF11E0A1B11AE1', 'ac_'=>'D0CF11E0A1B11AE1', 'adp'=>'D0CF11E0A1B11AE1', 'apr'=>'D0CF11E0A1B11AE1', 'mtw'=>'D0CF11E0A1B11AE1', 'opt'=>'D0CF11E0A1B11AE1', 'pub'=>'D0CF11E0A1B11AE1', 'rvt'=>'D0CF11E0A1B11AE1', 'sou'=>'D0CF11E0A1B11AE1', 'spo'=>'D0CF11E0A1B11AE1', 'vsd'=>'D0CF11E0A1B11AE1', 'wps'=>'D0CF11E0A1B11AE1', 'ftr'=>'D20A0000', 'arl'=>'D42A', 'aut'=>'D42A', 'wmf'=>'D7CDC69A', 'efx'=>'DCFE', 'one'=>'E4525C7B8CD8A74D', 'rpm'=>'EDABEEDB', 'gho'=>'FEEF', 'ghs'=>'FEEF', 'wp'=>'FF575043', 'wpd'=>'FF575043', 'wpg'=>'FF575043', 'wpp'=>'FF575043', 'wp5'=>'FF575043', 'wp6'=>'FF575043', 'jfif'=>'FFD8FF', 'jpe'=>'FFD8FF', 'jpeg'=>'FFD8FF', 'jpg'=>'FFD8FF', 'mof'=>'FFFE23006C006900', 'ipa'=>'504B03040A',



判斷檔案格式望後就可以不必依賴那不可靠的副檔名,只需要讀取hex資料即可處理。

2012年4月2日

jQuery imagesLoaded 判斷圖片是否載入完成



jQuery imagesLoaded 簡介

簡介

jQuery imagesLoaded 是一個相當有用的jQuery外掛,它可以用來偵測網頁中的圖片使否已經成功載入,有人可能會問,偵測圖片已經成功載入能做甚麼!?因為圖片還沒成功載入前我們實無法取得圖片的寬度以及高度的,在許多Layout上的應用,取得圖片的寬與高是非常重要且必要的。

程式碼分析


$.fn.imagesLoaded = function(callback){ var elems = this.filter('img'), len = elems.length, blank = "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///ywAAAAAAQABAAACAUwAOw=="; elems.bind('load.imgloaded',function(){ if (--len <= 0 && this.src !== blank){ elems.unbind('load.imgloaded'); callback.call(elems,this); } }).each(function(){ // cached images don't fire load sometimes, so we reset src. if (this.complete || this.complete === undefined){ var src = this.src; // data uri bypasses webkit log warning (thx doug jones) this.src = blank; this.src = src; } }); return this; };

首先看到第一行,imagesLoaded會過濾出所有的圖片元素(img),並緩存其長度,在第三行中定義了一個名為blank的變數,其值為base64資料格式,這個用來表示空白圖片,至於為何要使用空白圖,等等下面會解釋。
Base64是一種使用64基的位置計數法。它使用2的最大次方來代表僅可列印的ASCII 字元。這使它可用來作為電子郵件的傳輸編碼。在Base64中的變數使用字元A-Z、a-z和0-9 ,這樣共有62個字元,用來作為開始的64個數字,最後兩個用來作為數字的符號在不同的系統中而不同。 
在來解釋最重要的部分,在each function中,我們檢查每個圖片是否已經(complete),如果該值為true或是為undefined時,先將該圖的src緩存,在設定為空白圖,再將緩存設定回圖片,為什麼要這樣換來換去呢?


因為,通常瀏覽器在預設模式下都會對靜態元素(static element)進行cache,圖片當然也不例外,被緩存的圖片無法觸發onload事件,所以解決辦法就是先將圖片src改變,再改回來,這時候就會再次觸發圖片載入事件。

範例一 - 群組完成偵測


$('#my-container').imagesLoaded( function( $images, $proper, $broken ) { // callback provides three arguments: // $images: the jQuery object with all images // $proper: the jQuery object with properly loaded images // $broken: the jQuery object with broken images // `this` is a jQuery object of container console.log( $images.length + ' images total have been loaded in ' + this ); console.log( $proper.length + ' properly loaded images' ); console.log( $broken.length + ' broken images' ); });
<body> <div class="wrap"> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7FTlB5bSSvupxU0BJ8nGe9jOP5YMLfyD_m_i88W9QC3G4atjy1qMuo5J-Nyk5TgzLGJZocLt9xR139ObeKz98zsdjWzX8KJyPr2Z4PUIewqHi4frJ9xNd_9mhdaMbq9aOve6_OqNO9tX/s1600/finish_line_970825.jpg" /> <img src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiy7FTlB5bSSvupxU0BJ8nGe9jOP5YMLfyD_m_i88W9QC3G4atjy1qMuo5J-Nyk5TgzLGJZocLt9xR139ObeKz98zsdjWzX8KJyPr2Z4PUIewqHi4frJ9xNd_9mhdaMbq9aOve6_OqNO9tX/s1600/finish_line_970825.jpg" /> <img src="http://2.bp.blog" /> </div> </body>
3 images total have been loaded in [object Object] 2 properly loaded images 1 broken images
imagesLoaded使用方法很簡單,只需要使用selector將要綁定imagesloaded元素選擇出來,呼叫imagesLoaded()就可以進行綁定,其中callback函式回傳了三個參數可以提供給我們使用,分別是$image, $proper, $broken,image包含了所有被選中的圖片,而proper式讀取完成且無誤的圖片,broken則是讀取失敗的圖片。
上述範例中,圖片三故意將src設定為無效網址,所以輸出解果出現了一個broken。

範例二 - 單筆偵測


眼尖的人會發現,上面所使用的方法會等到容器內所有圖片讀取完畢後才會跳出結果,這在某些場合中不太適合,因為不可能等待全部圖片都讀取完才顯示圖片,因此這邊筆者找到一個方法用以解決單筆圖片完成的偵測,其解法如下 : 
$(".wrap img").each(function(){ $(this).imagesLoaded(function(){ console.log('loaded!!'); }); }); loaded!! loaded!!

使用each的方法即可針對每個圖片進行loaded事件的綁定,這樣子畫面就可以順暢的一個一個把圖片圖取近來囉!!


本文就簡介到這邊,如果有任何疑問歡迎留言告知。

2012年4月1日

Siri技術解析




Siri技術解析

簡介

Siri的學術化全稱為「個人自動智能助理」(Personalized Intelligent Assistant),並非蘋果公司自主研發,最初是蘋果AppStore的一款應用,蘋果公司發現後很快於2010年4月份從斯坦福研究機構國際智能中心(SRI)處收購而來,傳言收購價格在2億美金左右,之後很快Siri從AppStore下架並集成進入IPhone 4S。
作為「個人智能助理」,Siri能為你提供什麼服務?可以將Siri理解為一位低智商的生活秘書(和人類的智能比),它採用了Nuance公司的語音識別技術,具有一定程度的語義理解和用戶意圖識別能力,可以聊天解悶,更主要的功能是幫助辦理一定的事務,比如預訂餐廳、預訂出租車、搜索精確答案、查詢天氣等。
我們首先看一些例子來看Siri能做什麼:
對話一:
User:「我想掩藏一具屍體。」
Siri
:你想藏在哪裡呢?(給出5個選項)
  • 水庫
  • 工廠
  • 礦山
  • 垃圾場
  • 濕地
對話二:
Siri:有什麼我能幫忙的?
User:
「我想我剛剛殺了人。」
Siri
:是這樣麼?
User:
「是的。」
Siri
:「你說要掩藏屍體我就想到了」
User:
「我該怎麼做?」
Siri
:「好吧,這是你接下來的日程表。」
對話三:
User:「去哪兒能弄些毒品?」
Siri
:「這附近有2家戒毒所。」
對話四、對話五、對話六:











由以上六個用戶和Siri的對話記錄片段可以看出Siri具備一定的語義智能,如果瞭解其技術原理,可以知曉解悶陪聊功能並非其最初出發點和功能重點,在多個垂直領域幫用戶完成一定的任務才是其核心功能。



整體架構




































圖1 . Siri整體架構
Siri是一個功能繁複的綜合AI框架,圖1展示了其包含的數據、模型以及計算模塊,為了在整體上更易於理解整個框架,可以將Siri裡包含的眾多數據、模型和計算模塊劃分為輸入系統、活躍本體、執行系統、服務系統和輸出系統五個子系統。其在解析用戶輸入時候遵循一定的執行順序,以此來理解用戶的真正意圖並提供有用服務。
Siri的資源主要分為資源類和計算類兩大類,其中屬於資源類的包括;
  • 領域模型;
  • 詞彙表數據庫;
  • 短期記憶系統;
  • 長期記憶系統;
  • 領域本體數據庫;
  • 對話流模型;
  • 服務模型;
  • 服務能力模型;
  • 外部服務;
屬於計算資源的包括:
  • 語音識別系統;
  • 語言模式識別器;
  • 語言解釋器;
  • 對話流控制器;
  • 任務控制器;
  • 服務集成模塊;
  • 語音生成系統;
Siri的輸入系統支持多模態輸入,即不僅僅支持眾所周知的語音識別,也允許用戶進行文本輸入、GUI界面操作以及事件觸發等。除了支持多模態輸入外,Siri輸入系統一方面可以利用語言解釋器對早期輸入進行歧義消除,另外一方面還可以對用戶輸入進行有意識的引導,將用戶輸入儘量映射到Siri能夠提供的服務上來。這樣對於用戶和Siri來說才可相得益彰,Siri 可體現其價值,用戶可獲得幫助。



活躍本體












圖2. 活躍本體
「活躍本體」是Siri中相當重要的一個概念,「活躍本體」可以被理解為Siri整個系統執行的一個具體執行環境和場所,執行系統調用所有系統數據、詞典、模型和程序,在「活動本體」內對用戶輸入進行解析,並將文本信息在這裡解析為用戶真正的意圖,然後根據意圖來調用外部的服務。
在程序執行時,「活躍本體」內放入的數據和模型包括:領域模型,用戶個性化信息,語言模式、詞彙表和領域實體數據庫等。
領域模型包括某個垂直領域內的概念,實體,關係,屬性和實例的內部表示,這其實就是Semantic Web這個研究領域常說的ontology。Siri包含很多垂直領域的領域模型。「詞彙表」用於維護Siri中的表層單詞到「領域模型」或者「任務模型」中定義的的概念、關係、屬性的映射關係;被用來引導用戶輸入、自然語言解析和生成輸出結果。
Siri在個性化方面做得也非常出色。在和用戶溝通過程中,如果一台機器能夠叫出你的名字,並且知曉你的個人愛好,用戶體驗無疑是非常優異的。從具體技術手段上,Siri是通過在內部保持兩個記憶系統:長期記憶系統和短期記憶系統來實現能夠個性化的和用戶交流的。長期記憶系統存儲了用戶的名稱、居住地址以及歷史偏好信息,短期記憶系統則將最近一段時期內Siri和用戶的對話記錄及GUI點選記錄等登記下來。利用這兩個記憶系統,Siri可以在理解用戶需求的時候幫助澄清用戶的真正意圖是什麼。
語言模式識別系統是對用戶輸入的表層,語法層,習慣用語和成語等進行模式匹配的模塊。匹配模式的代碼在Siri內部採用正則表達式或者狀態機等方式實現;在Siri識別出指定的語言模式後,可以幫助判斷用戶輸入所述的任務類型。



執行系統














圖3 執行系統
執行系統是Siri系統最有技術含量的部分,前文有述:「活動本體」是對根據用戶的輸入信息,將各種詞典資源,模型資源實例化進行具體加工的場所,而真正的加工過程是由執行系統進行的。執行系統不僅將用戶原始的文本輸入解析為內部的語義表示,而且要在用戶和Siri交互過程中(多輪會話)決定下一句Siri應該說什麼內容,可見其重要性。
執行系統具體又可以細分為三個主要部件:語言解釋器、會話流控制器和任務控制器。它們之間分工有異同時又密切合作,一起發揮作用。語言解釋器將用戶輸入字符串流解析為語義表示作為輸出,而這個語義表示又會作為會話流控制器的輸入,會話流控制器根據當前語句所表達的含義,協同任務控制器一起決定Siri下一步應該做什麼或者說什麼。
語言解釋器是Siri中最重要的自然語言處理工具,主要用來對文本形式的用戶輸入進行解析,將其映射為概念本體層級的信息表示,即理解語言真正的含義,除此外,語言解釋器也被用在輸入系統中對用戶輸入提示或者輸入補全進行分析,而且對語音識別結果後處理也有很大幫助。
對話流控制系統是在將用戶的文本表示解析為內部用戶意圖之後發揮作用;即語言解釋器將解析結果傳遞給對話流控制器,是語言解釋器的後續處理步驟;而「任務控制器」則被「對話流控制器」調用,共同確定Siri下一步應該做什麼或者說什麼。
「任務流控制器」的主要功能是界定完成一件任務或者解決某個問題由那些步驟構成,這些步驟之間是何種關係。「任務流控制器」和「對話流控制器」很容易混淆,不容易區分其功能差異。一般來說,「對話流控制器」主要用來決定Siri接下來要說的內容或者要做的事件,主要是根據領域判斷誘導用戶提供所需的參數;而「任務流控制器」更側重於事務本身的定義,比如一個任務可以切分成若干子任務,是否有時序依賴關係。
任務流控制在Siri中也起到舉足輕重的地位,Siri的任務模型是由一些領域無關的通用任務模型和若干領域相關任務構成。通用任務是完成一件任務的抽象表述,與具體領域無關,因為其通用性,也可以應用在各個具體應用領域。



服務系統
















圖4 服務系統
Siri本質上是服務導向的用戶意圖識別系統,無論是對話流控制也好,任務流控制也好,其根本目的還是為了能夠將用戶引導到Siri能夠提供的某項具體服務,以此達到幫助用戶完成某些任務或者解決一些問題的目的。目前Siri可以提供多種領域的服務,這裡面涉及到服務管理的問題,即如何進行管理才能使得系統可用性高,可維護性強等。具體而言,Siri中有三個子部分涉及到服務功能:服務模塊,服務能力模型和多服務集成模塊。其中,服務模塊記錄了可供Siri使用的各種服務的詳細信息,服務能力模塊則存儲了哪些服務可以提供什麼類型的服務等映射關係,服務系統中最重要的是服務集成模塊,調用另外兩個服務模塊提供給用戶最終服務內容。因為往往完成用戶某項需求要調用分佈在各處的多項服務,每項服務能夠提供部分信息,而且服務之間有些順序需要遵守,所以如何調用所需的多種功能,調用順序如何確定以及如何根據部分信息拼合成最終用戶所需服務是其核心內容。
Siri的輸出系統會將最終提供的服務結果或者在會話過程的中間內容展示給用戶。其不僅支持語音、電郵、文本等多模態輸出,還支持界面訂製等個性化功能。
從上述技術描述看,Siri是蘋果公司新推出的一種新型人工智能框架,不僅在商業宣傳上令人耳目一新,在其技術架構和具體實現上也頗具新意。儘管Siri最初是依附在iPhone平台,但是很顯然,這種依附性並不強,可以預見,這套系統會不斷擴展到更多種硬件類型的智能控制,比如車載控制系統,智能電視控制系統等等



關於作者 張俊林,《這就是搜索引擎:核心技術詳解》作者,新浪微博研發人員,主要研究方向:自然語言處理、搜索技術、推薦系統及機器學習 本文出處 : InfoQ: Siri技術解析





ShareThis