先日「トプリクス for Photoshop」をリリースし、続きInDesign版を着手したところ何故かカラーテーマを切り替えてもうまくいかないゾ?となったのでいろいろ問題点を試行錯誤して解決してみました。

まずはこんな感じでPhotoshop Pluginのテンプレート「quick-layers-starter」からPhotoshop・InDesign両用のサンプルを作成しました。
HTML
<!DOCTYPE html>
<html>
<head>
<script src="main.js"></script>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<h1 id="title">Layers</h1>
<sp-body id="layers">
No layers
</sp-body>
<footer>
<div id="layerIcon"></div>
</footer>
</body>
</html>
CSS
body {
padding: 0 16px;
}
li:before {
content: '• ';
width: 3em;
}
#layers {
border: 1px solid #808080;
border-radius: 4px;
padding: 16px;
}
h1{
color: var(--uxp-host-text-color);
border-radius: 10px;
padding: 10px;
}
#layerIcon{
width: 32px;
height: 32px;
margin-right: 5px;
background-image: url("layer/dark.png");
}
#layerIcon:hover{
background-image: url("layer/light.png");
}
#layerIcon:active{
background-image: url("layer/dark.png");
}
javascript
const {entrypoints} = require("uxp");
const APID=require("uxp").host.name;
entrypoints.setup({
panels: {
vanilla: {
show(node) {
}
}
}
});
document.getElementById("layerIcon").addEventListener("click",async function(){
let allLayerNames;
if(APID=="InDesign"){
const allLayers = require("indesign").app.activeDocument.layers;
let al=[];
for(let l=0;l<allLayers.length;l++){
al.push(allLayers.item(l).name);
}
allLayerNames = al.map(layer => layer);
}else{
const app = require("photoshop").app;
const allLayers = app.activeDocument.layers;
allLayerNames = allLayers.map(layer => layer.name);
};
const sortedNames = allLayerNames.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
document.getElementById("layers").innerHTML = `
<ul>${
sortedNames.map(name => `<li>${name}</li>`).join("")
}</ul>`;
});
※manifest.jsonは割愛
改変したところはInDesign対応にしたのとh1タグを使用、ボタンを画像にしたところです。これをデバッグしてみます。まずはPhotoshop

文字のカラーはちゃんと切り替わります。もちろんこのままでは画像は切り替わりません。でもなんで画像がギザギザ?。
お次はInDesignでデバッグ

bodyタグ内にあるh1タグの色が変更されない…。まぁsp-bodyタグ内に配置すればいいんですがね。
スポンサーリンク
まずテーマの切り替えを検知してみた
実は「トプリクス for Photoshop」ではテーマの切り替えを検知して画像を切り替えたりしていました。今回のInDesign用に書くとこんな感じです。
javascript
document.theme.onUpdated.addListener(async(theme)=>{
const btElement=document.getElementById("layerIcon");
const h1Element=document.getElementById("title");
if(theme=="light" || theme=="lightest"){
h1Element.style.color="#424242";
btElement.style.backgroundImage='url("layer/light.png")';
}else{
h1Element.style.color="#ffffff";
btElement.style.backgroundImage='url("layer/dark.png")';
}
});
しかし、これだと起動時にどのテーマか分からないのでエラいことになります。それにhover・activeの設定がよくわかりません。動かすとこんな感じです。

一度でも切り替えすれば、上手くいきます。「トプリクス for Photoshop」では切り替えた時のテーマをローカルに保存して次回以降上手くいくようにしていました。
var(–uxp-host-text-color)が効かない問題
まぁまず前提としてUXPでは「Spectrum UXP widgets」というのがありまして頭に「sp」がつくやつです。「sp-label」とか「sp-body」とかですね。
こやつら使用するとテーマを切り替えても問題なく上手いことやってくれます(サンプルのレイヤー名のとこですな)。
しかし「トプリクス」ではツリー表示をするために「aタグ」やら何やらを使用しており「sp」を使用できないのです。
もしかしたら「sp-body」内に作成するようにすれば行けたかもしれませんが…。とにかくInDesign版は何故か
CSS
color: var(--uxp-host-text-color);
が効かないので、起動時に現在のテーマをチェックできないか調べたところ見つからず…。しかし意外なところに解決策はありました。
それはCSSでした
なんと公式の「CSS Reference」のところに「prefers-color-scheme」というモノがありテーマに合わせてCSSで使用できる変数を定義できたのです。
Photoshopで使用できる「–uxp-host-text-color」もデフォルトでこういう感じで定義されていたのか!
ということで今回のサンプルだと
CSS
:root {
--uxp-host-font-size: 13px;
--uxp-host-font-size-smaller: 12px;
--uxp-host-font-size-larger: 14px;
--uxp-host-text-color: #ffffff;
--uxp-host-border-color: #454545;
--uxp-host-background-color: #535353;
--layer-png: url("layer/dark.png");
--layer-hover-png: url("layer/light.png");
}
@media (prefers-color-scheme: darkest) {
:root {
--uxp-host-text-color: #ffffff;
--uxp-host-border-color: #292929;
--uxp-host-background-color: #323232;
--layer-png: url("layer/dark.png");
--layer-hover-png: url("layer/light.png");
}
}
@media (prefers-color-scheme:light) {
:root {
--uxp-host-text-color: #424242;
--uxp-host-border-color: #9c9c9c;
--uxp-host-background-color: #b8b8b8;
--layer-png: url("layer/light.png");
--layer-hover-png: url("layer/dark.png");
}
}
@media (prefers-color-scheme: lightest) {
:root {
--uxp-host-text-color: #4b4b4b;
--uxp-host-border-color: #d1d1d1;
--uxp-host-background-color: #f0f0f0;
--layer-png: url("layer/light.png");
--layer-hover-png: url("layer/dark.png");
}
}
こういう感じでrootに定義しました。ちなみに画像以外の定義はPhotoshopのデフォルトを調べて定義しているのでご参考にどうぞ。
使い方はこんな感じです。
CSS
h1{
color: var(--uxp-host-text-color);
border-radius: 10px;
padding: 10px;
}
#layerIcon{
width: 32px;
height: 32px;
margin-right: 5px;
background-image: var(--layer-png);
}
#layerIcon:hover{
background-image: var(--layer-hover-png);
}
#layerIcon:active{
background-image: var(--layer-hover-png);
}
やっと機能開発に専念できる…
これでやっと安心して眠れます。じゃなくてインターフェース関係にストレスがちょっと減って機能開発に重点がおけます。良かった…。
完成したサンプルコードをgitHubのコチラに上げておきました。ご自由にお使いください。
スポンサーリンク
More from my site
スポンサーリンク


