【WordPress】会話風吹き出しをプラグインなしで実装してみた【WP】

更新日:

【WP】会話風吹き出しをプラグインなしで実装してみた【WordPress】

 

 

ソルト

ソルト

会話風ふきだしって?


今のアナタよ!!

ルナリス

ルナリス


ソルト

ソルト

なんと!?!

目的

世に出ているふきだしプラグインは機能が豊富すぎて逆に使いづらかったので、シンプルな会話風ふきだしを実装してみました。
プラグインを使いたくない、シンプルなものが使いたいといった方はぜひ参考にして下さい。

実装例

今回はfunctions.phpとstyle.cssを編集して会話風吹き出しを実装します。

会話風吹き出しの機能実装

functions.phpに会話風吹き出しの機能を実装します。

//エスケープ処理
if ( ! function_exists( 'the_h' ) ){
    function the_h( $txt ){
        echo esc_html( $txt );
    }
}

//画像アップロードボタンの追加
//メディアアップローダの読込
function load_wp_enqueue_media() {
    wp_enqueue_media();
}
add_action( 'admin_print_scripts', 'load_wp_enqueue_media' );
//画像アップロード用のタグを出力
function generate_up_img_tag($name, $value){ ?>
    <input type="hidden" name="<?php the_h($name); ?>" id="<?php the_h($name); ?>" value="<?php echo esc_url($value); ?>">
    <div style="margin-bottom:25px;">
        <input type="button" name="<?php the_h($name); ?>_slect" value="アップロード" />
        <input type="button" name="<?php the_h($name); ?>_clear" value="クリア" />
    </div>
    <div id="<?php the_h($name); ?>_thumbnail" class="uploded-thumbnail">
        <?php if ($value): ?>
            <img src="<?php echo esc_url($value); ?>" alt="選択中の画像" style="max-width: 100%;">
        <?php else: ?>
            <p class="description">画像が選択されていません。</p>
        <?php endif; ?>
    </div>
    <script type="text/javascript">
        (function ($) {

            var custom_uploader;
            $("input:button[name=<?php the_h($name); ?>_slect]").click(function(e) {
                e.preventDefault();
                if (custom_uploader) {
                    custom_uploader.open();
                    return;
                }
                custom_uploader = wp.media({
                    title: "画像を選択してください",
                    library: { type: "image" },
                    button: { text: "画像の選択" },
                    multiple: false
                });
                custom_uploader.on("select", function() {
                    var images = custom_uploader.state().get("selection");
                    images.each(function(file){
                        $("input:hidden[name=<?php the_h($name); ?>]").val("");
                        $("#<?php the_h($name); ?>_thumbnail").empty();
                        $("input:hidden[name=<?php the_h($name); ?>]").val(file.attributes.sizes.full.url);
                        $("#<?php the_h($name); ?>_thumbnail").append('<img src="'+file.attributes.sizes.full.url+'" alt="選択中の画像" style="max-width: 100%;" />');
                    });
                });
                custom_uploader.open();
            });
            $("input:button[name=<?php the_h($name); ?>_clear]").click(function() {
                $("input:hidden[name=<?php the_h($name); ?>]").val("");
                $("#<?php the_h($name); ?>_thumbnail").empty();
                $('#<?php the_h($name); ?>_thumbnail').append('<p class="description">画像が選択されていません。</p>');
            });
        })(jQuery);
    </script>
<?php
}

//会話風ふきだし
//ふきだしメニュー追加
add_action( 'admin_menu', 'my_add_talk_menu' );
function my_add_talk_menu(){
    add_menu_page( '会話風ふきだし', '会話風ふきだし', 'manage_options', 'talk_menu', 'my_add_talk_menu_page', 'dashicons-format-status'); 
}
function my_add_talk_menu_page(){
    ?>
        <style>
            #wpbody-content .wrap td img { max-width:100px !important;}
            #wpbody-content .wrap li { border-top: solid 1px; }
            #wpbody-content .wrap li:last-child { border-bottom: solid 1px; }
        </style>

        <div class="wrap">
            <h1>会話風ふきだし</h1>
            <form method="post" action="options.php">
                <?php settings_fields( 'talk_settings' ); ?>
                <ul>
                    <?php for ($i=1; $i<11; $i++):?>
                        <li>
                            <?php
                                $talk_name = 'talk_name'.$i;
                                $talk_img = 'talk_img'.$i;
                                $talk_position = 'talk_position'.$i;
                                $talk_name_data = get_option( $talk_name );
                                $talk_img_data = get_option( $talk_img );
                                $talk_position_data = get_option( $talk_position );
                            ?>
                            <h2>会話<?php the_h($i); ?></h2>
                            <table class="form-table" role="presentation" style="margin-left: 15px;">
                                <tr>
                                    <th>名前:</th>
                                    <td><input type="text" name="<?php the_h($talk_name); ?>" id="<?php the_h($talk_name); ?>" value="<?php the_h($talk_name_data); ?>" ></td>
                                </tr>
                                <tr>
                                    <th>アイコン:</th>
                                    <td><?php generate_up_img_tag($talk_img, $talk_img_data); ?></td>
                                </tr>
                                <tr>
                                    <th>アイコン位置:</th>
                                    <td>
                                        <select name="<?php the_h($talk_position); ?>" id="<?php the_h($talk_position); ?>">
                                            <?php if( $talk_position_data != 'r' ): ?>
                                                <option value="l" selected>左</option>
                                                <option value="r">右</option>
                                            <?php else: ?>
                                                <option value="l">左</option>
                                                <option value="r" selected>右</option>
                                            <?php endif; ?>
                                        </select>
                                    </td>
                                </tr>
                            </table>
                        </li>
                    <?php endfor; ?>
                </ul>
                <?php submit_button(); ?>
            </form>
        </div><!-- /.wrap -->
    <?php
}

// フィールドの作成
add_action( 'admin_init', 'register_talk_settings' );
function register_talk_settings() {
    $my_options = [];
    for($i=1; $i<11; $i++){
        array_push( $my_options, 'talk_name'.$i, 'talk_img'.$i, 'talk_position'.$i);
    }
    foreach($my_options as $my_option){
        register_setting( 'talk_settings', $my_option );
    }
}

//投稿画面・会話風ボタン追加
function my_add_talk_btn() { 
    ?>
        <script type="text/javascript">
            <?php for ($i=1; $i<11; $i++):?>
                <?php
                    $talk_name_data = get_option( 'talk_name'.$i );
                    $talk_img_data = get_option( 'talk_img'.$i );
                    $talk_position_data = get_option( 'talk_position'.$i );
                    if( $talk_position_data != 'r' ){
                        $talk_position_data = 'l';
                    }
                ?>
                <?php if( $talk_name_data && $talk_position_data ): ?>
                    QTags.addButton('talk_f<?php the_h( $i ); ?>', '会話:<?php the_h( $talk_name_data ); ?>', '[talk_f id="<?php the_h( $i ); ?>" position="<?php the_h( $talk_position_data ); ?>"]', '[/talk_f]');
                <?php else: ?>
                    <?php break; ?>
                <?php endif; ?>
            <?php endfor; ?>
        </script>
    <?php
}
add_action('admin_print_footer_scripts','my_add_talk_btn');


//ショートコード作成
function my_add_talk_code( $atts, $content = null ) {
    extract( shortcode_atts( array(
        'id' => '',
        'position' => '',
    ), $atts ) );

    $html = '';

    if( $id ){

        $talk_name_data = get_option( 'talk_name'.$id );
        $talk_img_data = get_option( 'talk_img'.$id );
        $talk_position_data = get_option( 'talk_position'.$id );

        if( $talk_position_data != 'r' ){
            $talk_position_data = 'l';
        }
        if( !$position == 'l' && !$position == 'r' ){
            $position = $talk_position_data;
        }
        if( $talk_name_data && $talk_img_data ){
            ob_start();
            ?>
                <?php if( $position == 'l' ): ?>
                    <div class="talk_f_box">
                        <div class="talk_f_l talk_f_icon">
                            <div class="talk_f_img">
                                <img src="<?php echo esc_url($talk_img_data); ?>" alt="<?php the_h($talk_name_data); ?>" width="80" height="80" loading="lazy">
                            </div><!-- /.talk_f_img -->
                            <p class="talk_f_name"><?php the_h($talk_name_data); ?></p>
                        </div><!-- /.talk_f_l -->
                        <div class="talk_f_r talk_f_txt">
                            <p class="talk_f_txt_cont"><?php the_h($content); ?></p>
                        </div><!-- /.talk_f_r -->
                    </div><!-- /.talk_f_box -->
                <?php else: ?>
                    <div class="talk_f_box talk_f_box_r">
                        <div class="talk_f_l talk_f_txt">
                            <p class="talk_f_txt_cont"><?php the_h($content); ?></p>
                        </div><!-- /.talk_f_l -->
                        <div class="talk_f_r talk_f_icon">
                            <div class="talk_f_img">
                                <img src="<?php echo esc_url($talk_img_data); ?>" alt="<?php the_h($talk_name_data); ?>" width="80" height="80" loading="lazy">
                            </div><!-- /.talk_f_img -->
                            <p class="talk_f_name"><?php the_h($talk_name_data); ?></p>
                        </div><!-- /.talk_f_r -->
                    </div><!-- /.talk_f_box -->
                <?php endif; ?>
            <?php
            return $html = ob_get_clean();
        }else{
            return $html;
        }

    }else{
        return $html;
    }
}
add_shortcode('talk_f', 'my_add_talk_code');



//?>

CSS(デザイン)

共通のCSSや記事ページのCSSに記述して下さい。

/* 会話風ふきだし */
.talk_f_box { display: -webkit-flex; display: -moz-flex; display: -ms-flex; display: -o-flex; display: flex; align-items: center; margin-bottom: -24px; }
.talk_f_box_r { justify-content: flex-end; }
.talk_f_icon { width: 80px; }
.talk_f_img { width: 80px !important; height: 80px !important; margin-bottom: 2px; border-radius: 50%; overflow: hidden; border: solid 1px #858585; }
.talk_f_img img { vertical-align: bottom; }
.talk_f_name { text-align: center; font-size: 14px; }
.talk_f_txt { position: relative; }
.talk_f_txt_cont { margin: 0; padding: 12px; border: solid 1px #858585; border-radius: 10px; }
.talk_f_l.talk_f_icon { margin-right: 20px; }
.talk_f_r.talk_f_txt:before { content: ""; position: absolute; top: 50%; left: -23px; margin-top: -12px; border: 12px solid transparent; border-right: 12px solid #FFF; z-index: 2; }
.talk_f_r.talk_f_txt:after { content: ""; position: absolute; top: 51%; left: -25px; margin-top: -14px; border: 13px solid transparent; border-right: 13px solid #858585; z-index: 1; }
.talk_f_l.talk_f_txt { margin-right: 20px; }
.talk_f_l.talk_f_txt:before { content: ""; position: absolute; top: 50%; right: -23px; margin-top: -12px; border: 12px solid transparent; border-left: 12px solid #FFF; z-index: 2; }
.talk_f_l.talk_f_txt:after { content: ""; position: absolute; top: 51%; right: -25px; margin-top: -14px; border: 13px solid transparent; border-left: 13px solid #858585; z-index: 1; }

簡単な解説

管理画面に「会話風ふきだし」の設定画面を追加し、ショートコードで会話を表示します。

使い方

・管理画面でふきだしを設定
名前、アイコン画像、表示位置を設定します。
アイコンは80*80で表示されるので、80*80ピクセルか、160*160ピクセルがおすすめです。

 

 
・投稿画面のボタンを押してショートコードを追加
ショートコードのpositionのl,rを書き換えることで表示位置を調整できます。

 

 

ルナリス

ルナリス

私もショートコードで表示されているわ


私はHTML直書きで表示されてるよ!

ソルト

ソルト


ルナリス

ルナリス

えっ…

まとめ

管理画面に吹き出しの設定画面を追加し、ショートコードから吹き出しを表示する機能を実装しました。
ショートコードのボタンも自動で追加されるようにしたのでシンプルで使いやすいものができたと思います。
 

 
シンプルな会話風吹き出しを使用したい方はぜひ参考にして下さい。

コメント一覧

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です