TR小米哥 发表于 2022-1-4 15:18

【Javascript】【CEP教程-3】 CEP插件面板结构介绍

!(https://s2.loli.net/2022/01/04/3zKj7wi4LN1tMyO.png)
# 前言
原计划这篇文章要写开发工具和调试环境的,但是后来发现如果不先介绍CEP面板的基本结构的话,会对调试环境的配置的理解有障碍,于是本篇文章介绍一下CEP插件的基本分层结构和文件目录结构。

# 分层结构
!(https://s2.loli.net/2022/01/04/akbxl6WRTOfrv3q.png)
CEP的全称是Common Extensibility Platform,是Adobe在CC2014版本一起推出的扩展开发平台,在CC2014及以前,相对应的面板插件开发,是基于Flash开发平台,后来随着web的发展以及flash的逐渐没落,adobe随记放弃了使用flash来开发插件,拥抱web开发模式,CEP的插件开发,即全部采用的web开发技术。

Adobe通过在Photoshop中嵌入了一个浏览器框架CEF(Chromium Embeded Framework),使得我们可以通过像开发网页一样来开发插件面板,用到的技术和网页开发的技术基本是一致的,也即是
> HTML + CSS + JAVASCRIPT

面板负责呈现基本的内容和交互提供给用户,实际控制PS则依然用的宿主自身提供的脚本引擎,也即是Extension Script,分层结构图如下
!(https://s2.loli.net/2022/01/04/qES9ixstPlXfLCW.png)
# 运行结构
需要注意的一个地方是,Extension Script是运行在Ps的脚本引擎下的,它是EcmaScript的一个子集,它实现的是EcmaScript 3的标准,而运行在CEF下的Javascript是通过Google V8引擎来驱动的,它实现的是EcmaScript 5标准,两者是有一些差异的,最简单的理解,就是JSX里头包含的js特性要更少一些,比如不支持箭头函数,Array 对象没有 indexOf 方法等等,在实际开发的时候,不要想当然、随心所欲的写……

另外,PS在嵌入CEF的时候,同时在浏览器环境下嵌入了Node运行环境,于是你可以在开发网页的时候,使用nodejs的一些功能,比如你可以在面板中通过nodejs访问本地文件等等,在后续文章中专门来做介绍。

JSX中,脚本引擎也提供了本地路径访问的能力(File/Folder对象),这个也在后续的文章中介绍。
!(https://s2.loli.net/2022/01/04/chwurY4pKR1VSI2.png)
# 通信方式
由于面板和JSX是运行在不同的脚本环境下的,这就需要他们之间有一个通信的渠道,这样才能通过CEF中的JS来控制JSX,进而操作PS
> CEF -> JS -> JSX -> Photoshop

## JS -> JSX
为了能够让运行在浏览器中的JS,可以访问JSX脚本,adobe提供了一个基础库来实现(http://https://github.com/Adobe-CEP/CEP-Resources/tree/master/CEP_9.x)
> 注意
CSInterface.js是有版本的概念的,它随着PS的版本发布,不断在发布更新,高版本的CSInterface.js文件,在低版本的Ps中会有一些功能不可用,比如上面链接的版本是CEP_9.x,对应的是CC2018及以上的版本,在挑选该文件的时候需要特别注意

通过该基础库的api,我们可以直接运行JSX的代码
```
var cs = new CSInterface();
cs.evalScript(`alert(app.documents.length)`);
````

上面是一个非常简单的例子,实际使用中,我们会用到更多复杂的运用方式,后续文章中会在详细介绍。
## JSX -> JS
反过来,如果要从JSX发送一些数据给JS层,有两种途径

### 1.代码执行的返回结果
还是上面那个例子,我们改造一下
```
var cs = new CSInterface();
cs.evalScript(`app.documents.length`, function (result) {
    console.log(result);
});
````
**evalScript**方法的第二个参数,即是JSX运行的结果返回,通过这种方式,可以直接从JSX获取到执行结果,并返回到JS层。
### 2.事件派发
上面的方法只有在JS调用JSX的时候进行返回,当我们需要在某些特定场景主动发送数据给JS的时候,可以通过事件发送的方式来实现

```
// JSX
var eventObj = new CSXSEvent();
eventObj.type = "your-event-type";
eventObj.data = 'pass data from here';
eventObj.dispatch();
````
上面的data即是需要发送的数据,type的值可以自己定义,在JS层通过监听对应的事件来获取数据
```
// JS
var cs = new CSInterface();
cs.addEventListener("your-event-type", (event) => {
    var data = event.data;
    console.log(data);// output: pass data from here
});
````
# 面板的目录结构
CEP面板的文件结构,本质上是一堆web文件的集合,即html/css/js/jsx和一些图片等资源,除了有一个指定的目录文件规则之外,其它的目录结构可以自己定义,一版常见的目录结构如下
> panel-name
| - CSXS
| - | - manifest.xml
| - js
| - css
| - jsx
| - index.html

面板的目录结构,只有一条规则,即根目录下必须有一个叫**CSXS**文件夹,该文件夹下必须有一个manifest.xml文件,我们接下来详细介绍一下该文件

**manifest.xml**定义了此面板的一些基本信息,比如id,version,入口文件等,下面是Ps自带的Library插件面板的manifest.xml文件,为了简要说明,我删掉了一些内容
```
<?xml version="1.0" encoding="UTF-8"?>

<ExtensionManifest Version="7.0" ExtensionBundleId="com.adobe.DesignLibraries.angular.2015.1" ExtensionBundleVersion="3.14.242"
      ExtensionBundleName="DesignLibrary" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" DevBundleVersion="3.14.0">
    <ExtensionList>
      <!-- 插件面板的ID,一版是com.xxx.xxx的形式,Version是插件的版本 -->
      <Extension Id="com.adobe.DesignLibraries.angular" Version="1.0" />
    </ExtensionList>
    <ExecutionEnvironment>
      <HostList>
            <!-- 支持的宿主,比如Photoshop: PSXS,InDesign: IDSN 等等 -->
            <!-- Version是支持的宿主版本范围 -->
            <Host Name="PHXS" Version="" />
            <Host Name="PHSP" Version="" />
      </HostList>
      <LocaleList>
            <Locale Code="All" />
      </LocaleList>
      <RequiredRuntimeList>
            <!-- 支持的CSinterface的对应的版本 -->
            <RequiredRuntime Name="CSXS" Version="5.0" />
      </RequiredRuntimeList>
    </ExecutionEnvironment>
    <DispatchInfoList>
      <Extension Id="com.adobe.DesignLibraries.angular">
            <DispatchInfo>
                <Resources>
                  <!-- 面板的html文件路径 -->
                  <MainPath>./index.html</MainPath>
                  <CEFCommandLine>
                        <!-- CEF的启动参数 -->
                        <Parameter>--high-dpi-support=1</Parameter>
                        <Parameter>--enable-nodejs</Parameter>
                        <Parameter>--mixed-context</Parameter>
                        <Parameter>--disable-accelerated-video-decode</Parameter>
                        <Parameter>--disable-threaded-scrolling</Parameter>
                        <Parameter>--disable-pinch</Parameter>
                  </CEFCommandLine>
                  <ScriptPath>./jsx/core.jsx</ScriptPath>
                </Resources>
                <Lifecycle>
                  <AutoVisible>true</AutoVisible>
                </Lifecycle>
                <UI>
                  <Type>Panel</Type> <!-- 面板类型 -->
                  <Menu>%DL_LIBRARIES_PANEL_NAME</Menu> <!-- 面板名称 -->
                  <Geometry>
                        <!-- 面板尺寸 -->
                        <Size>
                            <Height>300</Height>
                            <Width>245</Width>
                        </Size>
                        <MinSize>
                            <Height>165</Height>
                            <Width>245</Width>
                        </MinSize>
                        <MaxSize>
                            <Height>7680</Height>
                            <Width>7680</Width>
                        </MaxSize>
                  </Geometry>
                  <Icons>
                        <!-- 不同主题下的面板图标 -->
                        <Icon Type="Normal">./images/IconLight.png</Icon>
                        <Icon Type="RollOver">./images/IconLight.png</Icon>
                        <Icon Type="DarkNormal">./images/IconDark.png</Icon>
                        <Icon Type="DarkRollOver">./images/IconDark.png</Icon>
                  </Icons>
                </UI>
            </DispatchInfo>
      </Extension>
    </DispatchInfoList>
</ExtensionManifest>
```

该配置的大多数内容都在上面注释中体现了,这里重点提几个地方
```
<HostList>
    <Host Name="PHXS" Version="" />
    <Host Name="PHSP" Version="" />
</HostList>
```
**Version**字段的含义是支持的宿主版本区间,版本号你可以通过Ps的关于来查看,比如22.0对应的是CC2021的版本

!(https://s2.loli.net/2022/01/04/GbrqCsFnQSI8wUX.png)
的含义是,支持从CC2021开始及往后的PS的版本,也可以省略后面的99.9,比如这样
```
<HostList>
    <Host Name="PHXS" Version="22.0" />
</HostList>

```
比如你想要支持的Ps版本是CC2015到CC2021,就可以这么写
```
<HostList>
    <Host Name="PHXS" Version="" />
</HostList>
```

版本/版本号/CEP版本/CSXS的对应关系如下


| PS版本 | 版本号 | CEP版本 | CSXS |
| -------- | -------- | -------- |-------- |
|CC2015        |16.0        |6.x        |CSXS.6
|CC2016        |17.0        |7.x        |CSXS.7
|CC2017        |18.0        |8.x        |CSXS.8
|CC2018        |19.0        |9.x        |CSXS.9
|CC2019        |20.0        |10.x        |CSXS.10
|CC2020        |21.0        |11.x        |CSXS.11
|CC2021        |22.0        |12.x        |CSXS.12

第二个要注意的地方是CEF的启动参数
```
<CEFCommandLine>
    <Parameter>--high-dpi-support=1</Parameter>
    <Parameter>--enable-nodejs</Parameter>
    <Parameter>--mixed-context</Parameter>
    <Parameter>--disable-accelerated-video-decode</Parameter>
    <Parameter>--disable-threaded-scrolling</Parameter>
    <Parameter>--disable-pinch</Parameter>
</CEFCommandLine>
```

这些参数是在Ps加载插件面板,启动浏览器时候给提供的参数,其中重点关注的是** –enable-nodejs** ,这个选项如果不加的话,你就不能再浏览器里头使用nodejs的特性了。

第三个是面板的类型 **Type**,面板提供了4这种类型, **Panel, Model, Modeless, invsible**,不同的类型在不同的场景会使用到,一般常用的是Panel类型,其它类型我们会在后续文章中涉及到时候再介绍。

# 结束
下一篇,我们继续介绍CEP开发的工具挑选和调试环境配置,敬请期待

z3597666 发表于 2022-8-4 09:29

师傅,第二节,JSX -> JS事件派发,为什么我写好的代码,在其他电脑js没有反应呢,相当于我的电脑可以接收jsx传参   但是换到其他电脑就失效了,是不是其他电脑的ps要配置一下什么
页: [1]
查看完整版本: 【Javascript】【CEP教程-3】 CEP插件面板结构介绍