@tsmallfield

Designer / Frontend Developer

カヤック意匠部&技術部ブログに投稿した記事のまとめ

なんと10年ぶりの投稿!
カヤックで書いたブログ記事をまとめてみました。


目次




意匠部ブログ


2022-05-31 日本最南端のイベント・コワーキングスペース「チャレンジ石垣島」が誕生

designblog.kayac.com


2022-06-30 チャレンジ石垣島制作秘話「ロゴデザイン」編

designblog.kayac.com


2023-02-28 チャレンジ石垣島制作秘話「ライトモード/ダークモードでファビコンを切り替える」編

designblog.kayac.com




技術部ブログ『アドベントカレンダー


2020-12-24 今すぐ使える?!クリスマスイブっぽいイージング関数を作ってみよう!

techblog.kayac.com


2021-12-14 すき焼きの写真にすき焼きの3Dモデルを埋め込む方法

techblog.kayac.com


2021-12-21【解説編】すき焼きの写真にすき焼きの3Dモデルを埋め込む方法】

techblog.kayac.com


2021-12-24 トナカイと白ひげのおじいさんに学ぶUVアニメーション

techblog.kayac.com


2022-12-24【WebGL】【MSDF】 イブにお父さんがサンタに変身する話

techblog.kayac.com


2023-12-24「JS体操」のすゝめ 〜その①〜

techblog.kayac.com


2024-12-17 おもしろ社内勉強会・ワークショップ総まとめ!

techblog.kayac.com




技術部ブログ 『JS体操』


2024-04-26【JS体操】JavaScript で頭の体操をしよう!〜第1問 44文字 解説編〜

techblog.kayac.com


2024-06-17【JS体操】第2問「画像の横長具合を比較しよう」〜正攻法&ハック部門の解説〜

techblog.kayac.com


2024-07-10【JS体操】第2問「画像の横長具合を比較しよう」〜チート部門①②③の解説〜

techblog.kayac.com


2024-07-18【JS体操第3問ヒント①】Zalgo Text のできるまで

techblog.kayac.com


2024-07-23【JS体操第3問ヒント②】「コードポイント」と「コードユニット」

techblog.kayac.com


2024-07-26【JS体操第3問ヒント③】「疎」な配列を「密」にする12の方法

techblog.kayac.com


2024-07-30【JS体操第3問ヒント④】「コードポイント」を「文字列」に変換する22の方法

techblog.kayac.com


2024-08-03【JS体操】第3問「Zalgo Text の生成」延長戦のお知らせ

techblog.kayac.com


2024-08-07【JS体操】第3問「Zalgo Text の生成」〜いろんな回答紹介編〜

techblog.kayac.com


2024-12-19【JS体操】第4問「ひらがなを画数順に並び替えよう」解説(最短文字数は109文字!)

techblog.kayac.com


2024-12-19【JS体操】第5問「画像からアスキーアートを生成しよう」解説

techblog.kayac.com


2025-01-28【JS体操】応援ありがとうございました!〜全5問の振り返り〜

techblog.kayac.com




旧意匠部ブログ(※ http)


2014-05-13 U.S.A. は U.S.A でなく U.S.A. なのだ!

design.kayac.com




閃光部ブログ(※ http)


2012-01-20 お正月スペシャルコンテンツ「おHTML5」の裏側みせちゃいます #1

level0.kayac.com

2012-06-12 Deferred を作ろう!

level0.kayac.com


2012-06-25 Deferred を作ろう!#2

level0.kayac.com


2012-07-25 コールバック関数の実行回数を間引く

level0.kayac.com


2012-08-15 Deferred を使おう:CSSトランジション終了の検知

level0.kayac.com


SVGを作ってみよう

普通のサイトだとあまり使い道がないと思われがちな SVG。。。

でも場合によっては PNG や JPG よりも便利な場合もあるんです!

最近の案件でもバリバリ使ってます!

 

そんなわけで今回はSVG のつくり方を簡単にご紹介します。

 

まず、イラレで適当に図形を作ります。

f:id:tsmallfield:20140120210112p:plain

 

そして command + shift + s で別名保存。

 

f:id:tsmallfield:20140120210155p:plain

 

ファイル形式を svg にするのを忘れずに!

ファイル名を決めたら save ボタンを押して。。。

 

f:id:tsmallfield:20140120210402p:plain

 

なにやら画面が出ますが気にせず OK を押しましょう。

 

はい、おしまい。

 

作成した svgイラレで編集してもよいですし、

テキストエディタで編集してもよいでしょう。

 

ちなみにテキストエディタで開くとこんな感じ。

f:id:tsmallfield:20140120213135p:plain

 

fill や stroke、stroke-width 等、属性をいろいろ追加&編集して遊んでみましょう!

ちなみにJavaScriptを使って属性を動的に変更すれば、こんなことも。。。

 

次回は SVG の(htmlでの)表示方法について書いてみます。。。

OGP画像の見え方を簡単操作でシミュレート!

デザイナーのみなさんはOGP画像をデザインする機会がたくさんあると思います。
でもFacebookだと、OGP画像が正方形で表示されたり横長で表示されたりで、
レイアウトが大変ですよね。。。

 

そんな時に便利なのがこちら!!

 

og:image Simulator
http://ogimage.tsmallfield.com/

f:id:tsmallfield:20140108014350p:plain

 

作成したOGP画像が、Facebookのタイムライン上でどのように表示されるかを、
簡単操作でシミュレートできるWEBアプリです。

 

使い方はとっても簡単!
画像をブラウザにドラッグ&ドロップするだけ。

f:id:tsmallfield:20140108015154p:plain

正方形の場合と、横長の場合とでどのように表示されるかプレビューできます!

 

また、裏ワザ的な使い方として、
Facebookhttp://ogimage.tsmallfield.com/ をシェアする際に

f:id:tsmallfield:20140108015935p:plain

赤丸のボタン(複数のOGP画像の中から選ぶボタン)を操作することで
いろんな縦横比の画像がどのように切り取られて表示されるかを
検討することも可能です。

 

なお、現在用意しているのは

・630 x 630
・1200 x 630 (Facebook 推奨)
・1200 x 1200

の3つ。(今後増やす可能性あり)

 

OGP画像をデザインする際は
ぜひぜひ使ってみてくださいー

簡易的なBoneアニメーションを作ってみよう

Boneアニメーションと聞くとなんだか難しそうだし
しかもそれをJavaScriptでやるなんて。。。

でも簡易的なものならなんとかなるかも!

というわけで今回は最近制作したBoneアニメーションのサンプルをご紹介します。

まずはBoneを描いてみよう

まずは<canvas>の
translate(), rotate(), moveTo(), lineTo(), stroke()
を駆使して簡単な人型のBoneを描画してみます。

ここまではとっても簡単。
さて、このBoneを歩かせるには、どうすればよいでしょう?

関節を動かすには?

とりあえず、rotate() に指定している角度を動的に変化させれば良さそうです。

でも関節の角度を一つ一つ指定し、
しかもちゃんと歩いている風に調整するのはすごい作業になりそうなので
根元の関節の角度を一つ指定したら、それが先端まで伝搬していく作りにしましょう。

そのためにはBoneが親子関係を持っている必要があります。
例えば「体」の子が「腕」でその子が「手」、という感じです。

さらに親のBoneから子のBoneに角度が伝搬する際、
それぞれに係数を掛けるとよさそうです。
例えば、肩の関節を10度動かしたら、肘の関節も10度動かすのではなく、
10 に 係数 -0.5 を掛けた値、すなわち 10 * -0.5 = -5 度動かす。。。
という具合です。

関節の角度はどうやって計算する?

歩くという動作は周期的(ある一定の動きを繰り返す)なもの。
周期的な関数と聞いてまず思い浮かぶのは 正弦波:Math.sin(), Math.cos() です。
今回はこれをうまく利用しましょう。

【横軸】を歩いた距離、
【縦軸】を関節の角度
とすればいい感じになりそうですね。

体の上下の動きもわすれずに!

人が歩いている時、体は上下に動いているので
それも関節の角度と同じく sin, cos で計算しましょう。
上下の動きは、腕や足のそれと周期が違うので注意しましょう。

サンプル

各関節の角度、係数、角度変化の周期を地道に調整し、歩いている風にしてみました。

Boneの定義をしている部分は以下になります。

this.skeleton = new Skeleton([
    new Bone('body', 150, -80, .2, [
        new Bone('head', 50, 20, 1),
        new Bone('leftArm', 90, 190, -4, [
            new Bone('leftArm2', 80, -50, 1)
        ]),
        new Bone('rightArm', 90, 190, 4, [
            new Bone('rightArm2', 80, -50, 1)
        ])
    ]),
    new Bone('leftLeg', 100, 70, -1, [
        new Bone('leftLeg2', 100, 40, 1, [
            new Bone('leftFoot', 30, -110, .1)
        ])
    ]),
    new Bone('rightLeg', 100, 70, 1, [
        new Bone('rightLeg2', 100, 40, 1, [
            new Bone('rightFoot', 30, -110, .1)
        ])
    ])
]);
new Bone(ラベル, Boneの長さ, デフォルトの関節角, 係数[, 子のBoneの配列]);

Boneの長さとデフォルトの関節角で姿勢を変えることができます。

また係数を変更することで回転方向と俊敏さを調整できます。

以下は関節角を計算している部分のコードです。
移動距離から sin, cos を用いて関節角(の差分)を計算しています。

※目標角ではなく差分を与えているのは、歩く以外の動作を同時に行えるようにするためです。
例えば、吠えるとか口から熱線を出すとか。

/**
 *  @param {number} distance
 */
function update(distance) {
    var OFFSET_Y_MAX   = -10,
        ROTATION_PHASE = 200,
        ROTATION_GAIN  = .04,
        OFFSET_Y_PHASE = 100,
        OFFSET_Y_GAIN  =   3,
        deltaRad;
    
    deltaRad = Math.cos(Math.PI * 2 * (distance % ROTATION_PHASE) / ROTATION_PHASE) * ROTATION_GAIN;
    
    this.skeleton.parts.body.rotate(deltaRad);
    this.skeleton.parts.leftLeg.rotate(deltaRad);
    this.skeleton.parts.rightLeg.rotate(deltaRad);
    
    this.destOffsetY += Math.sin(Math.PI * 2 * (distance % OFFSET_Y_PHASE) / OFFSET_Y_PHASE) * OFFSET_Y_GAIN;
}

Bone の長さや係数、周期を調整するといろんな動きができるので、ぜひお試しあれ!

canvasのコードを見やすくしよう!

明けましておめでとうございます。
本年もどうぞよろしくお願いいたします。

さて、
今年から閃光部(フロントエンド)を離れ
意匠部(デザイン)の所属になるのですが
そうなるとすぐJS忘れちゃいそうで。。。

というわけで忘れないようにブログ始めます!

最初の投稿はcanvasのお話。

canvasで複雑なパスを描こうとすると。。。

(function(win, doc) {

'use strict';

var cvs = doc.createElement('canvas'),
    ctx = cvs.getContext('2d');

cvs.width  = 200;
cvs.height = 300;
doc.body.appendChild(cvs);

ctx.translate(100, 100);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, Math.PI * 2, true);
ctx.save();
for (var i = 8; i--;) {
    ctx.rotate(45 * Math.PI / 180);
    ctx.moveTo(0, -50);
    ctx.lineTo(0, -80);
}
ctx.restore();
ctx.save();
ctx.translate(-50, 100);
ctx.save();
ctx.translate(0, 0);
ctx.moveTo( 0,  0);
ctx.lineTo(20,  0);
ctx.lineTo(20, 20);
ctx.lineTo( 0, 20);
ctx.lineTo( 0, 40);
ctx.lineTo(20, 40);
ctx.restore();
ctx.save();
ctx.translate(30, 0);
ctx.moveTo( 0,  0);
ctx.lineTo(20,  0);
ctx.lineTo(20, 40);
ctx.lineTo( 0, 40);
ctx.lineTo( 0,  0);
ctx.restore();
ctx.save();
ctx.translate(60, 0);
ctx.moveTo( 0, 10);
ctx.lineTo(10,  0);
ctx.lineTo(10, 40);
ctx.moveTo( 0, 40);
ctx.lineTo(20, 40);
ctx.restore();
ctx.save();
ctx.translate(85, 0);
ctx.moveTo(20, 40);
ctx.lineTo(20,  0);
ctx.lineTo( 0, 30);
ctx.lineTo(25, 30);
ctx.restore();
ctx.restore();
ctx.stroke();

}(this, document));

見づらい(T_T)

でも、これを save() / restore() の対でインデントすると。。。

(function(win, doc) {

'use strict';

var cvs = doc.createElement('canvas'),
    ctx = cvs.getContext('2d');

cvs.width  = 200;
cvs.height = 300;
doc.body.appendChild(cvs);

ctx.translate(100, 100);
ctx.beginPath();
ctx.arc(0, 0, 30, 0, Math.PI * 2, true);
ctx.save();
    for (var i = 8; i--;) {
        ctx.rotate(45 * Math.PI / 180);
        ctx.moveTo(0, -50);
        ctx.lineTo(0, -80);
    }
ctx.restore();
ctx.save();
    ctx.translate(-50, 100);
    ctx.save();
        ctx.translate(0, 0);
        ctx.moveTo( 0,  0);
        ctx.lineTo(20,  0);
        ctx.lineTo(20, 20);
        ctx.lineTo( 0, 20);
        ctx.lineTo( 0, 40);
        ctx.lineTo(20, 40);
    ctx.restore();
    ctx.save();
        ctx.translate(30, 0);
        ctx.moveTo( 0,  0);
        ctx.lineTo(20,  0);
        ctx.lineTo(20, 40);
        ctx.lineTo( 0, 40);
        ctx.lineTo( 0,  0);
    ctx.restore();
    ctx.save();
        ctx.translate(60, 0);
        ctx.moveTo( 0, 10);
        ctx.lineTo(10,  0);
        ctx.lineTo(10, 40);
        ctx.moveTo( 0, 40);
        ctx.lineTo(20, 40);
    ctx.restore();
    ctx.save();
        ctx.translate(85, 0);
        ctx.moveTo(20, 40);
        ctx.lineTo(20,  0);
        ctx.lineTo( 0, 30);
        ctx.lineTo(25, 30);
    ctx.restore();
ctx.restore();
ctx.stroke();

}(this, document));

見やすい!

さらに beginPath() と stroke() の対もインデントすると。。。

(function(win, doc) {

'use strict';

var cvs = doc.createElement('canvas'),
    ctx = cvs.getContext('2d');

cvs.width  = 200;
cvs.height = 300;
doc.body.appendChild(cvs);

ctx.translate(100, 100);
ctx.beginPath();
    ctx.arc(0, 0, 30, 0, Math.PI * 2, true);
    ctx.save();
        for (var i = 8; i--;) {
            ctx.rotate(45 * Math.PI / 180);
            ctx.moveTo(0, -50);
            ctx.lineTo(0, -80);
        }
    ctx.restore();
    ctx.save();
        ctx.translate(-50, 100);
        ctx.save();
            ctx.translate(0, 0);
            ctx.moveTo( 0,  0);
            ctx.lineTo(20,  0);
            ctx.lineTo(20, 20);
            ctx.lineTo( 0, 20);
            ctx.lineTo( 0, 40);
            ctx.lineTo(20, 40);
        ctx.restore();
        ctx.save();
            ctx.translate(30, 0);
            ctx.moveTo( 0,  0);
            ctx.lineTo(20,  0);
            ctx.lineTo(20, 40);
            ctx.lineTo( 0, 40);
            ctx.lineTo( 0,  0);
        ctx.restore();
        ctx.save();
            ctx.translate(60, 0);
            ctx.moveTo( 0, 10);
            ctx.lineTo(10,  0);
            ctx.lineTo(10, 40);
            ctx.moveTo( 0, 40);
            ctx.lineTo(20, 40);
        ctx.restore();
        ctx.save();
            ctx.translate(85, 0);
            ctx.moveTo(20, 40);
            ctx.lineTo(20,  0);
            ctx.lineTo( 0, 30);
            ctx.lineTo(25, 30);
        ctx.restore();
    ctx.restore();
ctx.stroke();

}(this, document));

もっと見やすい!!

このお正月、<canvas>でゴニョゴニョする際はぜひお試しください。