<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用JavaScript開發(fā)一個(gè)Photoshop插件

          共 9536字,需瀏覽 20分鐘

           ·

          2021-04-14 09:14

          作為前端開發(fā)者,我們可以利用Web技術(shù)在非常多的環(huán)境下開發(fā)應(yīng)用,為相關(guān)的用戶提供服務(wù)。其中,以Photoshop為首的Adobe系列工具是我們時(shí)長要去面對的一個(gè)平臺級應(yīng)用。Photoshop在圖像處理上有著很強(qiáng)大的功能,用戶量也非??捎^,而且其功能在前端開發(fā)的一些情況下也用得到,因此筆者認(rèn)為Photoshop相關(guān)的Web技術(shù)具有很不錯(cuò)的價(jià)值。

          本文將引導(dǎo)大家使用JavaScript開發(fā)一個(gè)Photoshop插件。

          CEP:通用擴(kuò)展平臺

          Adobe作為一家歷史悠久的軟件公司,已經(jīng)給開發(fā)者提供了相對成熟的擴(kuò)展開發(fā)技術(shù)棧,被稱作CEP——Common Extensibility Platform(通用擴(kuò)展平臺)。

          CEP擴(kuò)展基于Web技術(shù),可以在Adobe Photoshop、Adobe Illustrator、Adobe InDesign等全系列應(yīng)用中運(yùn)行,并且可以訪問這些應(yīng)用和外部操作系統(tǒng)環(huán)境的API。

          CEP應(yīng)用的結(jié)構(gòu)可以被分為五個(gè)抽象層級:

          1. 用戶層,用戶所得到的、構(gòu)建出來的應(yīng)用外部;

          2. 宿主應(yīng)用層,我們的CEP擴(kuò)展在宿主應(yīng)用中被配置好后,會在嵌入的CEF(一個(gè)開源的、嵌入基于Chromium內(nèi)核瀏覽器的簡單框架)中成功渲染;

          3. UI層,就是基于HTML文件構(gòu)建的WEB頁面;

          4. Javascript層,運(yùn)行在UI層頁面上的JavaScript腳本,比起一般Web應(yīng)用的環(huán)境里內(nèi)置了更多的功能——可以訪問Extendscript層與一些宿主應(yīng)用原生功能的API以及本機(jī)中Nodejs的API;

          5. Extendscript層,運(yùn)行在宿主應(yīng)用內(nèi)部的腳本,具有訪問宿主應(yīng)用的內(nèi)部API的能力,可以和JavaScript層之間通信;

          所謂宿主應(yīng)用,就是我們CEP擴(kuò)展運(yùn)行在的Adobe程序,例如Adobe Photoshop等,同時(shí)后文我們也默認(rèn)CEP的宿主程序是Adobe Photoshop

          ExtendScript

          作為一個(gè)類Web應(yīng)用,上面四層相對前端開發(fā)者來說都比較好理解,這一節(jié)我們來看下ExtendScript層:

          ExtendScript腳本可以用三套不同語言去編寫,分別為JavaScript、VBScript和AppleScript。三種語言功能上沒有任何區(qū)別。鑒于本文面向的是各位前端工程師,我們果斷選擇前者,同時(shí)文章的后文我們也是默認(rèn)選擇JavaScript版本的ExtendScript。

          ExtendScript有以下特點(diǎn):

          • 區(qū)別于 CEP 擴(kuò)展中后綴為.js的 JavaScript 文件,操作ExtendScript 的JavaScript文件后綴名為.jsx

          這里的.jsx文件和react用到的.jsx文件完全不同,如果你在自己的CEP應(yīng)用中引入了react,記得把它們分開以避免混淆

          • ExtendScript在全局下內(nèi)置了用來獲取和操作Adobe應(yīng)用和文件內(nèi)容的各種API

          • Adobe應(yīng)用中,ExtendScript腳本和CEP中的JavaScript腳本運(yùn)行于兩個(gè)不同的引擎,如果我們選擇JavaScript語言接口的ExtendScript腳本,對應(yīng)的引擎僅僅兼容至 ECMAScript3的標(biāo)準(zhǔn)

          了解了Extendscript之后,我們再來看一下CEP擴(kuò)展各層級之間的橫向關(guān)系:

          • CEP擴(kuò)展中的JavaScript代碼會在CEP JavaScript VM 中運(yùn)行,比起一般的Web應(yīng)用,增加了調(diào)用Node.js的API與操作系統(tǒng)交互,以及通過引入 CSInterface.js[3] 調(diào)用ExtendScript的功能

          • 宿主程序中,作為ExtendScript的JavaScript代碼會在另一個(gè)環(huán)境下——Host JavaScript VM中被解析

          • 在這一個(gè)類Web應(yīng)用中包含兩個(gè)腳本環(huán)境,兩個(gè)環(huán)境雖然都是JavaScript,而且可以通過傳遞字符串相互通信,但是是其上下文是相互隔離的,一定要區(qū)分開來


          關(guān)于Photoshop中,ExtendScript具體可以調(diào)用的API,我們可以直接看Adobe的官方手冊:ADOBE PHOTOSHOP SCRIPTING[1]

          項(xiàng)目構(gòu)建

          在動手開發(fā)前,我們先把運(yùn)行CEP擴(kuò)展的各種要素準(zhǔn)備齊全。

          首先我們來看下CEP擴(kuò)展需要的目錄結(jié)構(gòu):

          • CSXS/manifest.xml必需,項(xiàng)目的配置文件,配置CEP擴(kuò)展應(yīng)用的窗體大小、入口的html文件地址、入口jsx(ExtendScript)文件地址、版本兼容、啟動選項(xiàng)等信息,由于篇幅所限我們不在本文里具體展開,官方提供了配置文件的指南:Configure-your-extension-in-manifestxml[2]

          • client/index.htmlclient/index.js、client/style.cssCEP應(yīng)用相關(guān)頁面、腳本、樣式,就是我們CEP擴(kuò)展和Web相關(guān)的全部文件

          • client/CSInterface.jsAdobe官方提供的工具庫,需要在JavaScript層引入,封裝并提供了訪問ExtendScript層和一些原生功能的API,官方也在github上提供了文件CSInterface.js。



          這個(gè)工具庫大概一千多行,其中很大一部分是描述各個(gè)函數(shù)功能的注釋,所以可以直接通過閱讀注釋來學(xué)習(xí)這個(gè)工具庫的用法。

          CEP擴(kuò)展中的JavaScript環(huán)境下本身就內(nèi)置了調(diào)用ExtendScript環(huán)境的類,引入的CSInterface.js是對環(huán)境里調(diào)用ExtendScript環(huán)境的類進(jìn)行封裝使得開發(fā)者更便于調(diào)用而已,所以引入CSInterface.js并不是必要的。

          • host/index.jsxExtendScript的腳本,訪問宿主應(yīng)用的內(nèi)部API的能力,在CEP擴(kuò)展中,ExtendScript文件有兩種加載方式:

          • 在CEP擴(kuò)展內(nèi)用JavaScript通過CSInterface.js封裝好的方法主動進(jìn)行加載

          • manifest.xml中通過配置入口的jsx(ExtendScript)文件的腳本,在CEP擴(kuò)展應(yīng)用運(yùn)行的第一時(shí)間進(jìn)行加載

          最后,我們要把建立好的CEP擴(kuò)展的目錄放到Photoshop指定的位置:

          mac:~/Library/Application Support/Adobe/CEP/extensions

          win:{Photoshop安裝路徑}\Required\CEP\extensions

          這樣Photoshop就可以加載我們開發(fā)的擴(kuò)展,出現(xiàn)在其菜單欄中的「窗口」-「擴(kuò)展」中。

          debug模式與調(diào)試

          看了這么多概念,我們動手試試吧!

          新建CEP擴(kuò)展的目錄之后,我們嘗試在Photoshop菜單欄的「窗口」-「擴(kuò)展」中運(yùn)行擴(kuò)展,就發(fā)現(xiàn)了一個(gè)問題:

          這是因?yàn)槲覀冃陆ǖ腃EP擴(kuò)展沒有經(jīng)過簽名認(rèn)證。

          為了繞過這個(gè)認(rèn)證,我們需要打開Photoshop的debug模式:

          • 首先,我們要獲取自己當(dāng)前機(jī)器上Adobe CEP的版是CEP幾,關(guān)于Adobe不同應(yīng)用的種類和版本的簡稱,我們可以看官方提供的對應(yīng):Applications Integrated with CEP[4]

          • 得到當(dāng)前CEP的版本后,我們可以通過下面的方法進(jìn)入debug模式(記得將下列CSXS.[n]中的[n]用你目前的CEP版本替換)

          • 如果你是Windows用戶,你需要:

          • 打開 regedit

          • 找到HKEY_CURRENT_USER/Software/Adobe/CSXS.[n]

          • 然后添加一個(gè)叫PlayerDebugMode的字段

          • 設(shè)置值為string類型的"1"

          • 果你是macOS用戶,你需要:

          • 打開終端輸入:defaults write com.adobe.CSXS.[n] PlayerDebugMode 1

          • 你需要在終端輸入ps -axu $USER|grep cfprefsd,找到cfprefsd這個(gè)進(jìn)程的pid,然后用kill命令刪掉它(或者你也可以直接重新啟動你的機(jī)器)。

          執(zhí)行完上面的操作后,你就可以在自己的Photoshop里運(yùn)行自己新建的擴(kuò)展了。

          同時(shí),如果你想調(diào)試自己的擴(kuò)展,可以在目錄指定位置中添加.debug文件:

          .debug文件中,我們指定開發(fā)的應(yīng)用可以在哪個(gè)宿主應(yīng)用和哪個(gè)端口進(jìn)行調(diào)試:

          <ExtensionList>    <!-- 1 -->    <Extension Id="com.example.helloworld">       <HostList>
          <!-- 2 --> <Host Name="PHXS" Port="8088"/> <Host Name="PHSP" Port="8088"/>
          </HostList> </Extension></ExtensionList>

          然后,我們訪問在chrome瀏覽器中訪問chrome://inspect/#devices,點(diǎn)擊「Port forwarding...」監(jiān)聽我們在.debug中設(shè)置的端口,我們可以看到的自己的應(yīng)用:

          熟悉移動端調(diào)試的讀者一定對這個(gè)界面不陌生,我們找到自己的應(yīng)用并點(diǎn)開「inspect」,就可以在指定端口通過chrome的開發(fā)者工具來同步調(diào)試運(yùn)行的CEP擴(kuò)展了。

          開發(fā)「獲取/刪除所有文字圖層」的Ps插件

          我們從前文提到的「CEP應(yīng)用結(jié)構(gòu)的五個(gè)層級」自下向上來構(gòu)建:

          1. 首先,在Extendscript層,我們先在全局定義好「獲取所有文字圖層」和「刪除所有文字圖層」的功能函數(shù):

          function getAllLayers() {  var out = [];  var doc = app.activeDocument;  getLayers(doc.layers);  function getLayers(layers) {    for (var i = 0; i < layers.length; i++) {      if (layers[i].typename == "LayerSet") {        //判斷是否是圖層組        out.push(layers[i].name);        getLayers(layers[i].layers);      } else {        out.push(layers[i].name);      }    }  }  return JSON.stringify(out);}
          function hideAllTextLayers() { var doc = app.activeDocument; var out = []; function getLayers(layers) { for (var i = 0; i < layers.length; i++) { if (layers[i] && layers[i].kind === LayerKind.TEXT) { out.push(layers[i]); } if (layers[i].typename == "LayerSet") { getLayers(layers[i].layers); } } } getLayers(doc.layers); for (var j = 0; j < out.length; j++) { out[j].remove(); } return "{}";}


          • app作為Extendscript中的全局對象,有著獲取原生宿主程序各種功能的api,我們可以通過app.activeDocument.layers來獲取或者操作圖層

          • 同時(shí),我們通過返回字符串類型的結(jié)果,讓CEP的JavaScript端得以獲取

          由于在Extendscript環(huán)境下,JavaScript僅兼容ES3,而且ExtendScript和CEP JavaScript之間只能通過字符串進(jìn)行通信,所以我們要在ExtendScript的環(huán)境下引入JSON3[5]作為JSON功能的polyfill(注意這和CEP的JavaScript無關(guān))

          2. 在CEP的JavaScript層,我們在utils/cs.js中使用Promise封裝好界面上用得到的的hideLayersgetLayers函數(shù)——調(diào)用Extendscript中已經(jīng)定義好在全局的方法,并處理返回的字符串:

          const cs = new CSInterface();
          var c = cs.getSystemPath(SystemPath.EXTENSION) + "/jsx/";cs.evalScript(`$.evalFile("${c}json3.jsx")`);
          const evalJSXScript = (script) => new Promise((resolve) => { cs.evalScript(script, (res) => { resolve(JSON.parse(res)); }); });
          export const getLayers = () => evalJSXScript("getAllLayers()");export const hideLayers = () => evalJSXScript("hideAllTextLayers()");


          3. 在CEP的UI層(為了更直觀,這里我們用引入react來代替html展示UI),我們大致部署一下插件的界面,用兩個(gè)按鈕分別觸發(fā)「獲取所有文字圖層」和「刪除所有文字圖層」的功能。同時(shí)為了直觀一些,我們把獲取到的所有文字圖層在插件面板上顯示:


          import React, { useState } from "react";import { hideLayers, getLayers } from "./utils/cs";import "./styles/main.css";
          export default () => { const [layers, setLayers] = useState(null); const handleGetLayers = async () => { const layers = await getLayers(); setLayers(layers); }; return ( <div style={{ width: "100vw", height: "100vh", background: "#FFF" }}> <button className="primary" onClick={handleGetLayers}> 點(diǎn)擊獲取圖層 </button> <button className="primary" onClick={hideLayers}> 點(diǎn)擊刪除全部文字圖層 </button> <div className="area"> {layers && layers.length ? layers.map((e, i) => ( <div key={i} className="layer"> {e} </div> )) : "無"} </div> </div> );};


          1. 在CEF層,我們根據(jù)上一小節(jié)「項(xiàng)目構(gòu)建」的步驟,配置好manifest.xml和整個(gè)項(xiàng)目的目錄結(jié)構(gòu),打開debug模式,并將整個(gè)CEP擴(kuò)展應(yīng)用的目錄放到相應(yīng)的路徑下;

          2. 在界面層,我們在Photoshop中隨便打開一個(gè)包含文字圖層的psd文件,然后在「窗口」-「擴(kuò)展」里面打開我們剛開發(fā)好的擴(kuò)展,就可以成功運(yùn)行了。

          讓我們試試剛剛開發(fā)的功能,例如,當(dāng)我們點(diǎn)擊「點(diǎn)擊獲取圖層」的按鈕時(shí),得到了如下的結(jié)果:

          然后我們點(diǎn)擊右側(cè)「刪除所有文字圖層」后,是不是可以發(fā)現(xiàn)打開的psd文件中的文字圖層都消失了呢?

          我把實(shí)例的項(xiàng)目放在了Lumpychen/CEP-Test[6],大家有興趣可以自己嘗試。

          簽名與發(fā)布

          現(xiàn)在我們的應(yīng)用可以在記得Photoshop中跑起來了,但是如果想讓自己的擴(kuò)展可以在設(shè)計(jì)師同事的Photoshop里運(yùn)行,我們不能給讓每個(gè)用戶都開啟一下debug模式,這太麻煩了。

          在沒有進(jìn)入debug模式的情況,Adobe CEP 擴(kuò)展必須有簽名才能正常運(yùn)行,簽名分為兩種:

          • 商業(yè)簽名證書,可以在數(shù)字簽名提供商中購買

          • 自簽名證書,可以通過Adobe官方的ZXPSignCmd 創(chuàng)建

          具體如何獲取證書、簽名打包,Adobe也提供了官方的教程:package-distribute-install-guide[7]

          同時(shí),Adobe官方也把下載、管理和更新CEP擴(kuò)展的功能集成到了Creative Cloud里,如果你安裝了Creative Cloud,它會連接Adobe Exchange——Adobe官方推出的擴(kuò)展市場,以獲取和更新我們安裝的擴(kuò)展。

          如果你想把你自己開發(fā)的擴(kuò)展發(fā)布到Adobe Exchange上,Adobe官方也提供了Exchange Portal用來發(fā)布擴(kuò)展的渠道。

          然而……

          由于Adobe在中國的業(yè)務(wù)一直處于被閹割的狀態(tài),且國內(nèi)通過Creative Cloud購買正版Adobe應(yīng)用的用戶也相對有限,所以大家很少采用官方的渠道管理和獲取Adobe產(chǎn)品的CEP擴(kuò)展。

          而國內(nèi)的Photoshop擴(kuò)展應(yīng)用的生態(tài)依然處于一個(gè)略微灰色的狀態(tài),很多擴(kuò)展的發(fā)布和都依賴第三方社區(qū)(知乎、微信公眾號、淘寶)或素材網(wǎng)站,當(dāng)然這樣的生態(tài)也催生了我國互聯(lián)網(wǎng)的歷史上一批又一批的ps大神。

          輔助工具

          文章的最后,如果你想要開發(fā)一個(gè)Adobe CEP擴(kuò)展,我這邊強(qiáng)烈推薦幾個(gè)輔助用的工具:

          • Script Listener[8]

          Script Listener是Adobe社區(qū)里推出的輔助工具,可以隨時(shí)記錄用戶對Adobe宿主程序的操作,然后生成ExtendScript腳本文件在桌面上供用戶查看和選用——使用這種方式生成ExtendScript代碼,可以讓開發(fā)者省去很多學(xué)習(xí)Extendscript API的成本。

          • JSX.js[9]

          JSX.js是提供給CEP應(yīng)用的JavaScript環(huán)境一個(gè)JS庫,可以代替原生的方法來引入ExtendScript的文件或執(zhí)行Extendscript的代碼,它解決了一個(gè)很重要的痛點(diǎn)——提供了執(zhí)行ExtendScript的報(bào)錯(cuò)信息(這比起原生調(diào)用ExtendScript代碼執(zhí)行得到一句evalScript error體驗(yàn)要強(qiáng)上很多倍)

          • ExtendScript Debugger[10]

          這是目前Adobe官方提供的,當(dāng)前版本唯一用來調(diào)試ExtendScript的工具。它是一個(gè)VSCode Debugger插件,可以像其它的VScode Debugger一樣,提供相關(guān)報(bào)錯(cuò)信息,實(shí)現(xiàn)斷點(diǎn)調(diào)試的功能。

          擴(kuò)展閱讀

          1. ADOBE PHOTOSHOP SCRIPTING

            https://www.adobe.com/devnet/photoshop/scripting.html

          2. Configure-your-extension-in-manifestxml

            https://github.com/Adobe-CEP/Getting-Started-guides#2-configure-your-extension-in-manifestxml

          3. CSInterface.js

            https://github.com/Adobe-CEP/CEP-Resources/blob/master/CEP_10.x/CSInterface.js

          4. Applications Integrated with CEP

            https://github.com/Adobe-CEP/CEP-Resources/blob/master/CEP_9.x/Documentation/CEP%209.0%20HTML%20Extension%20Cookbook.md#applications-integrated-with-cep

          5. JSON3

            https://github.com/bestiejs/json3

          6. Lumpychen/CEP-Test

            https://github.com/LumpyChen/CEP-Test

          7. package-distribute-install-guide

            https://github.com/Adobe-CEP/Getting-Started-guides/tree/master/Package%20Distribute%20Install#package-distribute-install-guide

          8. Script Listener

            https://helpx.adobe.com/photoshop/kb/downloadable-plugins-and-content.html#ScriptingListenerplugin

          9. JSX.js

            https://creative-scripts.com/jsx-js/

          10. ExtendScript Debugger

            https://marketplace.visualstudio.com/items?itemName=Adobe.extendscript-debug

          11. 《CEP Intro》

            https://github.com/Adobe-CEP/CEP-Resources

          12. 《nullice的Adobe CEP擴(kuò)展開發(fā)教程》

            http://nullice.com/archives/category/note/%E8%BD%AF%E4%BB%B6%E6%95%99%E7%A8%8B/adobe-cep

          13. 《Photoshop Scripting Documentation》

            https://www.notion.so/a908db4f72a74854b36c10e72a69b751

          14. 《Photoshop-CC-Javascript-Ref-2019》

            https://wwwimages2.adobe.com/content/dam/acom/en/devnet/photoshop/pdfs/photoshop-cc-javascript-ref-2019.pdf




          瀏覽 69
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  免费黄色视频在线观看 | 国产在线视频一区 | 久久大鸡八三级片 | 一区二区亚洲 | 午夜激情操一操 |