开博第二篇:记一个利用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,大概思路就是这样了,然后接下来就是顺着这个思路啃文档了。。。

========================================拽炸天的分割线========================================

代码如下:

  1 //测试版本:PhotoShop CS5 12.0.3 x32 通过

  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的文档格式是下面这个样子的

<products>

    <product>

        <!--模板文件禁止修改-->

        <产品名称></产品名称> 

        <!--里外编码-->

        <里外编码></里外编码>

        <!--售价-->

        <售价></售价>

        <!--五包费用-->

        <五包费用></五包费用>

        <!--自提费用-->

        <自提费用></自提费用>

        <!--规格大小-->

        <规格大小></规格大小>

        <!--产地-->

        <产地></产地>

        <!--材质-->

        <材质></材质>

        <!--产品图片地址-->

        <产品图片地址></产品图片地址>

        <!--产品二维码地址-->

        <产品二维码地址></产品二维码地址>

    </product>

    <product>

        <!--模板文件禁止修改-->

        <产品名称></产品名称> 

        <!--里外编码-->

        <里外编码></里外编码>

        <!--售价-->

        <售价></售价>

        <!--五包费用-->

        <五包费用></五包费用>

        <!--自提费用-->

        <自提费用></自提费用>

        <!--规格大小-->

        <规格大小></规格大小>

        <!--产地-->

        <产地></产地>

        <!--材质-->

        <材质></材质>

        <!--产品图片地址-->

        <产品图片地址></产品图片地址>

        <!--产品二维码地址-->

        <产品二维码地址></产品二维码地址>

    </product>

</products>

看完了这个文档格式,你应该会有以下的疑问:

1:博主逗比吧,XML标签怎么用中文?!

2:写两遍product节点干什么?手抖么?

哎,我知道自己挺逗的,但是这事要从开发之初说起,我最开始不是用XML来存放数据的,我本来幻想着可以使用CVS文件,或者PRN文件来存放数据源,然而都是以失败告终,因为商品的描述里什么都有可能存,一些卖萌的编辑什么都会写的。。。都怪我太年轻,用什么分割数据搞不清啊。。。

好了,回到问题1,我为什么用中文?因为,是为了避免装13,和让非技术人员看懂。为什么这么说呢,因为用Excel打开这个模板文件,Excel会把子节点当字段名来显示,就比如

<产品二维码地址></产品二维码地址>

这个节点在Excel里的标题就是“产品二维码地址”,这就是用中文的原因,方便理解。不过呢,这里提一个有趣的现象,使用中文去取节点里的内容竟然是可以的,很是让我惊喜哎

代码里可以看到,我是通过

title = products.product[i].elements()[0]

去取商品名称的值的,但是实际上

title = products.product[i].产品名称

也能取得商品名称的值,感觉帅帅哒!
不过呢,我怕出问题,还是没有用中文去取。。。

再看问题2,为什么写两遍,这个就要问Excel了,因为只写一个子节点的话,Excel里是没有表头的, 写两个才有带表头的表格,如下

产品名称 里外编码 售价 五包费用 自提费用 规格大小 产地 材质 产品图片地址 产品二维码地址
                   

 

好了,使用Excel填写产品信息,再保存为XMl数据文件,准备工作就算完成了,接下来就是见证奇迹的时刻了

怎么运行?在页面里运行?看着不像啊。。app是个啥?浏览器认识么。。

其实是在photoShop里运行的,将写好的脚本放置于Adobe Photoshop CS5\Presets\Scripts下,打开PS,已经打开的就重启一下PS,之后你会在PS->文件->脚本下发现放入的脚本文件,默认是支持.jsx结尾的脚本文件,记得文档里说.js结尾的文件也支持来着。点击运行之后,你就会发现,图层啊,文字啊,刷刷的生成,刷刷的关闭,自动化的感觉很好啊,代码中的图片生成速度是10s左右一张,最高画质的,还可以接受。

好了,洋洋洒洒写了这么多,一是为了记录一下自己的心得,二是希望能给那些深陷在重复性设计工作中的人们一些帮助,只要稍微懂得一些脚本知识,能看懂英文文档就可以写啦,很炫酷的。PS脚本对我来说是一个新鲜的东西,或许我写的这些小玩意早就有大神在我之前写过,而且效率更高,或许有现成的软件可以直接生成,或许我做了很多无用功,但是都没关系啦,因为有时候是不是坑,你只有跳进去再爬出来才能知道它是不是,这样以后才好绕着走。博文至此,希望技术大神,和设计大师不用过分重视,毕竟这篇小小的博文只能是一个针对初学者的小例子,就比如说我,我作为一个程序员,两天前都不知道PS可以运行脚本,而对于那些和我一样的小伙伴们,如果你们感兴趣,自己可以先去写个脚本,alert一下自己的helloworld!哈哈~

 



                            

你可能感兴趣的:(JavaScript)