LoginSignup
1
0

正弦波を使ってオリジナルパワポ背景生成器を作った

Last updated at Posted at 2024-05-24

はじめに

オリジナルパワポ背景、欲しいですよね。
それどころか、もしそれぞれのページに固有の背景パターンを作れたら、どうでしょう。

もしセクションごとに背景パターンが異なると、「違う話を始めたな」と 視覚的に 分かります。(もちろんちゃんとそれが分かるようにお話するべきであるのは間違いないですが、、、)

今回は、テキストからパワポ背景に変換するサイトを作りました。

これには見てて面白いの王、見てて面白いキングであるところの (正弦波による) 合成波 を描画しています。

image.png

仕組み

発想はいたって単純

これだけです。

実装

弊ライブラリ HotSoupScriptを使っています。

テキストを数値に変換

ぶっちゃけ単射でも全射でもあるほど一意性に対する需要はないので、charコードを足し算しているだけです

function TextToSeed(text) {
	let seed = 0
	for (let i = 0; i < text.length; i++) {
		seed += text.charCodeAt(i)
	}

	return seed
}

乱数シードに

高級乱数には詳しくありませんが、標準的な乱数には「シード値」があって、そのシード値を設定すると決まった順番の乱数が排出されます。

JavaScriptの標準乱数であるところのMath.random()は初期シードを設定できません。 (参考)
なので、シード値を設定できる自前の乱数関数を作る必要があります。

簡単な実装として XorShift アルゴリズムがあります。
特に暗号性に対する需要がないので、こちらを選択。

コードをコピペするのは申し訳ないので、参照元の記事をペタリ
JavaScriptで再現性のある乱数を生成する + 指定した範囲の乱数を生成する

これで 入力テキストに対して一意の乱数列 が得られます。

sin関数のパラメーターを生成

$sin$関数の一般形は、 $x$を変数として
$d\sin{(ax + b)}$
ですね。振幅、角速度、位相。

まずはそれを実装。

class Sin {
	constructor(amplitude, angularVelocity, phase) {
		this.amplitude = amplitude
		this.angularVelocity = angularVelocity
		this.phase = phase
	}

	Calc(x) {
		return this.amplitude * Math.sin(this.angularVelocity * x + this.phase)
	}
}

先ほどの乱数生成器Randomクラスを使って、パラメーターを割り当てます。

function MakeSinsRandomly(
	amount,
	amplitudeWidth = 2.5,
	amplitudeMin = 0.1,
	angularVelocityWidth = 0.2,
	angularVelocityMin = 0.05,
	phaseShiftMax = 2 * Math.PI,
) {
	const sins = []
	const random = new Random(textSeed)
	for (let cnt = 0; cnt < amount; cnt++) {
		sins.push(
			new Sin(
				random.nextFloat() * amplitudeWidth + amplitudeMin,
				random.nextFloat() * angularVelocityWidth + angularVelocityMin,
				random.nextFloat() * phaseShiftMax,
			),
		)
	}

	return sins
}

複数のsin関数を合成して描画

合成はただの足し算

function Func(x, sins) {
	let value = 0
	for (let cnt = 0; cnt < sins.length; cnt++) {
		value += sins[cnt].Calc(x)
	}

	return value
}

描画は弊ライブラリHotSoupScriptの腕の見せ所、これだけ

function _DrawCurve(curve, lineWidth = 3) {
	for (let i = 0; i < curve.length - 1; i++) {
		DrawLine(
			curve[i][0],
			curve[i][1],
			curve[i + 1][0],
			curve[i + 1][1],
			lineWidth,
		)
	}
}

要するに隣り合う2点に直線を引くのを繰り替えしていますが、それぞれの直線が短いので、遠目に見ると綺麗な曲線に見えるってやつですね。

結果

あんみつの王 あんみつキング
image.png

忸怩の王、忸怩キング
image.png

ちょ待てよの王、ちょ待てよキング
image.png

バリエーションあるよ(笑)

右上埋め
image.png

右埋め
image.png

上埋めず
image.png

上埋め
image.png

この記事にいいね、レポジトリにスターつけてくださると泣いて喜びます!!!!!!!!!!!!!!1

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0