背景
と思ったので、漫画っぽいふきだしを簡単に差し込める仕組みをつくりました。
(絵が下手なので漫画は書けないから、あらかじめ絵を用意して、やつら🍙に喋ってもらうことにした)
CSSだけでつくるのはやめた
最近ブログ界隈では吹き出しが流行っているようで、CSSで作った吹き出しで会話をさせるサイトをよく見かけます。
私がお世話になっているWordPressテンプレートのSimplicityやCocoonでも、簡単に吹き出しが使えるようになっています。
しかし…
(吹き出しを紹介する記事なので、さっきから乱用しています。)
↑のように、
- キャラクターに表情をつけられる
- 吹き出し内の色も変えつついろいろな形の吹き出しを使える
仕組み を作ることにしました。
方法
結構思考錯誤してJS使ったりすることも試したのですが、使わなくても実現できそうだったので、結局やめました。
SVGにしたのは、吹き出し内の文字の長さによって拡大縮小しても線の太さや画像の荒さが変わらないようにしたいという、エンジニアのどうでもいいこだわりです。
ふきだし
まずはふきだしを用意。
SVGを用意
これ↓を利用したときの例です。
可愛いからそのままいただきました。
※ 現在はSVGでDLできるようなので、以下の書き出しは不要。
AI形式なので、イラストレーターにて下記の設定でSVGに書き出します。
- スタイル : 「内部CSS」
- のちに削除しやすいように
- オブジェクトID : 最小
- ファイルサイズ抑えるために
- 小数点以下の桁数 : 1
- ファイルサイズ(略)
- 「縮小」にチェック
- ファイルサイズ(略)
- 「レスポンシブ」にチェック
SVGを編集
以下を削除
– 1,2行目のコメント
– <svg>
タグ
+ ver
+ id
+ x
+ y
+ style
+ xml:space
– <style>
以下を追加
* <svg>
– preserveAspectRatio="none"
* <path>
– vector-effect="non-scaling-stroke"
after
<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none" viewBox="0 0 552 253">
<path vector-effect="non-scaling-stroke" d="M411 18c-40-8-89-13-150-13s-109 5-149 13C53 29 5 66 5 126s48 98 107 109a762 762 0 0 0 172 13c50-1 92-6 127-13 27-5 46-12 65-28 3-2 11-8 20-6l20 5c20 2 31-12 31-12-1-2-13 1-22-7-6-6-11-14-13-20-1-2 1-9 1-11a103 103 0 0 0 4-30c0-60-47-97-106-108z"/>
</svg>
viewBox
削除しちゃったら全然うまく動かなくてハマった
キャラクター

よくみるこういうふきだしでは満足しない私は、
もっとまめきちまめこ、みたいな勢いと面白さを目指します。
それには面白い絵が欠かせないと思うのですが、
絵は全く得意でないので、顔と体とそれぞれ何パターンか用意して、組み合わせて使うことにしました。
絵を描く
絵が苦手すぎるので(なのに、使い方もわからずイラストレーターを持っている宝の持ち腐れ)、
ペンツールでぽちぽちと点を打って、それらを繋げて線にして、書きました。
ペンタブなんか使ってもうまく書けないので、ひたすらマウスでぽちぽちと書きました。
SVGに書き出す
顔と体をそれぞれ別々にして、SVGに書き出します。
以下の二点がポイント。
- 余白を含めたアートボードごと書き出す
- 「レスポンシブ」のチェックを外す
- あとで顔と体を合体させるため
書き出したSVGを編集する必要性はなし。
タイトルが不要なくらい?
ほんとはふきだしと同じくvector-effect="non-scaling-stroke"
を追加したいけど、
絵だとパスが多すぎていちいち追加するの大変だし、
線の太さが変わってしまうと絵が変わってしまって面倒かなぁ?と思って、
特に何もしてない。笑
HTML
この漫画っぽいふきだしシステムを、わたしは「わんごま」と名付けました。
なのでcssのクラス名はonegoma
です。
ふきだしの種類、使う顔・体、セリフをHTMLで記載します。
<div class="onegoma {$side}">
<div class="balloon" data-frame="{$frame}" data-type="{$type}">{$content}
{$balloon}</div>
<div class="character"><object data="{$body}" type="image/svg+xml" width="300" height="150"></object>
<object class="face" data="{$face}" type="image/svg+xml" width="300" height="150"></object></div>
</div>
{$変数} | 指定する内容 | |
---|---|---|
{$side} | キャラクターの位置 | CSSのクラス名 |
{$frame} | ふきだしの形 | CSSのクラス名 |
{$type} | ふきだしのデザイン | CSSのクラス名 |
{$content} | 本文 | 思うがままに書け |
{$balloon} | ふきだしのSVG | SVGファイルの中身をそのまま書き出す(... ) |
{$body} | キャラクターの体 | SVGファイルのURL |
{$body} | キャラクターの顔 | SVGファイルのURL |
ふきだしは、線や塗りつぶしの色などをCSSから編集できるように、SVGをそのまま書き出します。
顔や体はとくにいじる予定がないので、Objectとして読み込み。
「CSSのクラス名」の部分は、後述のCSSに記載したクラス名を書く。
CSS
素材は用意できたので、あとはうまく並べれば完成!
SCSS
これを機会にSCSSを使ってみました。
.onegoma {
--balloon-padding: 8%;
--balloon-padding-tail: 10%;
--character-margin-tail: -5%;
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
display: -webkit-flex;
display: -moz-flex;
display: -ms-flex;
display: -o-flex;
-webkit-box-orient: horizontal;
-webkit-box-direction: normal;
-ms-flex-direction: row;
flex-direction: row;
-webkit-flex-wrap: nowrap;
-ms-flex-wrap: nowrap;
flex-wrap: nowrap;
justify-content: center;
align-items: center;
&.left {
-webkit-box-orient: horizontal;
-webkit-box-direction: reverse;
-ms-flex-direction: row-reverse;
flex-direction: row-reverse;
.balloon {
padding-right: var(--balloon-padding);
padding-left: var(--balloon-padding-tail);
}
.character {
margin-right: var(--character-margin-tail);
margin-left: 0;
}
svg, object {
transform: scale(-1,1);
}
}
&.bottom {
-webkit-box-orient: vertical;
-ms-flex-direction: column;
flex-direction: column;
.character {
margin: 0;
margin-top: var(--character-margin-tail);
}
}
.balloon {
width: auto;
margin: 10px;
padding: var(--balloon-padding);
padding-right: var(--balloon-padding-tail);
position: relative;
z-index: 2;
svg {
width: 100%;
height: 100%;
position: absolute;
left: 0px;
top: 0px;
z-index: -1;
&> * {
fill: transparent;
stroke: black;
stroke-width: 2px;
}
}
&[data-frame='boom'] {
padding: 15%;
}
&[data-type='blue'] {
svg>* {
fill: skyblue;
stroke: transparent;
}
}
&[data-type='gold'] {
svg>* {
fill: gold;
}
}
}
.character {
width: 25%;
height: 25%;
max-width: 200px;
max-height: 200px;
margin-left: var(--character-margin-tail);
position: relative;
text-align: center;
object {
width: 100%;
height: 100%;
box-shadow: none;
&.face {
left: 0px;
top: 0px;
position: absolute;
}
}
}
}
- ふきだしの画像の上に文字を表示するために、
balloon
クラスとSVGにz-index
を指定 - キャラクターの画像を正方形で書き出していて余白が目立ったので、ネガティブマージンでちょっと寄せてみた
ショートコードを作る
毎回HTMLを描くのも面倒なので、ショートコードを作りました。
function onegomaCode($atts, $content = null) {
$url = "https://blog.kuromusubi.com/wp-content/plugins/onegoma";
$path = dirname(__FILE__);
if (is_array($atts)) {
$atts = array_filter($atts, "strlen");
// ファイルが見つからない場合は初期値を使う
foreach($atts as $k => $v) {
if (in_array($k, array('type', 'side'))) continue;
$tmparr = explode(',', $v);
foreach($tmparr as $i => $a) {
if (!count(glob($path . "/image/{*,*/*}/{$a}.svg", GLOB_BRACE)))
unset($tmparr[$i]);
}
if (count($tmparr))
$atts[$k] = implode(',', $tmparr);
else
unset($atts[$k]);
}
}
extract(shortcode_atts(array(
'frame' => 'normal',
'type' => 'normal',
'body' => 'normal',
'face' => 'normal',
'accessory' => '',
'side' => 'right'
), $atts));
$balloon = file_get_contents($path . "/image/balloon/{$frame}.svg");
$body = $url . "/image/character/body/{$body}.svg";
$face = $url . "/image/character/face/{$face}.svg";
$accessory_html = "";
if ($accessory != "")
foreach(explode(',', $accessory) as $a) {
$accessory_html .= "<object type=\"image/svg+xml\" data=\"". $url . "/image/character/accessory/{$a}.svg\" class=\"accessory\"></object>";
}
return <<<TXT
<div class="onegoma {$side}">
<div class="balloon" data-frame="{$frame}" data-type="{$type}">
{$content}
{$balloon}
</div>
<div class="character">
<object type="image/svg+xml" data="{$body}"></object>
<object type="image/svg+xml" data="{$face}" class="face"></object>
{$accessory_html}
</div>
</div>
TXT;
}
add_shortcode('onegoma', 'onegomaCode');
svgをあらかじめ階層に配置しておいて、引数の文字列のものを取ってきます。
万が一指定した画像がないときに首なしにならないように、画像がない場合はデフォルト値を使うようにしました。
コメント