syakoo's Lab

技術ブログやちょっと気合の入った記事を残すブログ

ポケモン風のツールチップを作るログ(d3.js)

はじめに

ここはポケモン風のツールチップを作るログを残した記事です。 結果やコードはQrunchにあげるのでそちらを見てください。

ポケモン風のツールチップを作ってみた(d3.js) | Qrunch(クランチ)

まずは

まずはどんな風なツールチップを作るか考える。小さいころからお世話になったポケモンの体力バーみたいなものを作りたいけれど、ポケモンと言っても作品によってデザインが違うのでどれを作ろうか眺めてみる。

BW2がよさそうだな...

f:id:syakoo:20190611192318j:plain (公式ホームページより)

デザインもシンプルでかっこいい。そして作れそうだったからこれに決定。

設計図

設計図なんて普段全然書かないくせに、調子に乗って描いてみる。 f:id:syakoo:20190611192820p:plain

雑すぎるけど、個人開発だし何となく目途がたったからいいよね。 本当はLv.のところに個数を入れたいけど、後に考えることにする。 図にもあるけれど、ツールチップは大まかにベースとなる黒いやつとバーと後はテキストになると考えた。

まずはベースを作ってみる

ベース作り

ベースはよく見ると多角形になっているのがわかる。多角形をd3で描写するのはそんなに難しいことはなく、SVGpolygonというタグがある。このpolygonについての説明はこちらを見れば大変参考になるが、簡単に言うと、

<polygon points="x1,y1 x2,y2 ..."/>

みたいな感じでpointsに頂点を渡してあげればそれらを結んだ多角形を作ってくれる。てことで、頂点の位置を考えてみる。

f:id:syakoo:20190611194718p:plain
頂点の位置

変数はベースの幅であるwidthheight。それを使ってさっきの画面っぽい座標を求めてみるとこうなった。この座標を実際にd3を使って描いてみると...

// 土台
var base = tooltip.append("polygon")
    .attr("points", (height * 2 / 7 + "," + 0 + " " +
        0 + "," + height * 3 / 7 + " " +
        height * 4 / 7 + "," + height + " " +
        (width - height * 2 / 7) + "," + height + " " +
        width + "," + height * 2 / 7 + " " +
        (width - height * 2 / 7) + "," + 0 + " ")
    )
    .attr("stroke", "#000")
    .attr("fill", "#303030");

f:id:syakoo:20190611194753p:plain
ベース

おお、コードは見にくいけどそれっぽい。これでベースは一応完成とする。

バー

バーは棒グラフ作る要領でやれば簡単なのでは...?と思うかもしれないが、ちょっとしたテクニックが必要になる。

このバーは(多分)二個の長方形からなっている為、普通の棒グラフと違って二個描写する必要がある。 ここで、グループとして二つの棒をまとめるやり方を採用した。一つ一つ描くのもできないことはないが、まとめといた方が楽。 考え方としてはこんな感じ

f:id:syakoo:20190611201533p:plain
二つのrectをまとめる

これを使うとこうなった。

const bar_size = {"width": width/2 , "height": base_size.height/3};
//バーのグループ
var bars = tooltip.append("g")
    .attr("transform", function () {
        return "translate(" + (width*2/5) + ", " + (height*2/5) + ")";
    });

//グループの上にバーの背景を追加
bars.append("rect")
    .attr("x", 0).attr("y", 0)
    .attr("width", bar_size.width)
    .attr("height", bar_size.height)
    .attr("fill","#000")
    .attr("rx",2);

var bar_scale = d3.scaleLinear().domain([0, 100]).rangeRound([0, bar_size.width]);
//グループの上にバーを追加
var bar = bars.append("rect")
    .attr("x", 0).attr("y", bar_size.height*1/6)
    .attr("width", bar_scale(90))
    .attr("height", bar_size.height*2/3)
    .attr("fill","#00ff22")
    .attr("stroke","rgba(40,40,40,0.8)")
    .style("stroke-width",3)
    .attr("rx",2);

f:id:syakoo:20190611201954p:plain
ベースとバー

良い感じ。

仕上げ

記事が長くなるのが嫌なので、テキストは割愛して完成。テキストはそれぞれtextタグをアペンドしただけです。

完成

まあまあカッコよくできたんじゃないかと思う。文字の太さ等を厳密に可変にするのは今の僕には無理なので、現実性はなさそう。

f:id:syakoo:20190611213157p:plain

まとめ

またいつか面白い物を作ってみようと思う