Help us understand the problem. What is going on with this article?

【CSS/Javascript】手書き風の文字を錬成して時代錯誤に立ち向かえ

More than 1 year has passed since last update.

TL;DR

  • 手書き文化は滅べ
  • それっぽく対抗してみた
  • 実運用は自己責任で…

intro

わし「ES提出したるで~、OpenES(※)でいくらでも出したるわ」
企業「手書きね^^」
わし「」

こういう非効率の塊みたいな企業が死滅することを祈りながら、技術的に解決することを試みる。

※OpenES: Web上で書いてそのまま提出できるES。ガクチカ(学生時代に力を入れていたこと)という9割の人間はろくに書けない質問などを提供してくれる

目標

ぱっとみ手書きっぽくないようなフォントの組み合わせとかを錬成。

使用フォント

1: それっぽいフォントを組み合わせる

CSSを整備する。

@font-face {
    font-family: 'Kalam';
    font-weight: bold; /* ここをboldに指定することで、標準の太さフォントを太字と誤認させる */
    src: local('Kalam'), local('Kalam-Regular'),
         url('./fonts/kalam/kalam-v9-latin-regular.woff2') format('woff2'),
         url('./fonts/kalam/kalam-v9-latin-regular.woff') format('woff');
}
@font-face {
    font-family: 'dartsfont';
    src: local('dartsfont'), 
         url('./fonts/dartsfont/dartsfont.eot?#iefix') format('eot'),
         url('./fonts/dartsfont/dartsfont.woff') format('woff');
}

/* 手書き風 */
.hw {
    font-family: 'Kalam', 'dartsfont';
    font-weight: bold;
    letter-spacing: -1px;         /* そのままだと若干幅が広い。お好みで */
    text-shadow: 0 0 1px #EEE;    /* 影をつけると文字が濃く見える。好み */
    color: #222;                  /* ここもお好み */
    transform: rotate(0.05deg);   /* Windows Chromeできれいに描画してもらうため */
}

フォントはcssの中身見て適宜配置。これでひとまずそれっぽくなる。

この他に、行間とかを調整するためにpを修飾する。

p {
    white-space: pre-line;  /* コピペできるように */
    font-size: 1.4rem;      /* 文字サイズ。任意 */
    line-height: 1.3;       /* 行間。任意 */
    line-break: strict;     /* 禁則処理。あったほうが自然 */
    text-align: justify;    /* 両端揃え。これも多分あったほうがいい */
}

これで準備1は完了。
以上のCSSを使用して、文章をHTMLで書いてみるとこんな感じで表示される。
(文章は適当にここから拝借)
image.png

わりとそれっぽい。
半角数字は全体的に詰まってみえるため、1文字なら全角を使うことを推奨。
(上の画像でいうと「学生位」の部分)

2: ランダム性を導入する

コード

このままだとPCで出力した感がまだ残っている。
というのも、各フォントごとの文字の形が全く同じだからである。

これを解消するのにJavascriptを使用する。
jQuerysugarjsを使用して、こんな感じで書いてみた。

Sugar.extend();

$(() => {
    var hws = $(".hw");
    hws.each((i,e) => {
        console.log(e.textContent.split(''));
        e.innerHTML = e.textContent.split('').map(t => {
            if(t === '\n') return `<br/>`;
            if(t === '\t') return ``;
            return `<span style="${generateRandomizeStyle()}">${t}</span>`;
        }).join("");
    });
});

function generateRandomizeStyle(){
    const CharBeautyRate = 500; // 文字の綺麗さ指数。だいたい100-1000の範囲
    var color = Number.random(0, 0x30);
    var colorRgb = [1,1,1].map(e => color);
    var tax = 1 + Number.random(-10, 10) / CharBeautyRate;
    var tby = 1 + Number.random(-10, 10) / CharBeautyRate;
    var tay = Number.random(-10, 10) / CharBeautyRate;
    var tbx = Number.random(-10, 10) / CharBeautyRate;
    var transfromLocate = [1,1].map(e => Number.random(-5, 5) / 10);
    var letterSpace = Number.random(-8, -5) / 5;
    return `
        display: inline-block;
        white-space: pre;
        color: rgb(${colorRgb});
        letter-spacing: ${letterSpace}px;
        transform: matrix(${tax},${tay},${tbx},${tby},${transfromLocate});
    `;
}

各文字ごとに<span>で囲み、それぞれについてランダムで少し文字を変形させる。
このとき、あんまり派手に変形させると変な文字になるので、微小にずらしている。
調整しているパラメーターは「色」「文字空白」「文字形状」の3つ。

文字形状の調整

色、空白はランダム化させるだけでいいが、形状はそこまで単純でもない。
今回は、transform:matrixを使用した。

matrixは行列形式で文字変形を指定する。
詳しくはググってもらうのが早いが、簡単に説明すると
matrix(a, b, c, d, e, f)と指定した場合、前半のa~dの部分が行列になる。

\begin{matrix}
a & b \\
c & d 
\end{matrix}

一切の変換を施さない行列はというと、

\begin{matrix}
1 & 0 \\
0 & 1 
\end{matrix}

になる。
今回は少しだけ動かしたいので、

\begin{matrix}
1+δw & 0+δx \\
0+δy & 1+δz 
\end{matrix}

といったようにパラメーターを微小に動かす。
ここの値の動かし度合いで字の汚さを簡易的に指定することができる。

先程のコードでいうと

var tax = 1 + Number.random(-10, 10) / CharBeautyRate;
var tby = 1 + Number.random(-10, 10) / CharBeautyRate;
var tay = Number.random(-10, 10) / CharBeautyRate;
var tbx = Number.random(-10, 10) / CharBeautyRate;

CharBeautyRateの部分である。

サンプル例

上記コードを当てはめると、こんな感じの文字になる。

CharBeautyRate=500
CharBeautyRate=500

CharBeautyRate=300
image.png

CharBeautyRate=100
image.png

CharBeautyRate=50
image.png

CharBeautyRate=50ぐらいになるとどういった変形を施しているかが明確になる。
徐々に文字が変な形になることがわかるだろう。
手書き風かつ丁寧な文章にしたいので、200-500ぐらいが無難だろうか。

今回はNumber.randomで一様乱数を使っているが、正規分布に従わせるとよりそれっぽくなりそう。

demo

つくりました。
https://arika0093.github.io/handwriting/tools.html

image.png
生成ボタンを押すたびに字の形状が毎回変わります。

課題

  • フォントの太さが均一
    • text-shadowでうまいこと調整できるか
    • ボールペン字ならそこまで気にならないか
  • とめはね等の調節
    • さすがに厳しい
  • 文字変形の単純さ
    • うまい方法があまり思いつかない
  • 字の「癖」の再現
    • transform:matrixを一様乱数でなくある程度の傾向をつける等?
  • 実際のESに貼り付ける方法
    • Word等で位置を調節して印刷が一番無難?
  • いつ使うのか
    • どうでもいい企業にしか使えないよね…

参考文献

https://xar.sh/post/95166529739/
https://sugarjs.com/docs/#/Number/random
https://qiita.com/junya/items/a1ad6126fa0315acc2aa
https://ginpen.com/2018/11/13/understanding-transform-matrix/
https://understanding-transform-matrix.ginpei.info/

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした