22
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

AdobeXDでCSSグラデーションを書き出すプラグインを作ってみた

Last updated at Posted at 2018-10-16

これは

2018/10/15にリリースされた Adobe XD 13 から、プラグインを作れるようになったらしい
JavaScriptで作れて便利そうなので、試しに作ってみた

参考にする/したもの

開発準備

基本的には、 誰もが見ているはずのHelloWorldの記事 を見れば分かるはずなのでここでは説明しない
本記事では、上の記事の helloHandlerFunction を編集するものとして説明する

何を作るか

XDにはcssを書き出す機能がないので、それを作ればよさそうと思った
何を自動で生成させるとよさそうかと考えたとき、グラデーションをcssにできれば便利そうだと思った

Adobe XDで作れるグラデーション

線形グラデーション (linear-gradient)

スクリーンショット 2018-10-17 1.10.18.png

円形グラデーション (radial-gradient)

※今回は作らない
スクリーンショット 2018-10-17 1.10.23.png

作っていくよ

とりあえず選択した図形の情報を取ってみる

選択した図形は selection.items に配列で入る
なので適当に console.log で出してあげれば何かわかりそう

function helloHandlerFunction(selection) {
  console.log(selection.items);
}
スクリーンショット 2018-10-17 1.19.50.png これらの長方形、楕円形、線で試してみる
[ Rectangle ('長方形') {
    width: 258, height: 242
    global X,Y: 943, 5
    parent: Artboard ('Web 1920 – 1')
    stroke: ff707070
    fill: LinearGradientFill
  },
  Ellipse ('楕円形') {
    width: 273, height: 273
    global X,Y: 1259, 5
    parent: Artboard ('Web 1920 – 1')
    stroke: ff707070
    fill: fff08c8c
  },
  Line ('線') {
    width: 186, height: 229
    global X,Y: 1581.5, 18.5
    parent: Artboard ('Web 1920 – 1')
    stroke: ff7be539
  } ]

長方形の LinearGradientFill を見るとグラデーションがわかりそう

塗り情報を詳しく見てみる

単純にそれぞれの fill を見るだけ

function helloHandlerFunction(selection) {
  const items = selection.items;

  items.forEach(item => {
    console.log(item.fill);
  });
}

さっきの図形たちで確認する

// 長方形 (グラデーション)
{ endY: 1,
  endX: 1,
  startY: 0,
  startX: 0,
  colorStops: [ { color: [Object], stop: 0 }, { color: [Object], stop: 1 } ],
  sx: 1,
  sy: 1 }

// 楕円形 (ベタ塗り)
{ value: 4293954700 }

// 線 (塗りの概念なし)
null

長方形は LinearGradientFill の詳細が見えた
リファレンスはこちら

スクリーンショット 2018-10-17 1.35.41.png `startX` `startY` `endX` `endY` は、長方形の左上を `(0,0)` 右下を `(1,1)` としたときのグラデーション位置の座標 なお、 `sx` `sy` は、リファレンスに情報がないので謎 `colorStops` を見ると、色の設定がわかりそう

ちなみに、
ベタ塗りの楕円形は #F08C8C の上2桁に alpha情報 FF をつけた FFF08C8C の10進数
線は塗りの概念がないのでnull

塗りの数値をrgbaにするコードがこちら
多分もっといい書き方があると思う
(追記編集) String.slice 使うほうがいいじゃん
(更に追記編集) Color.toRgba() が用意されていた

/**
 * 色をcssのrgba()に変換
 * @param {Color} color 変換する色
 */
function toCssRgba(color) {
  const {r, g, b, a} = color.toRgba();
  return `rgba(${r}, ${g}, ${b}, ${a})`;
}

グラデーションの色情報を見てみる

colorStops を詳しく見てみる
またここからは楕円形、線は見ないことにする

function helloHandlerFunction(selection) {
  const items = selection.items;

  items.forEach(item => {
    console.log(item.fill.colorStops);
  });
}
[ { color: { value: 4280795042 }, stop: 0 },
  { color: { value: 4282601983 }, stop: 1 } ]

色が切り替わるポイントの位置と、その位置の色が、ポイントの配列で分かる
stop がグラデーションの線分を1としたときの位置
パーセンテージにすればcssでそのまま利用できる
また、color.value で色が分かる

グラデーションの角度を求める

長方形の幅、高さ、グラデーション線分の座標が取得できているので、計算するだけ
2点間の距離と角度と座標の求め方 を参考にした

function helloHandlerFunction(selection) {
  const items = selection.items;

  items.forEach(item => {
    const startX = item.width * item.fill.startX;
    const startY = item.height * item.fill.startY;
    const endX = item.width * item.fill.endX;
    const endY = item.height * item.fill.endY;
    const deg = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI + 90;
    console.log(`${deg}deg`);
  });
}
133.16716049405795deg

そのまま linear-gradient() にいれる角度として使える
また90度を足さないと、正しい角度にならないっぽいので足す

cssに変換する

今まで出した情報を linear-gradient() にいれていくだけ

function helloHandlerFunction(selection) {
  const items = selection.items;
  const css = items.map(item => {
    // degを求める
    const startX = item.width * item.fill.startX;
    const startY = item.height * item.fill.startY;
    const endX = item.width * item.fill.endX;
    const endY = item.height * item.fill.endY;
    const deg = Math.atan2(endY - startY, endX - startX) * 180 / Math.PI + 90;

    const colors = item.fill.colorStops
      .map(point => {
      // 色の10進数の数値を16進数の文字列に変更
      const color = toCssRgba(point.color);
      return `${color} ${point.stop * 100}%`;
       })
      .join(', ');

    return `.${item.name} { background: linear-gradient(${deg}deg, ${colors}); }`;
  });

  console.log(css.join('\n'));
}

これを実行すると

.長方形 {
  background: linear-gradient(133.16716049405795deg, rgba(39, 191, 162, 255) 0%, rgba(67, 81, 255, 255) 100%);
}

無事 linear-gradient を取得できた

XDのグラデーション

スクリーンショット 2018-10-17 2.06.36.png

出力したcssを適用させた<div>

スクリーンショット 2018-10-17 2.07.10.png

完全に一致

今できていないこと

グラデーション線分の位置が中途半端なときの計算

スクリーンショット 2018-10-17 2.10.20.png

グラデーションの開始・終了位置が変わるため、linear-gradient での色の位置を調整する必要がある
このまま出力するとこんなになり、全然違う

スクリーンショット 2018-10-17 2.12.26.png

radial-gradient

多分できるが、寝たいのでやらなかった

プラグイン作成に便利そうなもの

AdobeXD typings

AdobeXD公式が typings を提供しており、TypeScriptでの開発も柔軟にできそう

終わりに

煮るなり焼くなりしていただけると幸い

プラグインの開発のしやすさがとても気持ちよかった
はじめてのAdobe XDプラグイン開発!定番のHello Worldを表示させてみよう を見ればいいが、プラグインの再読込がショートカットでできたり、デベロッパーコンソールもとてもいい機能

AdobeXDは Sketchと比べるとまだまだ機能が少ないが、少ないからこそシンプルだったり、軽かったり、プロトタイピング機能が便利だったりするので、使うプロジェクトも増えてきていると思う
そこでアホみたいな手作業をプラグインによって自動化できれば、楽しい未来しか見えてこないのではないかと感じた

22
12
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
22
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?