generated at
ランダムに背景を切り替える
アクセス毎に背景画像がランダムで変更されます。
thanks
#Todo 外出先だとバッテリー消費がえげつないので、端末がモバイルであるときは機能を制限したいところ。
使用法
以下のコードをUserScriptとして打ち込む。
なお、 ${} は置換されるであろう文字を指す。
HowToUse.js
import setBackgroundRandomly from "https://scrapbox.io/api/code/appbirdNotebook-public/ランダムに背景を切り替える/script.js"; setBackgroundRandomly("${userName}",true);

setBackgroundRandomly(userName,unavailableWhenMobile,pageName,projectName)
userName:string
使用者のユーザー名
unavailableWhenMobile:boolean
モバイルの時(画面横幅が764px以下)、画面切り替えを無効にする。
初期値 true
pageName:string
ページ名
どのmuseumページ(後述)を適用するかを指定できる。
ページごとにグループをわけて、気分ごとに背景グループを変える…なんてことも。
projectName:string
プロジェクト名
自分の所有しているプロジェクトのうち一つを指定することで、そのプロジェクトに存在するmuseumページをそのまま適用することが出来る。

museumページとは?
別途に用意した ${userName}-museum というページ(関数に指定すればどのような名前のページでも可能)に画像を複数貼り付ける。
このように背景画像のために用意されたページのことを museumページ と呼ぶことにする。
背景にしたい画像が掲載されている行のインデントの深度を一段にすると、その画像を背景候補にすることができる。
一段のインデントを持つもの以外は全てスルーされる。

写真の下の行に以下のプロパティを、一段インデントを下げてCSSコードを書き込むことで画像のカスタムが可能になる。
filter: brightness(60%) blur(3px);
など。文字「`」によるインラインコード化が必須となる。
コードブロック code:css では無視される。
初期値は
filter: brightness(50%) blur(2px);
background-position: center;
である。
一番上の、画像が上に一切ない行にこれらの設定を書き込むと、それが初期値となる。

追加用法1:UserCSSとの併用で訪問者の閲覧時にも画像の背景を表示する。(静的)
この挙動はUserScriptによるものであり、編集者以外のアクセス者には一切影響しない
このScriptだけを適用しても訪問者には一切背景は表示されません。

もしも訪問者にも静的な背景を表示したいとなれば、以下のUserCSSで設定ができます。
この関数 setBackgroundRandomly を実行すると、要素 body にクラス .setBackgroundByUserScript が付与されます。
そのため
styleForVisitor.css
@import "https://scrapbox.io/api/code/appbirdNotebook-public/Scrapboxに不動の背景をつける/style.css"; body:not(.setBackgroundByUserScript)::before{ background-image: url(/* 画像URL */); filter: /* optional */; }
と、属性セレクタと否定疑似要素を用いることで、UserScriptによる背景画像の設定も上書きされることもなく、訪問者に背景を提供することが可能になります。

定義
script.js
import HelperAboutAjax from "https://scrapbox.io/api/code/appbirdNotebook-public/HelperAboutAjax/script.js"; export default function setBackgroundRandomly(userName,unavailableWhenMobile,noteName = `${userName}-museum`,projectName = scrapbox.Project.name){ if (unavailableWhenMobile && navigator.userAgent.match(/iPhone|Android.+Mobile/) ) return; HelperAboutAjax.loadCodeFromProvidedURL( `https://scrapbox.io/api/pages/${projectName}/${noteName}/text`, `ページ${projectName}/${noteName}がありません。`).then( text => { const data = interpret(text); const selectedIndex = Math.floor(Math.random()*data.length); if (data.length === 0) throw new Error("画像が一つも指定されていません。") const option = data[selectedIndex]; console.info(`setBackgroundRandomly: ${option.get("background-image")}`) setBackground(option); }).catch(err => alert(err)) } function interpret(text){ const dataInText = text.split("\n").filter( (row) => (/^\s/).test(row)); let defaultOptions = new Map(); defaultOptions.set("filter","brightness(50%) blur(2px)") defaultOptions.set("background-position","center") let result = []; let targetIndex = 0; for (const data of dataInText){ if ((/^(\s\[https:\/\/gyazo.com\/.+\])$/).test(data)) { //入力行が写真であった場合 targetIndex = result.push(new Map()) - 1; result[targetIndex].set("background-image",`url(${data.replace(/[ \[\]]/g,"")}/thumb/1000)`); for (const option of defaultOptions) result[targetIndex].set(option[0],option[1]); continue; }else if ((/^(\s`[a-zA-Z\d- ]+:[a-zA-Z\d-()%\s!]+;`)$/).test(data)) { //入力行がオプションであった場合 const option = data.replace("\t","").replace(/[`;]/g,"").split(":"); option[0] = option[0].replace(/ /g,"") if (result.length === 0){ //写真入力がまだなく、オプションが書き込まれている場合 defaultOptions.set(option[0],option[1]); continue; } result[targetIndex].set(option[0],option[1]); }else { console.info( `以下の行が無視されました。 行の内容: ${data}`); } } return result; } function setBackground(options){ document.body.classList.add("setBackgroundByUserScript"); let result = ""; for (const option of options) result += `${option[0]}:${option[1]};\n\t\t\t`; const rule = ` body::before { ${result} background-repeat: no-repeat; background-size: cover; z-index:-1; position: fixed; height: 100vh; width: 100%; content: " "; overflow: hidden; }` document.styleSheets[0].insertRule(rule) console.info(`設定されたCSS:\n${rule}`) }

実装メモ書き
attr background-image に対応しておらず、手段として用いることが出来ない。
今後対応される可能性は十二分にある。
body.sheet から insertRule を用いて入力するのは、 sheet がもう宣言されていないため不可
document.styleSheets から直接ルールを挿入する insertRule は、他の箇所で定義された効果を全てリセットする?
https://gyazo.com/${id}/thumb/1000 はその画像のURLに直接リダイレクトされる。

思ったこと
ここで、一度に表示される可能性のある背景は、自分が把握できる量だけを入れておくべきかもしれない。
引用符を5画像ぐらいに付けるのが最適?
何の画像が出てくるかある程度見慣れていないと記事を書くのに集中できない?

更新しないと背景が更新されない。
つまり、Scrapboxの別ページからこれを適用してるページに戻っても反応されない可能性がある。

モバイルからだとめっちゃ重い
ので、モバイルからのアクセス(画面横サイズが 764px 以下みたいな)の時は、この関数を実行しないといった if 文を挟んでおくべきだと思う。