JavaScript_利用JavaScript,編寫PS腳本,開發圖片量產工具
背景:身在一個有實業的電商公司,設計部的妹子們總是會有做不完的商品圖片,當然了,要是做點有技術含量的美化工作也罷,但是最近她們很是無聊,總是要做一些重復性的工作,就比如如題所說的,圖片量產,量產什么呢?價格牌。。。這東西很沒意思哎!就是給你一個模板,然后你自己把模板原來的文字圖片換掉就行了,再排一下版,純體力勞動好么!博主做過一陣子的對日外包工作,深知她們的痛苦,如果說某些對日外包的程序猿是人肉轉碼器的話,那么設計部的妹子們現在就成了。。算了,詞就不說了,太殘酷了
========================================炫炸天的分割線========================================
線索:針對背景交代的情況,BOSS給了我一個提示:PS腳本,順著這個線索,我就進行了一系列調查,我分別做了@#¥%……&*()的努力,簡而言之,photoShop自帶的開發文檔幫了我大忙,文檔位于Adobe Photoshop CS5\Scripting\Documents\,參考了Photoshop CS5 Scripting Guide.pdf和Photoshop CS5 JavaScript Ref.pdf,當然了,自帶的文檔貌似還不能完全滿足我的需求,我還自己下載了一個JavaScriptToolsGuide_CS5.pdf,抱著這三個文檔啃了又啃,總歸算是完成了這樣一個量產工具。
========================================酷炸天的分割線========================================
開發思路:既然是量產工具,那么他的工作流程應該是這樣的,1工具讀了一個文件,文件包含了所有產品的信息,2循環抽取每一個商品的信息,生成圖片并保存,3循環完畢,給出一個提示,OK,大概思路就是這樣了,然后接下來就是順著這個思路啃文檔了。。。
========================================拽炸天的分割線========================================
代碼如下:
2 //作者:Duke
3 //測試完結日期:2014/08/24
4
5 priceCardGenerator()
6
7 function priceCardGenerator(){
8
9 /**
10 * 定義統一的賦值變量
11 */
12 var title //標題
13 var liwaiCode //里外編碼
14 var priceTitle //售價標題,為了方便替換
15 var price //售價
16 var sample //價格符號
17 var fiveAssureFeeTitle //五包費用標題,為方便替換
18 var fiveAssureFee //五包費用
19 var seftFeeTitle //自提費用標題,為方便替換
20 var seftFee //自提費用
21 var size //尺寸
22 var producingArea //產地
23 var material //材質
24
25 /**
26 * 定義統一的字體配置
27 */
28 var tipFont = "MicrosoftYaHei-Bold"
29 var valueFont = "MicrosoftYaHei"
30 var priceFont = "Century Gothic"
31
32 /**
33 * 定義統一的顏色配置
34 */
35 //價格的顏色
36 var priceColor = new SolidColor()
37 priceColor.rgb.red = 208
38 priceColor.rgb.green = 28
39 priceColor.rgb.blue = 119
40 //頂部欄的顏色
41 var topBarColor = new SolidColor()
42 topBarColor.rgb.red = 212
43 topBarColor.rgb.green = 0
44 topBarColor.rgb.blue = 102
45
46 /**
47 * 在此讀取文件
48 */
49 //打開logo圖片
50 var logoImg = app.open(File("D:/priceCard/liwailogo.jpg"))
51
52 //讀取數據文件
53 var dataFile = new File("D:/priceCard/priceCardData.xml")
54 //后續操作設置為“讀”操作
55 dataFile.open("r")
56
57 //緩沖變量
58 var xmlCode = dataFile.read()
59 //alert(xmlCode)
60
61 //空文件直接退出
62 if(xmlCode == ""){
63 alert("文件沒有內容")
64 return
65 }
66
67 //新建XML對象
68 var products = new XML(xmlCode)
69
70 //產品總數
71 var productCount = products.product.length()
72
73 //遍歷
74 for( i = 0;i < productCount;i++){
75
76 //變量賦值
77 title = products.product[i].elements()[0]
78 liwaiCode = "里外編碼:" + products.product[i].elements()[1]
79 priceTitle = "售價"
80 price = products.product[i].elements()[2]
81 sample = "¥"
82 fiveAssureFeeTitle = "五包費用"
83 fiveAssureFee = "¥" + products.product[i].elements()[3]
84 seftFeeTitle = "自提費用"
85 seftFee = "¥" + products.product[i].elements()[4]
86 size = products.product[i].elements()[5]
87 producingArea = products.product[i].elements()[6]
88 material = products.product[i].elements()[7]
89
90 // 存儲當前的單位長度,并設置自定義的單位
91 var originalUnit = preferences.rulerUnits
92 preferences.rulerUnits = Units.PIXELS
93
94 // 聲明一個文檔
95 var docRef = app.documents.add( 886, 561 ,72.0,"tempDoc")
96
97 // 頂部欄,創建選區并上色
98 // “選區”的填充要在定義組之前操作,否則會報出“fill方法在當前版本不可用”
99 docRef.selection.select([[0,0],[0,20],[886,20],[886,0]],SelectionType.EXTEND)
100 var selRef = docRef.selection
101 selRef.fill( topBarColor, ColorBlendMode.NORMAL, 100, false)
102
103 // 定義一個圖片組
104 var layerSetRef =docRef.layerSets.add()
105 layerSetRef.name = "圖片組"
106
107 //設置logo所在的文檔為活動文檔
108 app.activeDocument = logoImg
109 //聲明logo圖層
110 var logoLayer = logoImg.activeLayer
111 //復制商品圖層到背景文檔
112 var logoLayerTemp = logoLayer.duplicate(layerSetRef,
113 ElementPlacement.PLACEATEND)
114 //設置背景文檔為活動文檔
115 app.activeDocument=docRef
116 //logo移動至左下角
117 logoLayerTemp.translate(-265,225)
118
119 //讀取當前商品對應的二維碼圖片
120 var qrCodeImg = app.open(File(products.product[i].elements()[9]))
121 //設置二維碼圖片所在的文檔為活動文檔
122 app.activeDocument = qrCodeImg
123 //聲明二維碼圖片圖層
124 var qrCodeImgLayer = qrCodeImg.activeLayer
125 //復制二維碼圖片到背景文檔
126 var qrCodeImgLayerTemp = qrCodeImgLayer.duplicate(layerSetRef,
127 ElementPlacement.PLACEATEND)
128 //設置背景文檔為活動文檔
129 app.activeDocument=docRef
130 //商品圖片移動至中間偏右
131 qrCodeImgLayerTemp.translate(320,180)
132 //關閉商品圖片文檔
133 qrCodeImg.close(SaveOptions.DONOTSAVECHANGES)
134
135 //讀取當前價格牌的商品圖片
136 var productImg = app.open(File(products.product[i].elements()[8]))
137 //設置商品圖片所在的文檔為活動文檔
138 app.activeDocument = productImg
139 //聲明商品圖片圖層
140 var productImgLayer = productImg.activeLayer
141 //復制商品圖層到背景文檔
142 var productImgLayerTemp = productImgLayer.duplicate(layerSetRef,
143 ElementPlacement.PLACEATEND)
144 //設置背景文檔為活動文檔
145 app.activeDocument=docRef
146 //商品圖片移動至中間偏右
147 productImgLayerTemp.translate(200,-50)
148 //關閉商品圖片文檔
149 productImg.close(SaveOptions.DONOTSAVECHANGES)
150
151 /**
152 *內容開始
153 */
154 // 商品名稱
155 var proNameLayerRef = docRef.artLayers.add()
156 proNameLayerRef.kind = LayerKind.TEXT
157 var proNameTextItemRef = proNameLayerRef.textItem
158 proNameTextItemRef.contents = title
159 proNameTextItemRef.position = Array(55, 70)
160 proNameTextItemRef.font = tipFont
161 proNameTextItemRef.size = 30
162
163 //里外編碼
164 var liwaiCodeLayerRef = docRef.artLayers.add()
165 liwaiCodeLayerRef.kind = LayerKind.TEXT
166 var liwaiCodeTextItemRef = liwaiCodeLayerRef.textItem
167 liwaiCodeTextItemRef.contents = liwaiCode
168 liwaiCodeTextItemRef.position = Array(55, 95)
169 liwaiCodeTextItemRef.font = valueFont
170 liwaiCodeTextItemRef.size = 14
171
172 //售價標題
173 var liwaiCodeLayerRef = docRef.artLayers.add()
174 liwaiCodeLayerRef.kind = LayerKind.TEXT
175 var liwaiCodeTextItemRef = liwaiCodeLayerRef.textItem
176 liwaiCodeTextItemRef.contents = priceTitle
177 liwaiCodeTextItemRef.position = Array(55, 135)
178 liwaiCodeTextItemRef.font = tipFont
179 liwaiCodeTextItemRef.size = 22
180
181 //¥
182 var sampleLayerRef = docRef.artLayers.add()
183 sampleLayerRef.kind = LayerKind.TEXT
184 var sampleTextItemRef = sampleLayerRef.textItem
185 sampleTextItemRef.contents = sample
186 sampleTextItemRef.position = Array(50, 235)
187 sampleTextItemRef.font = tipFont
188 sampleTextItemRef.size = 40
189 sampleTextItemRef.color = priceColor
190
191 //金額
192 var liwaiPriceLayerRef = docRef.artLayers.add()
193 liwaiPriceLayerRef.kind = LayerKind.TEXT
194 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
195 liwaiPriceTextItemRef.contents = price
196 liwaiPriceTextItemRef.position = Array(105, 235)
197 liwaiPriceTextItemRef.font = valueFont
198 liwaiPriceTextItemRef.size = 100
199 liwaiPriceTextItemRef.color = priceColor
200
201 //五包費用
202 var liwaiPriceLayerRef = docRef.artLayers.add()
203 liwaiPriceLayerRef.kind = LayerKind.TEXT
204 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
205 liwaiPriceTextItemRef.contents = fiveAssureFeeTitle
206 liwaiPriceTextItemRef.position = Array(55, 275)
207 liwaiPriceTextItemRef.font = tipFont
208 liwaiPriceTextItemRef.size = 20
209
210 //五包費用金額
211 var liwaiPriceLayerRef = docRef.artLayers.add()
212 liwaiPriceLayerRef.kind = LayerKind.TEXT
213 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
214 liwaiPriceTextItemRef.contents = fiveAssureFee
215 liwaiPriceTextItemRef.position = Array(140, 275)
216 liwaiPriceTextItemRef.font = valueFont
217 liwaiPriceTextItemRef.size = 18
218 liwaiPriceTextItemRef.color = priceColor
219
220 //自提費用
221 var liwaiPriceLayerRef = docRef.artLayers.add()
222 liwaiPriceLayerRef.kind = LayerKind.TEXT
223 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
224 liwaiPriceTextItemRef.contents = seftFeeTitle
225 liwaiPriceTextItemRef.position = Array(250, 275)
226 liwaiPriceTextItemRef.font = tipFont
227 liwaiPriceTextItemRef.size = 20
228
229 //自提費用金額
230 var liwaiPriceLayerRef = docRef.artLayers.add()
231 liwaiPriceLayerRef.kind = LayerKind.TEXT
232 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
233 liwaiPriceTextItemRef.contents = seftFee
234 liwaiPriceTextItemRef.position = Array(335, 275)
235 liwaiPriceTextItemRef.font = valueFont
236 liwaiPriceTextItemRef.size = 18
237 liwaiPriceTextItemRef.color = priceColor
238
239 //規格
240 var liwaiPriceLayerRef = docRef.artLayers.add()
241 liwaiPriceLayerRef.kind = LayerKind.TEXT
242 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
243 liwaiPriceTextItemRef.contents = "規格:"
244 liwaiPriceTextItemRef.position = Array(55, 345)
245 liwaiPriceTextItemRef.font = tipFont
246 liwaiPriceTextItemRef.size = 20
247
248 //規格數值
249 var liwaiPriceLayerRef = docRef.artLayers.add()
250 liwaiPriceLayerRef.kind = LayerKind.TEXT
251 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
252 liwaiPriceTextItemRef.contents = size
253 liwaiPriceTextItemRef.position = Array(125, 345)
254 liwaiPriceTextItemRef.font = valueFont
255 liwaiPriceTextItemRef.size = 20
256
257 //產地
258 var liwaiPriceLayerRef = docRef.artLayers.add()
259 liwaiPriceLayerRef.kind = LayerKind.TEXT
260 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
261 liwaiPriceTextItemRef.contents = "產地:"
262 liwaiPriceTextItemRef.position = Array(55, 375)
263 liwaiPriceTextItemRef.font = tipFont
264 liwaiPriceTextItemRef.size = 20
265
266 //產地值
267 var liwaiPriceLayerRef = docRef.artLayers.add()
268 liwaiPriceLayerRef.kind = LayerKind.TEXT
269 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
270 liwaiPriceTextItemRef.contents = producingArea
271 liwaiPriceTextItemRef.position = Array(125, 375)
272 liwaiPriceTextItemRef.font = valueFont
273 liwaiPriceTextItemRef.size = 20
274
275 //材質
276 var liwaiPriceLayerRef = docRef.artLayers.add()
277 liwaiPriceLayerRef.kind = LayerKind.TEXT
278 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
279 liwaiPriceTextItemRef.contents = "材質:"
280 liwaiPriceTextItemRef.position = Array(55, 405)
281 liwaiPriceTextItemRef.font = tipFont
282 liwaiPriceTextItemRef.size = 20
283
284 //材質值
285 var liwaiPriceLayerRef = docRef.artLayers.add()
286 liwaiPriceLayerRef.kind = LayerKind.TEXT
287 liwaiPriceLayerRef.textItem.kind = TextType.PARAGRAPHTEXT
288 var liwaiPriceTextItemRef = liwaiPriceLayerRef.textItem
289 liwaiPriceTextItemRef.contents = material
290 liwaiPriceTextItemRef.position = Array(125, 391)
291 liwaiPriceTextItemRef.font = valueFont
292 liwaiPriceTextItemRef.width = 550
293 liwaiPriceTextItemRef.height = 200
294 liwaiPriceTextItemRef.size = 20
295
296 //保存文件
297 new Folder("D:/priceCard/result").create ()
298 jpgFile = new File( "D:/priceCard/result/" + products.product[i].elements()[1] + ".jpeg" )
299 jpgSaveOptions = new JPEGSaveOptions()
300 jpgSaveOptions.embedColorProfile = true
301 jpgSaveOptions.formatOptions = FormatOptions.STANDARDBASELINE
302 jpgSaveOptions.matte = MatteType.NONE
303 jpgSaveOptions.quality = 12
304 app.activeDocument.saveAs(jpgFile, jpgSaveOptions, true,
305 Extension.LOWERCASE)
306
307 //強制關閉
308 docRef.close(SaveOptions.DONOTSAVECHANGES)
309
310 //恢復默認長度單位
311 app.preferences.rulerUnits = originalUnit
312 }
313 //關閉logo所在的文檔
314 logoImg.close(SaveOptions.DONOTSAVECHANGES)
315 alert("生成" + productCount + "條產品信息,請在以下位置\"D:/priceCard/result/\"查看")
316 }
代碼里的priceCardData.xml的文檔格式是下面這個樣子的
2 <product>
3 <!--模板文件禁止修改-->
4 <產品名稱></產品名稱>
5 <!--里外編碼-->
6 <里外編碼></里外編碼>
7 <!--售價-->
8 <售價></售價>
9 <!--五包費用-->
10 <五包費用></五包費用>
11 <!--自提費用-->
12 <自提費用></自提費用>
13 <!--規格大小-->
14 <規格大小></規格大小>
15 <!--產地-->
16 <產地></產地>
17 <!--材質-->
18 <材質></材質>
19 <!--產品圖片地址-->
20 <產品圖片地址></產品圖片地址>
21 <!--產品二維碼地址-->
22 <產品二維碼地址></產品二維碼地址>
23 </product>
24 <product>
25 <!--模板文件禁止修改-->
26 <產品名稱></產品名稱>
27 <!--里外編碼-->
28 <里外編碼></里外編碼>
29 <!--售價-->
30 <售價></售價>
31 <!--五包費用-->
32 <五包費用></五包費用>
33 <!--自提費用-->
34 <自提費用></自提費用>
35 <!--規格大小-->
36 <規格大小></規格大小>
37 <!--產地-->
38 <產地></產地>
39 <!--材質-->
40 <材質></材質>
41 <!--產品圖片地址-->
42 <產品圖片地址></產品圖片地址>
43 <!--產品二維碼地址-->
44 <產品二維碼地址></產品二維碼地址>
45 </product>
46 </products>
看完了這個文檔格式,你應該會有以下的疑問:
1:博主逗比吧,XML標簽怎么用中文?!
2:寫兩遍product節點干什么?手抖么?
哎,我知道自己挺逗的,但是這事要從開發之初說起,我最開始不是用XML來存放數據的,我本來幻想著可以使用CVS文件,或者PRN文件來存放數據源,然而都是以失敗告終,因為商品的描述里什么都有可能存,一些賣萌的編輯什么都會寫的。。。都怪我太年輕,用什么分割數據搞不清啊。。。
好了,回到問題1,我為什么用中文?因為,是為了避免裝13,和讓非技術人員看懂。為什么這么說呢,因為用Excel打開這個模板文件,Excel會把子節點當字段名來顯示,比如
這個節點在Excel里的標題就是“產品二維碼地址”,這就是用中文的原因,方便理解。不過呢,這里提一個有趣的現象,使用中文去取節點里的內容竟然是可以的,很是讓我驚喜哎
代碼里可以看到,我是通過
去取商品名稱的值的,但是實際上
也能取得商品名稱的值,感覺帥帥噠!
不過呢,我怕出問題,還是沒有用中文去取。。。
再看問題2,為什么寫兩遍,這個就要問Excel了,因為只寫一個子節點的話,Excel里是沒有表頭的, 寫兩個才有帶表頭的表格,如下
產品名稱 | 里外編碼 | 售價 | 五包費用 | 自提費用 | 規格大小 | 產地 | 材質 | 產品圖片地址 | 產品二維碼地址 |
好了,使用Excel填寫產品信息,再保存為XMl數據文件,準備工作就算完成了,接下來就是見證奇跡的時刻了
怎么運行?在頁面里運行?看著不像啊。。app是個啥?瀏覽器認識么。。
其實是在photoShop里運行的,將寫好的腳本放置于Adobe Photoshop CS5\Presets\Scripts下,打開PS,已經打開的就重啟一下PS,之后你會在PS->文件->腳本下發現放入的腳本文件,默認是支持.jsx結尾的腳本文件,記得文檔里說.js結尾的文件也支持來著。點擊運行之后,你就會發現,圖層啊,文字啊,刷刷的生成,刷刷的關閉,自動化的感覺很好啊,代碼中的圖片生成速度是10s左右一張,最高畫質的,還可以接受。
好了,洋洋灑灑寫了這么多,一是為了記錄一下自己的心得,二是希望能給那些深陷在重復性設計工作中的人們一些幫助,只要稍微懂得一些腳本知識,能看懂英文文檔就可以寫啦,很炫酷的。PS腳本對我來說是一個新鮮的東西,或許我寫的這些小玩意早就有大神在我之前寫過,而且效率更高,或許有現成的軟件可以直接生成,或許我做了很多無用功,但是都沒關系啦,因為有時候是不是坑,你只有跳進去再爬出來才能知道它是不是,這樣以后才好繞著走。博文至此,希望技術大神,和設計大師不用過分重視,畢竟這篇小小的博文只能是一個針對初學者的小例子,就比如說我,我作為一個程序員,兩天前都不知道PS可以運行腳本,而對于那些和我一樣的小伙伴們,如果你們感興趣,自己可以先去寫個腳本,alert一下自己的helloworld!哈哈~
posted on 2014-11-25 21:19 都較瘦 閱讀(3425) 評論(3) 編輯 收藏 所屬分類: JavaScript案例積累