クソアプリ Advent Calendar 2019 16日目の記事です。
壁尻とは
いわゆる「埋め込み系」と称されるジャンルの中でも、
上半身と下半身が分断されているのが特徴。
自分の下半身の状態を確認できないもどかしさや、
尻だけが出ている状況のシュールさ、
顔の見えない下半身を犯すフェティッシュな背徳感が肝。
つまり壁から下半身が出ているシチュエーションのことです。
特に成人向け作品では、尻の近くに顔写真が貼ってあることが多いです。フェティッシュですね。
今回は壁尻になりたい皆さんの願いを叶えるWebアプリを作りました。
完成品
こちらです。
https://kabeshiri-maker.utabami.com/
あとは3秒くらい待つだけで憧れの壁尻になれます。
(Facebookでやる猛者はいるのだろうか……)
壁尻完成画面でシェアすれば、SNS上でもOGPで画像が表示されます。みんなに見てもらいましょう。
使用技術
- Nuxt.js
- Vuetify
- Firebase Authentication
- Firebase Storage
- Firebase Cloud Firestore
- Netlify
めけぽんビンゴの改装でNetlifyのPrerenderingを使う予定なので、それに合わせた技術になっています。そうです、今回の主な目的はPrerenderingのお試しです。
プロフィール画像と名前はFirebase Authenticationで取得できるので、そのまま使います。
実装
壁尻画像を生成する
async makeImage(style) {
//キャンバスの用意
const canvas = document.createElement('canvas')
var ctx = canvas.getContext('2d')
canvas.width = 600
canvas.height = 300
//背景画像を描画
const baseImage = await loadImage(
require('~/assets/kabe_' + style + '.png')
)
ctx.drawImage(baseImage, 0, 0)
//アイコンを描画
const profileImage = await loadImage(auth.user.photoURL)
ctx.drawImage(profileImage, 320, 40, 96, 96)
//テキストを描画
ctx.font = "18px 'M PLUS Rounded 1c'"
ctx.fillText(auth.user.displayName, 320, 160)
return canvas.toDataURL()
}
//画像読み込み
function loadImage(url) {
return new Promise(resolve => {
const img = new Image()
img.onload = () => {
resolve(img)
}
img.onerror = e => {
console.log(e)
resolve()
}
img.setAttribute('crossOrigin', 'Anonymous')
img.crossOrigin = 'Anonymous'
img.src = url
})
}
今回は複雑な画像の加工はしないので、HTML5 Canvasでモリモリッと作っています。
余談ですが、もう少し複雑なことをするときはFabric.jsというライブラリを使っています。
完成した壁尻を表示するページ
<template>
<v-layout column justify-center align-center>
<v-flex class="headline my-6" xs12 sm8 md6>{{name}}の壁尻</v-flex>
<v-flex xs12 sm8 md6>
<v-card class="mb-5">
<v-card-text>
<v-img :src="image"/>
</v-card-text>
<v-card-text>
<v-layout column justify-center>
<v-flex xs12>
<v-btn
class="mb-3"
color="#55acee"
style="width:100%"
x-large
@click="share('twitter')"
>Twitterに投稿</v-btn>
</v-flex>
<v-flex xs12>
<v-btn
class="mb-3"
color="#385185"
style="width:100%"
x-large
@click="share('facebook')"
>Facebookにシェア</v-btn>
</v-flex>
</v-layout>
</v-card-text>
</v-card>
<makeKabeshiri/>
</v-flex>
</v-layout>
</template>
<script>
import { store } from '~/plugins/app'
import makeKabeshiri from '~/components/makeKabeshiri'
export default {
components: {
makeKabeshiri
},
data: () => ({
name: '',
image: ''
}),
async asyncData({ params }) {
//データセットしていく
const user = await store
.collection('users')
.doc(params.userId)
.get()
return {
name: user.data().displayName,
image: user.data().image
}
},
head() {
return {
title: this.name + 'の壁尻',
meta: [
{
hid: 'og:image',
property: 'og:image',
content: this.image
},
{
hid: 'twitter:image',
name: 'twitter:image',
content: this.image
}
]
}
},
methods: {
share(target) {
let shareUrl = ''
if (target === 'twitter') {
const baseUrl = 'https://twitter.com/intent/tweet?'
const text = ['text', '壁尻になりました!']
const hashtags = ['hashtags', 'みんなで壁尻メーカー']
const url = ['url', location.href]
const query = new URLSearchParams([text, hashtags, url]).toString()
shareUrl = `${baseUrl}${query}`
} else if (target === 'facebook') {
const baseUrl = 'https://www.facebook.com/sharer/sharer.php?'
const url = ['u', location.href]
const query = new URLSearchParams([url]).toString()
shareUrl = `${baseUrl}${query}`
}
window.open(
shareUrl,
'share',
'width=600, height=400, personalbar=0, toolbar=0, scrollbars=1, sizable=1'
)
}
}
}
</script>
NuxtのasyncDataってSPAモードでも動くんですね。偏見でSSRでしか動かないと思っていました。
NetlifyのPre-RenderingをON!
NetlifyのSettings > Build & deploy > Prerenderingのチェックを付けます。
これだけでjsで設定したOGP画像が表示されます!すごい!!!しかも結構早い!!!
ハマった?ところ
プロフィール画像はCORSによる制限が緩い
今までの経験で「外部画像をCanvasに読み込む場合、CORSでひっかかってうまく読み込めないことが多い」ということが身に染みていたので、当初はFirebase Functionsをプロキシ代わりにするつもりで実装してたのですが、後になってプロフィール画像は"Access-Control-Allow-Origin: *"になっていることに気づきました。
プロフィール画像はどんなサイトでも使えるようにしてあるのですね。
パンツ密着させすぎた
このサービスで使っているお尻は自前で描きました。冷静に見ると、女のほうのパンツを密着させすぎた感がありますね。もうちょっと密着度低めのリアルよりのほうがよかったかも。
まとめ
ということでNetlifyのPrerenderingのお試しとしてクソアプリを作ってみました。
せっかくなら完全成人向けにして、アイコンでなく自分で描いたイラストが使えたり、あらかじめ用意されたセリフや液体や落書きをレイヤーで重ねて実用性を上げてみたいところです。
需要ありそうならやるかもしれませんので、その時はよろしくお願いします。