html2canvas で 画像生成

vue.js で html2canvas 決定版


ラブレターみたいなのを作りたい。
ラブレターではphp側で画像を生成して出力している。


参考
https://love-letter.club/
https://wood-roots.com/web/vue-js/2253



# 特徴



# PHP側


○ ユーザーの環境に依存しない

X サーバー重くなる
X 絵文字使えない (強引にライブラリ入れりゃ使えるが・・・ユーザー側の絵文字更新に応じ要変更)

# JS側で生成

○ サーバーに負荷をかけない
○ 絵文字使える

X ユーザーの環境によってバグったりする
X 環境がバラバラなのでデバッグに手間がかかる


ただ、これからの時代は jsで 生成したい。



# インストール


α版を指定してインストールする

```

npm install html2canvas@1.0.0-alpha.12

```




# 注意

・CSSで body に フォントを設定しない。
・バージョンは アルファ版を使う。
・npm update すると α版ではなく、stableにされるので、再度入れ直す必要がある。
・でかいモニターで出力すると線が入る ( 画像がにじむ )
これはしょうがないので諦める。

```hoge.vue

<style>


    #preview {
        overflow: auto;
        width: 100%;
    }

    #preview_inner {
        background-size: 600px auto;
        position: relative;
        width: 600px;
    }


    #letter_body {
        position: relative;

        border-left: 17px solid #fbbfc8;
        border-right: 17px solid #fbbfc8;

        display: inline-block;
        font-size: 1.5rem;
        color: #444;
        margin-top: -30px;
        padding: 10px 10px 10px 10px !important;
        min-width: 600px;
        text-align: center;

        height:200px;

        display: table-cell; /* IE8から使用可能 */
        vertical-align: middle;
        white-space: pre-wrap;
    }

</style>



<template>
    <div>


        <img v-if="imgData" :src="'/gcp-storage/' + imgData" style="width: 95%;">

        <el-input type="textarea" v-model="message" :rows=5></el-input>
        <el-button type="primary" @click="generate">画像を生成</el-button>


            <div id="preview" style="display: block;">
                <div id="preview_inner">
                    <div id="letter_top"><img src="/img/tegami-top.png"></div>
                    <div id="letter_body">--</div>
                    <div id="letter_bottom"><img src="/img/tegami-bottom.png"></div>
                </div>
            </div>


            <div id="text_body">{{ message }}</div>


            <h2>完成品</h2>

            <div id="result"></div>


    </div>
</template>

<script>

    import html2canvas from 'html2canvas'//古いと、文字のサイズがずれるので、 vue.blade で 読みコンで使う

    export default {

        data() {
            return {
                imgData:'',
                message:'',
            };
        },
        created () {
            this.message = 'つけめんそばざるうどん恋をした夜はすべてがうまくいきそうで。';
        },
        watch: {

        },
        methods: {

            generate(){


                    //まずはテキスト部分だけ生成させる
                    let vc = this;

                    html2canvas(document.querySelector("#text_body"),{
                        scale: 2 //文字がぼやけないように
                    }).then(function(canvas){


                        //まずは一旦テキストを画像に
                        var letter_body = document.querySelector("#letter_body");
                        letter_body.innerHTML = '';
                        letter_body.appendChild(canvas);
                        vc.letterHeight = document.getElementById('letter_body').offsetHeight;

                        //その後、メイン画像として生成
                        html2canvas(document.querySelector("#preview_inner"),{
                            scale: 2
                        }).then(function(canvas){

                            var result = document.querySelector("#result");
                            result.innerHTML = '';
                            result.appendChild(canvas);

                            // document.getElementById('preview').style.display = "none";
                            // document.getElementById('result').style.display = "none";


                            // 以下、サーバーに送る処理
                            // var dataURI = canvas.toDataURL('image/png');
                            // let dataform = new FormData();
                            // //
                            // const message_tmp = document.getElementsByName("message");
                            // dataform.append('id',vc.$route.params.id);
                            // dataform.append('body',message_tmp[0].value);
                            // dataform.append('img',dataURI);
                            //
                            // //サーバー側に画像を保存
                            // axios.post('/hoge/makeGcpOnly/', dataform).then(e => {
                            //
                            //     vc.imgData = e.data;
                            //     vc.dialogVisible = false;
                            //     vc.message = '';
                            //     vc.loading = false;
                            //
                            // }).catch((error) => {
                            //     console.log(error);
                            //     console.log("エラー");
                            // });

                        });


                    });

                }




        }
    };
</script>


```


これで画像が生成される。


![名称未設定-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/31338/ccb1c84d-c68e-bf76-3f5c-94361aa5cf85.png)