映射用于表示鍵和值的關(guān)聯(lián)關(guān)系。這種關(guān)聯(lián)方式是由 “#{” 與 “}” 括起來。創(chuàng)建一個字符串 "key" 到值 42 的映射的方法如下:
1>#{ "key"=>42}.
#{"key" => 42}
讓我們直接通過示例來看一些有意思的特性。
下面的例子展示了使用映射來關(guān)聯(lián)顏色與 alpha 通道,從而計算 alpha 混合(譯注:一種讓 3D 物件產(chǎn)生透明感的技術(shù))的方法。將下面的代碼輸入到 color.erl 文件中:
-module(color).
-export([new/4, blend/2]).
-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).
new(R,G,B,A) when ?is_channel(R), ?is_channel(G),
?is_channel(B), ?is_channel(A) ->
#{red => R, green => G, blue => B, alpha => A}.
blend(Src,Dst) ->
blend(Src,Dst,alpha(Src,Dst)).
blend(Src,Dst,Alpha) when Alpha > 0.0 ->
Dst#{
red := red(Src,Dst) / Alpha,
green := green(Src,Dst) / Alpha,
blue := blue(Src,Dst) / Alpha,
alpha := Alpha
};
blend(_,Dst,_) ->
Dst#{
red := 0.0,
green := 0.0,
blue := 0.0,
alpha := 0.0
}.
alpha(#{alpha := SA}, #{alpha := DA}) ->
SA + DA*(1.0 - SA).
red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).
green(#{green := SV, alpha := SA}, #{green := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).
blue(#{blue := SV, alpha := SA}, #{blue := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).
編譯并測試:
1> c(color).
{ok,color}
2> C1 = color:new(0.3,0.4,0.5,1.0).
#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3}
3> C2 = color:new(1.0,0.8,0.1,0.3).
#{alpha => 0.3,blue => 0.1,green => 0.8,red => 1.0}
4> color:blend(C1,C2).
#{alpha => 1.0,blue => 0.5,green => 0.4,red => 0.3}
5> color:blend(C2,C1).
#{alpha => 1.0,blue => 0.38,green => 0.52,red => 0.51}
關(guān)于上面的例子的解釋如下:
-define(is_channel(V), (is_float(V) andalso V >= 0.0 andalso V =< 1.0)).
首先,上面的例子中定義了一個宏 is_channel,這個宏用的作用主要是方便檢查。大多數(shù)情況下,使用宏目的都是為了方便使用或者簡化語法。更多關(guān)于宏的內(nèi)容可以參考預(yù)處理。
new(R,G,B,A) when ?is_channel(R), ?is_channel(G),
?is_channel(B), ?is_channel(A) ->
#{red => R, green => G, blue => B, alpha => A}.
函數(shù) new/4 創(chuàng)建了一個新的映射,此映射將 red,green,blue 以及 alpha 這些健與初始值關(guān)聯(lián)起來。其中,is_channel 保證了只有 0.0 與 1.0 之間的浮點(diǎn)數(shù)是合法數(shù)值 (其中包括 0.0 與 1.0 兩個端點(diǎn)值)。注意,在創(chuàng)建新映射的時候只能使用 => 運(yùn)算符。
使用由 new/4 函數(shù)生成的任何顏色作為參數(shù)調(diào)用函數(shù) blend/2,就可以得到該顏色的 alpha 混合結(jié)果。顯然,這個結(jié)果是由兩個映射來決定的。
blend/2 函數(shù)所做的第一件事就是計算 alpha 通道:
alpha(#{alpha := SA}, #{alpha := DA}) ->
SA + DA*(1.0 - SA).
使用 := 操作符取得鍵 alpha 相關(guān)聯(lián)的值作為參數(shù)的值。映射中的其它鍵被直接忽略。因?yàn)橹恍枰I alpha 與其值,所以也只會檢查映射中的該鍵值對。
對于函數(shù) red/2,blue/2 和 green/2 也是一樣的:
red(#{red := SV, alpha := SA}, #{red := DV, alpha := DA}) ->
SV*SA + DV*DA*(1.0 - SA).
唯一不同的是,每個映射參數(shù)中都有兩個鍵會被檢查,而其它鍵會被忽略。
最后,讓我們回到 blend/3 返回的顏色:
blend(Src,Dst,Alpha) when Alpha > 0.0 ->
Dst#{
red := red(Src,Dst) / Alpha,
green := green(Src,Dst) / Alpha,
blue := blue(Src,Dst) / Alpha,
alpha := Alpha
};
Dst 映射會被更新為一個新的通道值。更新已存在的映射鍵值對可以用 := 操作符。
更多建議: