最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 使用JavaScript开发一个Photoshop插件

    正文概述 掘金(奇舞精选)   2021-03-15   646

    作为前端开发者,我们可以利用Web技术在非常多的环境下开发应用,为相关的用户提供服务。其中,以Photoshop为首的Adobe系列工具是我们时长要去面对的一个平台级应用。Photoshop在图像处理上有着很强大的功能,用户量也非常可观,而且其功能在前端开发的一些情况下也用得到,因此笔者认为Photoshop相关的Web技术具有很不错的价值。

    本文将引导大家使用JavaScript开发一个Photoshop插件

    CEP:通用扩展平台

    Adobe作为一家历史悠久的软件公司,已经给开发者提供了相对成熟的扩展开发技术栈,被称作CEP——Common Extensibility Platform(通用扩展平台)。

    使用JavaScript开发一个Photoshop插件

    CEP扩展基于Web技术,可以在Adobe Photoshop、Adobe Illustrator、Adobe InDesign等全系列应用中运行,并且可以访问这些应用和外部操作系统环境的API。

    CEP应用的结构可以被分为五个抽象层级:

    使用JavaScript开发一个Photoshop插件

    1. 用户层,用户所得到的、构建出来的应用外部;
    2. 宿主应用层,我们的CEP扩展在宿主应用中被配置好后,会在嵌入的CEF(一个开源的、嵌入基于Chromium内核浏览器的简单框架)中成功渲染;
    3. UI层,就是基于HTML文件构建的WEB页面;
    4. Javascript层,运行在UI层页面上的JavaScript脚本,比起一般Web应用的环境里内置了更多的功能——可以访问Extendscript层与一些宿主应用原生功能的API以及本机中Nodejs的API
    5. Extendscript层,运行在宿主应用内部的脚本,具有访问宿主应用的内部API的能力,可以和JavaScript层之间通信;

    所谓宿主应用,就是我们CEP扩展运行在的Adobe程序,例如Adobe Photoshop等,同时后文我们也默认CEP的宿主程序是Adobe Photoshop

    ExtendScript

    作为一个类Web应用,上面四层相对前端开发者来说都比较好理解,这一节我们来看下ExtendScript层:

    ExtendScript脚本可以用三套不同语言去编写,分别为JavaScript、VBScript和AppleScript。三种语言功能上没有任何区别。鉴于本文面向的是各位前端工程师,我们果断选择前者,同时文章的后文我们也是默认选择JavaScript版本的ExtendScript。

    ExtendScript有以下特点:

    • 区别于 CEP 扩展中后缀为.js的 JavaScript 文件,操作ExtendScript 的JavaScript文件后缀名为.jsx

      这里的.jsx文件和react用到的.jsx文件完全不同,如果你在自己的CEP应用中引入了react,记得把它们分开以避免混淆

    • ExtendScript在全局下内置了用来获取和操作Adobe应用和文件内容的各种API

    • Adobe应用中,ExtendScript脚本和CEP中的JavaScript脚本运行于两个不同的引擎,如果我们选择JavaScript语言接口的ExtendScript脚本,对应的引擎仅仅兼容至 ECMAScript3的标准

    了解了Extendscript之后,我们再来看一下CEP扩展各层级之间的横向关系:

    使用JavaScript开发一个Photoshop插件

    • CEP扩展中的JavaScript代码会在CEP JavaScript VM 中运行,比起一般的Web应用,增加了调用Node.js的API与操作系统交互,以及通过引入CSInterface.js调用ExtendScript的功能
    • 宿主程序中,作为ExtendScript的JavaScript代码会在另一个环境下——Host JavaScript VM中被解析
    • 在这一个类Web应用中包含两个脚本环境,两个环境虽然都是JavaScript,而且可以通过传递字符串相互通信,但是是其上下文是相互隔离的,一定要区分开来

    关于Photoshop中,ExtendScript具体可以调用的API,我们可以直接看Adobe的官方手册:ADOBE PHOTOSHOP SCRIPTING)

    项目构建

    在动手开发前,我们先把运行CEP扩展的各种要素准备齐全。

    首先我们来看下CEP扩展需要的目录结构:

    使用JavaScript开发一个Photoshop插件

    • CSXS/manifest.xml必需,项目的配置文件,配置CEP扩展应用的窗体大小、入口的html文件地址、入口jsx(ExtendScript)文件地址、版本兼容、启动选项等信息,由于篇幅所限我们不在本文里具体展开,官方提供了配置文件的指南:Configure-your-extension-in-manifestxml

    • client/index.htmlclient/index.jsclient/style.css:CEP应用相关页面、脚本、样式,就是我们CEP扩展和Web相关的全部文件

    • client/CSInterface.js:Adobe官方提供的工具库,需要在JavaScript层引入,封装并提供了访问ExtendScript层和一些原生功能的API,官方也在github上提供了文件CSInterface.js。

      这个工具库大概一千多行,其中很大一部分是描述各个函数功能的注释,所以可以直接通过阅读注释来学习这个工具库的用法。

      CEP扩展中的JavaScript环境下本身就内置了调用ExtendScript环境的类,引入的CSInterface.js是对环境里调用ExtendScript环境的类进行封装使得开发者更便于调用而已,所以引入CSInterface.js并不是必要的。

    • host/index.jsx:ExtendScript的脚本,访问宿主应用的内部API的能力,在CEP扩展中,ExtendScript文件有两种加载方式:

      • 在CEP扩展内用JavaScript通过CSInterface.js封装好的方法主动进行加载
      • manifest.xml中通过配置入口的jsx(ExtendScript)文件的脚本,在CEP扩展应用运行的第一时间进行加载

    最后,我们要把建立好的CEP扩展的目录放到Photoshop指定的位置:

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

    win:{Photoshop安装路径}\Required\CEP\extensions

    这样Photoshop就可以加载我们开发的扩展,出现在其菜单栏中的「窗口」-「扩展」中。

    debug模式与调试

    看了这么多概念,我们动手试试吧!

    新建CEP扩展的目录之后,我们尝试在Photoshop菜单栏的「窗口」-「扩展」中运行扩展,就发现了一个问题:

    使用JavaScript开发一个Photoshop插件

    这是因为我们新建的CEP扩展没有经过签名认证。

    为了绕过这个认证,我们需要打开Photoshop的debug模式:

    • 首先,我们要获取自己当前机器上Adobe CEP的版是CEP几,关于Adobe不同应用的种类和版本的简称,我们可以看官方提供的对应: Applications Integrated with CEP
    • 得到当前CEP的版本后,我们可以通过下面的方法进入debug模式(记得将下列CSXS.[n]中的[n]用你目前的CEP版本替换)
      • 如果你是Windows用户,你需要:
        • 打开 regedit
        • 找到HKEY_CURRENT_USER/Software/Adobe/CSXS.[n]
        • 然后添加一个叫PlayerDebugMode的字段
        • 设置值为string类型的"1"
      • 如果你是macOS用户,你需要:
        • 打开终端输入: defaults write com.adobe.CSXS.[n] PlayerDebugMode 1
        • 你需要在终端输入ps -axu $USER|grep cfprefsd,找到cfprefsd这个进程的pid,然后用kill命令删掉它(或者你也可以直接重新启动你的机器)。

    执行完上面的操作后,你就可以在自己的Photoshop里运行自己新建的扩展了。

    同时,如果你想调试自己的扩展,可以在目录指定位置中添加.debug文件:

    使用JavaScript开发一个Photoshop插件

    .debug文件中,我们指定开发的应用可以在哪个宿主应用和哪个端口进行调试:

    <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,点击「Port forwarding...」监听我们在.debug中设置的端口,我们可以看到的自己的应用:

    使用JavaScript开发一个Photoshop插件

    熟悉移动端调试的读者一定对这个界面不陌生,我们找到自己的应用并点开「inspect」,就可以在指定端口通过chrome的开发者工具来同步调试运行的CEP扩展了。

    Case:开发一个可以「获取/删除所有文字图层」的Photoshop插件

    我们从前文提到的「CEP应用结构的五个层级」自下向上来构建:

    1. 首先,在Extendscript层,我们先在全局定义好「获取所有文字图层」和「删除所有文字图层」的功能函数:

      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来获取或者操作图层
      • 同时,我们通过返回字符串类型的结果,让CEP的JavaScript端得以获取

      由于在Extendscript环境下,JavaScript仅兼容ES3,而且ExtendScript和CEP JavaScript之间只能通过字符串进行通信,所以我们要在ExtendScript的环境下引入JSON3作为JSON功能的polyfill(注意这和CEP的JavaScript无关)

    2. 在CEP的JavaScript层,我们在utils/cs.js中使用Promise封装好界面上用得到的的hideLayersgetLayers函数——调用Extendscript中已经定义好在全局的方法,并处理返回的字符串:

      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),我们大致部署一下插件的界面,用两个按钮分别触发「获取所有文字图层」和「删除所有文字图层」的功能。同时为了直观一些,我们把获取到的所有文字图层在插件面板上显示:

      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}>
              点击获取图层
            </button>
            <button className="primary" onClick={hideLayers}>
              点击删除全部文字图层
            </button>
            <div className="area">
              {layers && layers.length
                ? layers.map((e, i) => (
                    <div key={i} className="layer">
                      {e}
                    </div>
                  ))
                : "无"}
            </div>
          </div>
        );
      };
      
    4. 在CEF层,我们根据上一小节「项目构建」的步骤,配置好manifest.xml和整个项目的目录结构,打开debug模式,并将整个CEP扩展应用的目录放到相应的路径下;

    5. 在界面层,我们在Photoshop中随便打开一个包含文字图层的psd文件,然后在「窗口」-「扩展」里面打开我们刚开发好的扩展,就可以成功运行了。

      让我们试试刚刚开发的功能,例如,当我们点击「点击获取图层」的按钮时,得到了如下的结果:

      使用JavaScript开发一个Photoshop插件

      然后我们点击右侧「删除所有文字图层」后,是不是可以发现打开的psd文件中的文字图层都消失了呢?

      我把实例的项目放在了Lumpychen/CEP-Test,大家有兴趣可以自己尝试。

    签名与发布

    现在我们的应用可以在记得Photoshop中跑起来了,但是如果想让自己的扩展可以在设计师同事的Photoshop里运行,我们不能给让每个用户都开启一下debug模式,这太麻烦了。

    在没有进入debug模式的情况,Adobe CEP 扩展必须有签名才能正常运行,签名分为两种:

    • 商业签名证书,可以在数字签名提供商中购买
    • 自签名证书,可以通过Adobe官方的 ZXPSignCmd 创建

    具体如何获取证书、签名打包,Adobe也提供了官方的教程:package-distribute-install-guide

    同时,Adobe官方也把下载、管理和更新CEP扩展的功能集成到了Creative Cloud里,如果你安装了Creative Cloud,它会连接Adobe Exchange——Adobe官方推出的扩展市场,以获取和更新我们安装的扩展。

    如果你想把你自己开发的扩展发布到Adobe Exchange上,Adobe官方也提供了Exchange Portal用来发布扩展的渠道。

    然而……

    使用JavaScript开发一个Photoshop插件

    由于Adobe在中国的业务一直处于被阉割的状态,且国内通过Creative Cloud购买正版Adobe应用的用户也相对有限,所以大家很少采用官方的渠道管理和获取Adobe产品的CEP扩展。

    使用JavaScript开发一个Photoshop插件

    而国内的Photoshop扩展应用的生态依然处于一个略微灰色的状态,很多扩展的发布和都依赖第三方社区(知乎、微信公众号、淘宝)或素材网站,当然这样的生态也催生了我国互联网的历史上一批又一批的ps大神。

    辅助工具

    文章的最后,如果你想要开发一个Adobe CEP扩展,我这边强烈推荐几个辅助用的工具:

    • Script Listener

      使用JavaScript开发一个Photoshop插件

      Script Listener是Adobe社区里推出的辅助工具,可以随时记录用户对Adobe宿主程序的操作,然后生成ExtendScript脚本文件在桌面上供用户查看和选用——使用这种方式生成ExtendScript代码,可以让开发者省去很多学习Extendscript API的成本。

    • JSX.js

      使用JavaScript开发一个Photoshop插件

      JSX.js是提供给CEP应用的JavaScript环境一个JS库,可以代替原生的方法来引入ExtendScript的文件或执行Extendscript的代码,它解决了一个很重要的痛点——提供了执行ExtendScript的报错信息(这比起原生调用ExtendScript代码执行得到一句evalScript error体验要强上很多倍)

    • ExtendScript Debugger

      使用JavaScript开发一个Photoshop插件

      这是目前Adobe官方提供的,当前版本唯一用来调试ExtendScript的工具。它是一个VSCode Debugger插件,可以像其它的VScode Debugger一样,提供相关报错信息,实现断点调试的功能。

    扩展阅读

    • 《CEP Intro》
    • 《nullice的Adobe CEP扩展开发教程》
    • 《Photoshop Scripting Documentation》
    • 《Photoshop-CC-Javascript-Ref-2019》

    起源地下载网 » 使用JavaScript开发一个Photoshop插件

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元