🏆

canvasにトーナメントを書く

2022/03/08に公開

konvajsでcanvasに図形を描画するとき、canvasの左上を(0,0)として図形が通る点の座標や高さ、幅などを指定します。
今回はトーナメント表を書くときに「こうしたら楽だった」ということをまとめてみようと思います。

動的にデータを渡してトーナメントを生成する

座標の計算式を書く

ここからは数列の話になります。
まず、最小のブランケットの高さをB、ブランケット同士の間隔をMとします。

そうすると、2回戦のブランケットの高さAと3回戦のブランケットの高さCは

A = \text{\(\frac 1 2\)}B*2 + M = B + M
C = \text{\(\frac 1 2\)}A*2 + A = 2A

同様に4回戦のブランケットの高さDも作図するとわかるのですが、

D = \text{\(\frac 1 2\)}C*2 + C = 2C

とおけます。

ここで簡略化のためにB=Mとすると、

A = 2B
C = 2A = 4B
D = 2C = 4A = 8B

となります。
1回戦のブランケットの横線のY座標b_n

b_0 = 0
b_n = b_0 + n * B

2回戦のブランケットの横線のY座標a_n

a_0 = \text{\(\frac 1 2\)}B
a_n = a_0 + n * A = \text{\(\frac 1 2\)}B + 2n * B

3回戦のブランケットの横線のY座標c_n

c_0 = \text{\(\frac 1 2\)}(A+B)
c_n = c_0 + n * C = \text{\(\frac 3 2\)}B + 4n * B

同様に、4回戦のブランケットの横線のY座標d_n

d_0 = \text{\(\frac 1 2\)}(A+B+C)
d_n = d_0 + n * D = \text{\(\frac 7 2\)}B + 8n * B

( nはプログラムの都合上、n=0,1,2...としています。)

お、数式書けそうですね!
(r+1)回戦のとき、n番目の線のY座標は

y = \text{\(\frac 1 2\)} * (2^r -1) + 2^r * B * n

x座標も同様に、横線の長さlを用いて(r=0,1,2...)

x = l * r

コードを書こう

l: lineWidth
r: roundIdx
n: gameIdx
B: BLOCK

として、太さ5pxの線を書いています。
nが偶数と奇数の場合で縦線を書く処理も要るのですが、ここでは割愛します。

import { Line } from "react-konva";
const lineBeginPointX = lineWidth * roundIdx;
const lineBeginPointY =
    (1 / 2) * ((Math.pow(2, roundIdx) - 1) * BLOCK) +
    Math.pow(2, roundIdx) * BLOCK * gameIdx;
...
    <Line
        opacity={!game.firstTeamName && !game.lastTeamName ? 0 : 1}
        x={adjustX + lineBeginPointX}
        y={adjustY + 10 + lineBeginPointY}
        fillLinearGradientColorStops={fillColor(
            progress * rounds.length - roundIdx
        )}
        points={[0, 0, lineWidth, 0, lineWidth, 5, 0, 5]}
        closed
        fillLinearGradientStartPoint={{ x: 0, y: 0 }}
        fillLinearGradientEndPoint={{ x: lineWidth, y: 5 }}
        width={lineWidth}
        height={5}
    />

渡すデータが固定の時はわざわざ数式を立てなくてもいいかもしれませんが、意外ときれいに書けると楽しいよね!という話でした。

完成例

今回のトーナメントコンポーネントは以下のページなどで使っています。
https://cap-baseball.com/GameList/26

こんなサービス作ってます

https://cap-baseball.com/
https://cap-scorebook.com
https://draft-now.com
https://pawapro-gen.netlify.app/

Discussion