WordPress スライダーでアイキャッチ画像を表示するブロックを作成
WordPress のブロックエディタ Gutenberg で特定のカテゴリーのアイキャッチ画像をスライダーで表示するブロックを作成する方法の覚書です。スライダーの表示はダイナミックブロックを作成して PHP でレンダリングします。
以下は(旧)ブロックの作成 チュートリアル(削除予定)などの古い情報を参考にしているため部分的に古い情報になっています。
最新のブロック開発入門(2024/12):WordPress 初めてのブロック開発
スライダーは Swiper という JavaScript のプラグインを使用しています。
更新日:2024年12月13日
作成日:2020年10月14日
ブロックの基本的な作成方法や環境の構築方法については以下を御覧ください。
- 関連ページ
また、Node.js がインストールされていて、WordPress のローカル環境があることを前提にしています。
概要
以下は特定のカテゴリーの投稿に設定されているアイキャッチ画像をスライダーで表示するブロックの例です。ブロックはダイナミックブロックで作成します。
スライダーに表示する画像の数やナビゲーション、ページネーション、キャプションなどの表示・非表示はインスペクターで設定が可能です。
withSelect と getEntityRecords を使って全てのカテゴリーを取得してそのリストを表示し、ユーザーが選択したカテゴリーの投稿のアイキャッチ画像を表示します。
以下のサイトを参考にさせていただきました。
環境構築とファイルの作成
ブロックの作成に必要なファイルとスライダープラグイン Swiper のファイルを用意します。
ブロックの作成では JSX を使用するので JSX をコンパイルする環境が必要ですが、create-block を使用すると簡単に環境の構築と初期ファイルが作成できます。
関連ページ:Gutenberg ブロック開発の環境構築
create-block の実行
この例ではプラグインとしてブロックを作成するので、ターミナルでプラグインディレクトリ wp-content/plugins に移動します。パスは環境に合わせて指定します。
$ cd /path/to/wp-content/plugins return //プラグインディレクトリへ移動
続いて、create-block のコマンドを実行して環境の構築と初期ファイルを生成します。
以下は、--namespace オプションで namespace を wdl に指定し、slug に my-dynamic-slider を指定して create-block のコマンドを実行しています。
この例では対話モードで slug に my-dynamic-slider を指定して create-block を実行したので、以下のようなファイルが出力されます。
my-dynamic-slider //作成されたプラグインのディレクトリ
├── block.json //ブロックディレクトリの登録で使用されるファイル(?)
├── build //ビルドで出力されるファイルのディレクトリ
│ ├── index.asset.php //依存情報とファイルバージョンが記載されるファイル(自動生成)
│ ├── index.css //editor.scss がビルドで変換された CSS
│ ├── index.js //ビルドされたブロック用のスクリプト
│ └── style-index.css // style.scss がビルドで変換された CSS
├── node_modules //関連パッケージのディレクトリ
├── my-dynamic-slider.php //メインのプラグインファイル
├── package-lock.json
├── package.json //パッケージの設定ファイル
├── readme.txt
└── src //開発用ディレクトリ(この中のファイルを編集)
├── edit.js
├── editor.scss
├── index.js //ブロック用のスクリプト
├── save.js
└── style.scss
ターミナルで作成されたプラグインのディレクトリに移動して npm start を実行して開発モードにして作業をしていきます。
開発モードを終了するには control + c を押します。
$ cd my-dynamic-slider return //プラグインのディレクトリに移動 $ npm start return //開発モード
procuction ビルドするには npm run build を実行します。
初期ファイルの作成
この例では create-block を実行して生成されたファイルを利用します。
src フォルダ内に生成されたブロックの作成に使用するファイルにはコメントや翻訳関連の関数などが記述されていますが、コメントは削除し、この例では翻訳関数は使わないのでその部分なども変更しています。
以下が変更後のファイルです。
src/edit.js
edit.js はこの時点では p 要素をレンダリングするだけです。
import './editor.scss';
export default function Edit( { className } ) {
return (
<p className={ className }>My Dynamic Slider – hello from the editor!</p>
);
}
save 関数で null を return
ダイナミックブロックを作成するので src/index.js では save 関数が null を返すように変更して、save.js は削除します。
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
registerBlockType( 'wdl/my-dynamic-slider', {
title: 'My Dynamic Slider',
description:'Example block written with ESNext standard and JSX support',
category: 'widgets',
icon: 'smiley',
supports: {
html: false,
},
edit: Edit,
// save 関数の定義を直接記述して null を返す
save: () => { return null }
} );
render_callback の追加
ブロックを PHP でレンダリングするには、PHP 側でブロックを登録する register_block_type 関数の第2パラメータの配列に render_callback を追加して、ブロックをレンダリングする関数を定義します。
register_block_type( 'wdl/my-dynamic-slider', array( 'editor_script' => 'wdl-my-dynamic-slider-block-editor', 'editor_style' => 'wdl-my-dynamic-slider-block-editor', 'style' => 'wdl-my-dynamic-slider-block', //render_callback を追加 'render_callback' => 'my_dynamic_slider_render', ) );
この時点では以下のような単に p 要素を返すだけの render_callback 関数を定義しておきます。
function my_dynamic_slider_render($attributes, $content) {
return '<p>スライダーのレンダリングをここに記述</p>';
}
<?php
/**
* Plugin Name: My Dynamic Slider
* Description: Example block written with ESNext standard and JSX support – build step required.
* Version: 0.1.0
* Author: The WordPress Contributors
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-dynamic-slider
*
* @package wdl
*/
/**
* Registers all block assets so that they can be enqueued through the block editor
* in the corresponding context.
*
* @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/applying-styles-with-stylesheets/
*/
function wdl_my_dynamic_slider_block_init() {
$dir = dirname( __FILE__ );
$script_asset_path = "$dir/build/index.asset.php";
if ( ! file_exists( $script_asset_path ) ) {
throw new Error(
'You need to run `npm start` or `npm run build` for the "wdl/my-dynamic-slider" block first.'
);
}
$index_js = 'build/index.js';
$script_asset = require( $script_asset_path );
wp_register_script(
'wdl-my-dynamic-slider-block-editor',
plugins_url( $index_js, __FILE__ ),
$script_asset['dependencies'],
$script_asset['version']
);
wp_set_script_translations( 'wdl-my-dynamic-slider-block-editor', 'my-dynamic-slider' );
$editor_css = 'build/index.css';
wp_register_style(
'wdl-my-dynamic-slider-block-editor',
plugins_url( $editor_css, __FILE__ ),
array(),
filemtime( "$dir/$editor_css" )
);
$style_css = 'build/style-index.css';
wp_register_style(
'wdl-my-dynamic-slider-block',
plugins_url( $style_css, __FILE__ ),
array(),
filemtime( "$dir/$style_css" )
);
register_block_type( 'wdl/my-dynamic-slider', array(
'editor_script' => 'wdl-my-dynamic-slider-block-editor',
'editor_style' => 'wdl-my-dynamic-slider-block-editor',
'style' => 'wdl-my-dynamic-slider-block',
//render_callback を追加
'render_callback' => 'my_dynamic_slider_render',
) );
}
add_action( 'init', 'wdl_my_dynamic_slider_block_init' );
function my_dynamic_slider_render($attributes, $content) {
return '<p>スライダーのレンダリングをここに記述</p>';
}
この時点で、プラグインページで作成したプラグインを有効化し、投稿に挿入すると以下のように表示されます。
以下はフロントエンド側の表示例です。
属性の追加
ユーザが選択した値を保持するためにこの例では以下のような属性(attributes)を設定します。
- termId :表示するアイキャッチ画像のカテゴリーの ID
- numSlides:スライダーに表示する画像の枚数
- showNavigationButton:ナビゲーションボタンの表示・非表示
- showPagination:ページネーションの表示・非表示
- showScrollbar:スクロールバーの表示・非表示
- showCaption:キャプションの表示・非表示
この例の場合、ダイナミックブロックなので PHP 側の register_block_type で属性を設定します。
register_block_type に attributes を設定する場合は連想配列で設定します。
register_block_type( 'wdl/my-dynamic-slider', array(
'editor_script' => 'wdl-my-dynamic-slider-block-editor',
'editor_style' => 'wdl-my-dynamic-slider-block-editor',
'style' => 'wdl-my-dynamic-slider-block',
//render_callback を追加
'render_callback' => 'my_dynamic_slider_render',
//属性を追加
'attributes' => [
//アイキャッチ画像のカテゴリーのID
'termId' => [
'type' => 'number',
'default' => 0
],
//スライダーに表示する画像の数
'numSlides' => [
'type' => 'number',
'default' => 3
],
//ナビゲーションボタンの表示・非表示
'showNavigationButton' => [
'type' => 'boolean',
'default' => true
],
//ページネーションの表示・非表示
'showPagination' => [
'type' => 'boolean',
'default' => true
],
//スクロールバーンの表示・非表示
'showScrollbar' => [
'type' => 'boolean',
'default' => true
],
//キャプションの表示・非表示
'showCaption' => [
'type' => 'boolean',
'default' => true
],
]
));
インスペクターの追加
インスペクター(設定サイドバー)に、表示する画像の数を指定できるスライドバー(RangeControl)及びナビゲーションボタンなどの表示・非表示を選択するトグルボタン(ToggleControl)を設置します
InspectorControls コンポーネントの中に PanelBody、PanelRow コンポーネントを配置し、その中に RangeControl や ToggleControl を配置します。
インスペクターの設定の詳細は「インスペクター」を御覧ください。
それぞれのコンポーネントをパッケージからインポートします。
| パッケージ | コンポーネント |
|---|---|
| block-editor | InspectorControls |
| components | Placeholder, PanelBody, PanelRow, RangeControl, ToggleControl |
import { InspectorControls } from '@wordpress/block-editor';
import { Placeholder, PanelBody, PanelRow, RangeControl, ToggleControl } from '@wordpress/components';
インスペクターは return ステートメントに直接記述することもできますが、この例ではインスペクターを追加する以下のような関数を作成します。
//インスペクターを表示する関数
const getInspectorControls = () => {
return (
<InspectorControls>
<PanelBody
title='Slider Settings'
initialOpen={true}
>
<PanelRow>
<RangeControl
label='Number of slides'
value={attributes.numSlides}
onChange={(val) => setAttributes({ numSlides: val })}
min={1}
max={10}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ナビゲーションボタン"
checked={attributes.showNavigationButton}
onChange={(val) => setAttributes({ showNavigationButton: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ページネーション"
checked={attributes.showPagination}
onChange={(val) => setAttributes({ showPagination: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="スクロールバー"
checked={attributes.showScrollbar}
onChange={(val) => setAttributes({ showScrollbar: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="キャプション"
checked={attributes.showCaption}
onChange={(val) => setAttributes({ showCaption: val })}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
);
}
RangeControl コンポーネントには以下のようなプロパティを指定することができます。
onChange プロパティでは値が変更された際に setAttributes で属性 numSlides の値を更新し、その値が val プロパティの値になります。
| プロパティ | 説明 |
|---|---|
| label | 指定すると label 要素でラベルを出力します。 |
| help | 指定するとヘルプテキストを出力します。 |
| beforeIcon | DashIcon を指定するとスライダーの前にアイコンを表示できます。 |
| afterIcon | DashIcon を指定するとスライダーの後ろにアイコンを表示できます。 |
| allowReset | このプロパティに true を指定するとデフォルトにリセットするボタンを表示します。 |
| onChange | 値が変更された際に新しい値を受け取るコールバック関数を指定します。 |
| min | 指定できる値の最小値 |
| max | 指定できる値の最大値 |
| step | 最小値(min)と最大値(max)の間のステップ間隔 |
| value | 現在のレンジスライダーの値 |
以下は ToggleControl のプロパティです。トグルボタンの値(checked)は真偽値になります。
| プロパティ | 説明 |
|---|---|
| label | 指定すると label 要素でラベルを出力します。 |
| help | 指定するとヘルプテキストを出力します。 |
| checked | トグルボタンの状態を表す真偽値。トグルボタンがオンの場合、checked の値は true になり、false の場合はトグルボタンはオフ(チェックされていない状態)です。 |
| onChange | checked の値(真偽値)を引数に取る関数 |
Placeholder の追加
この例では編集画面では実際のスライダーは表示せず、スライダーを表示する部分の領域に Placeholder コンポーネントを配置し、その中に後で MenuItem コンポーネントを使ったアイキャッチ画像のカテゴリーを選択するためのリストを表示します。
Placeholder コンポーネントには以下のようなプロパティを指定することができます。
| プロパティ | 説明 |
|---|---|
| label | プレースホルダーのラベルを div 要素で出力します。 |
| icon | DashIcon を指定するとラベルの前にアイコンを出力します。 |
| instructions | 指定するとインストラクション用のテキストをラベルの下に表示します。 |
| isColumnLayout | true を指定すると Placeholder コンポーネントの子要素のレイアウトを flex-row から flex-column に変更します。 |
この時点では instructions と icon プロパティとダミーの文字列「スライダーのプレースホルダー」を表示しておきます。
return ステートメント内に前述のインスペクターの関数と共にプレースホルダーのレンダリングを記述します。その際にはレンダリングを配列で記述します。
return (
[
getInspectorControls(), //インスペクター
<div className={className}>
<Placeholder
label='スライダーカテゴリー'
icon='format-image'
instructions='スライダーに表示するアイキャッチ画像のカテゴリーを選択'
>
スライダーのプレースホルダー
</Placeholder>
</div>
]
);
import './editor.scss';
import { InspectorControls } from '@wordpress/block-editor';
import { Placeholder, PanelBody, PanelRow, RangeControl, ToggleControl } from '@wordpress/components';
export default function Edit( props ) {
//props 経由でプロパティを取得して分割代入で変数を設定
const {className, attributes, setAttributes} = props;
//インスペクターを表示する関数
const getInspectorControls = () => {
return (
<InspectorControls>
<PanelBody
title='Slider Settings'
initialOpen={true}
>
<PanelRow>
<RangeControl
label='Number of slides'
value={attributes.numSlides}
onChange={(val) => setAttributes({ numSlides: val })}
min={1}
max={10}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ナビゲーションボタン"
checked={attributes.showNavigationButton}
onChange={(val) => setAttributes({ showNavigationButton: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ページネーション"
checked={attributes.showPagination}
onChange={(val) => setAttributes({ showPagination: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="スクロールバー"
checked={attributes.showScrollbar}
onChange={(val) => setAttributes({ showScrollbar: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="キャプション"
checked={attributes.showCaption}
onChange={(val) => setAttributes({ showCaption: val })}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
);
}
return (
[
getInspectorControls(), //インスペクター
<div className={className}>
<Placeholder
label='スライダーカテゴリー'
icon='format-image'
instructions='スライダーに表示するアイキャッチ画像のカテゴリーを選択'
>
スライダーのプレースホルダー
</Placeholder>
</div>
]
);
}
上記を記述して保存するとエディター画面は以下のような表示になります。
カテゴリーを選択するコンポーネントの作成
このスライダーでは指定された投稿のカテゴリーのアイキャッチ画像を表示するので、投稿のカテゴリーを WordPress から取得する必要があります。
投稿の情報(この場合はカテゴリー)を取得するには withSelect を使います。
withSelect
withSelect を使うには、data モジュールから withSelect と select をインポートします。
import { withSelect, select } from '@wordpress/data';
withSelect の中で select() と getEntityRecords() を使って投稿の情報(オブジェクト)を取得することができます。例えば、3件の投稿を取得するには以下のように記述します。
select('core').getEntityRecords('postType', 'post', { per_page: 3 })
セレクター select('core') で Core Data にアクセスしてセレクターの関数 getEntityRecords() でパラメータで指定したオブジェクトを取得します。全てのカテゴリーを取得するには以下のように記述します。
select('core').getEntityRecords('taxonomy', 'category', {per_page: -1})
この例ではカテゴリーを選択する CategorySelect コンポーネントを別ファイル(category-select.js)に記述します。
以下では withSelect と定義した CategorySelect コンポーネントの組み合わせをデフォルトエクスポートしています(withSelect の戻り値は CategorySelect が拡張されたコンポーネント)。
withSelect 内では、select() で取得したカテゴリーを値に指定したオブジェクト terms を return しています。terms は withSelect に渡されるコンポーネント(CategorySelect)への props になります。
つまり、CategorySelect コンポーネントでは props 経由で terms を取得できます。言い換えると CategorySelect コンポーネントの props に terms がマージされます。
この時点では、CategorySelect コンポーネントは props 経由で取得した terms(カテゴリーオブジェクトの配列)をコンソールに出力し、「Category Select」と表示する div 要素をレンダリングします。
import { withSelect } from '@wordpress/data';
const CategorySelect = (props) => {
console.log(props.terms); //カテゴリーをコンソールに出力
return(
<div>Category Select</div>
);
}
export default withSelect((select, props) => {
return {
terms: select('core').getEntityRecords('taxonomy', 'category', {per_page: -1})
}
})(CategorySelect);
作成した CategorySelect コンポーネントを src/edit.js でインポートして使用します。
import CategorySelect from './category-select';
return ステートメント内の Placeholder 内に CategorySelect を配置(ネスト)します。
return (
[
getInspectorControls(),
<div className={className}>
<Placeholder
label='スライダーカテゴリー'
icon='format-image'
instructions='スライダーに表示するアイキャッチ画像のカテゴリーを選択'
>
<CategorySelect
/>
</Placeholder>
</div>
]
);
ブロックを挿入した投稿のエディター画面のコンソールにはカテゴリーオブジェクトの配列が出力されます。コンソールには最初に空の配列や null が出力されますが、これは getEntityRecords() が非同期で行われるためで、値がまだ受信されていない(投稿が読み込まれていない)場合は null を返します。
カテゴリーリストのレンダリング
MenuGroup と MenuItem コンポーネントを使って選択するカテゴリーのリストをレンダリングします。
メニュー(リスト)に表示する項目(MenuItem)を MenuGroup でラップします。
<MenuGroup label="Settings"> <MenuItem>Setting 1</MenuItem> <MenuItem>Setting 2</MenuItem> </MenuGroup>
CategorySelect コンポーネントで、取得したカテゴリーを MenuGroup と MenuItem でレンダリングします。
MenuGroup と MenuItem を components パッケージからインポートします。
import { MenuGroup, MenuItem } from '@wordpress/components';
props 経由で取得した terms はカテゴリーオブジェクトの配列なので map() を使ってループして各オブジェクトの名前(name プロパティ)を取得して MenuItem に出力します。
MenuItem の role プロパティには menuitemradio を指定して、1つの項目を選択できるようにしています。
const CategorySelect = (props) => {
// props 経由で terms(カテゴリーオブジェクトの配列)を取得
const { terms } = props;
//terms を map() でループして name プロパティを MenuItem に出力
return(
<MenuGroup
className="my-category-select"
>
{terms && (
terms.map((item) => (
<MenuItem
role="menuitemradio"
>
{item.name}
</MenuItem>
))
)}
</MenuGroup>
);
}
MenuItem には以下のようなプロパティがあります。
| プロパティ | 説明 |
|---|---|
| children | button 要素の子要素としてレンダリングする要素を指定 |
| info | ボタン(button)のテキストの説明として使用するテキスト |
| icon | 項目の前に表示するアイコン(DashIcon)。例 icon='smiley' |
| isSelected | 現在この項目が選択されているかどうかの真偽値 |
| role | ARIA の role 属性。選択可能なメニュー項目が必要な場合は、単一選択には menuitemradio を使用し、複数選択には menuitemcheckbox を使用します。 |
import { withSelect } from '@wordpress/data';
import { MenuGroup, MenuItem } from '@wordpress/components';
const CategorySelect = (props) => {
// props 経由で terms(カテゴリーオブジェクト)を取得
const { terms } = props;
//terms(カテゴリーオブジェクトの配列)を map() でループして name プロパティを MenuItem に出力
return(
<MenuGroup
className="my-category-select"
>
{terms && (
terms.map((item) => (
<MenuItem
role="menuitemradio"
>
{item.name}
</MenuItem>
))
)}
</MenuGroup>
);
}
export default withSelect((select, props) => {
return {
terms: select('core').getEntityRecords('taxonomy', 'category', {per_page: -1})
}
})(CategorySelect);
カテゴリーリストのスタイルの設定
カテゴリーが多い場合、カテゴリーリストは長くなってしまうので、max-height を設定してそれ以上の高さになる場合はスクロールバーを表示するようにします。
MenuGroup に指定したクラス my-category-select を使ってスタイルを指定します。以下を editor.scss に記述します。
.my-category-select {
max-height: 200px;
overflow: hidden scroll;
border: 1px solid #C0BCBC;
background: #fcfcfc;
}
props の追加
props はコンポーネントに渡される任意のデータで、props を使ってデータをコンポーネントに渡すことができます。(関連項目:React props )
現在選択されているカテゴリーのID(属性 termId の値)を selectedTermId、選択が変更された場合にその値(カテゴリーID)を更新する関数を selectTerm として CategorySelect コンポーネントの props に追加します。
コンポーネント内では、selectedTermId と各 id を比較して MenuItem の isSelected プロパティ及び icon プロパティの値を設定しています。そして onClick プロパティのハンドラ(クリックされたら呼び出される関数)に selectTerm を指定しています。
const CategorySelect = (props) => {
// selectedTermId と selectTerm を追加
const { terms, selectedTermId, selectTerm } = props;
return(
<MenuGroup
className="my-category-select"
>
{terms && (
terms.map((item) => (
<MenuItem
role="menuitemradio"
//selectedTermId と id を比較して真偽値を設定
isSelected={item.id == selectedTermId}
//selectedTermId と id の比較結果により表示するアイコンを設定
icon={item.id == selectedTermId ? 'yes' : 'marker'}
//ハンドラで選択されたIDを属性に設定して更新
onClick={() => selectTerm(item.id)}
>
{item.name}
</MenuItem>
))
)}
</MenuGroup>
);
}
import { withSelect } from '@wordpress/data';
import { MenuGroup, MenuItem } from '@wordpress/components';
const CategorySelect = (props) => {
// props 経由で terms(カテゴリーオブジェクト)を取得
// selectedTermId は選択されているカテゴリーID の値のプロパティ
// selectTerm は選択されているカテゴリーIDを更新する関数のプロパティ
const { terms, selectedTermId, selectTerm } = props;
//terms(カテゴリーオブジェクトの配列)をループして各 name プロパティを MenuItem に出力
return(
<MenuGroup
className="my-category-select"
>
{terms && (
terms.map((item) => (
<MenuItem
role="menuitemradio"
//selectedTermId と id を比較して真偽値を設定
isSelected={item.id == selectedTermId}
//selectedTermId と id の比較結果により表示するアイコンを設定
icon={item.id == selectedTermId ? 'yes' : 'marker'}
//ハンドラで選択されたIDを属性に設定して更新
onClick={() => selectTerm(item.id)}
>
{item.name}
</MenuItem>
))
)}
</MenuGroup>
);
}
export default withSelect((select, props) => {
return {
terms: select('core').getEntityRecords('taxonomy', 'category', {per_page: -1})
}
})(CategorySelect);
edit 関数では CategorySelect コンポーネントの selectTerm プロパティに指定する関数を定義し(5〜7行目)、selectTerm プロパティに定義した同じ名前の関数 selectTerm を指定します(30行目)。
また、selectedTermId プロパティに選択されたカテゴリー ID(属性 termId の値)を設定します。
export default function Edit( props ) {
const { className, attributes, setAttributes } = props;
// 属性 termId を更新する関数 selectTerm を実装
const selectTerm = ( termId ) => {
setAttributes({ termId: termId });
}
const getInspectorControls = () => {
return (
<InspectorControls>
・・・中略・・・
</InspectorControls>
);
}
return (
[
getInspectorControls(), //インスペクター
<div className={ className }>
<Placeholder
label='スライダーカテゴリー'
icon='format-image'
instructions='スライダーに表示するアイキャッチ画像のカテゴリーを選択'
>
<CategorySelect
// プロパティ selectedTermId に属性 termId を指定
selectedTermId={ attributes.termId }
// プロパティ selectedTerm に5行目で実装した関数 selectTerm を指定
selectTerm={ selectTerm }
/>
</Placeholder>
</div>
]
);
}
import './editor.scss';
import { InspectorControls } from '@wordpress/block-editor';
import { Placeholder, PanelBody, PanelRow, RangeControl, ToggleControl } from '@wordpress/components';
import CategorySelect from './category-select';
export default function Edit( props ) {
//props 経由でプロパティを取得して分割代入で変数を設定
const {className, attributes, setAttributes} = props;
// 属性 termId を更新する関数
const selectTerm = (termId) => {
setAttributes({ termId: termId });
}
//インスペクターを表示する関数
const getInspectorControls = () => {
return (
<InspectorControls>
<PanelBody
title='Slider Settings'
initialOpen={true}
>
<PanelRow>
<RangeControl
label='Number of slides'
value={attributes.numSlides}
onChange={(val) => setAttributes({ numSlides: val })}
min={1}
max={10}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ナビゲーションボタン"
checked={attributes.showNavigationButton}
onChange={(val) => setAttributes({ showNavigationButton: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ページネーション"
checked={attributes.showPagination}
onChange={(val) => setAttributes({ showPagination: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="スクロールバー"
checked={attributes.showScrollbar}
onChange={(val) => setAttributes({ showScrollbar: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="キャプション"
checked={attributes.showCaption}
onChange={(val) => setAttributes({ showCaption: val })}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
);
}
return (
[
getInspectorControls(), //インスペクター
<div className={className}>
<Placeholder
label='スライダーカテゴリー'
icon='format-image'
instructions='スライダーに表示するアイキャッチ画像のカテゴリーを選択'
>
<CategorySelect
selectedTermId={attributes.termId}
selectTerm={selectTerm}
/>
</Placeholder>
</div>
]
);
}
この時点でブロックの挿入された投稿を再読込して確認すると、エディター画面では以下のようにカテゴリーのリストが表示され、選択されたカテゴリーにはチェックマークが表示されます。
Swiper のファイルの追加
この例では、スライダーの表示には Swiper という JavaScript のプラグインを使用します。
Swiper の使い方の詳細は以下を御覧ください。
この例では Swiper のダウンロードページの swiper-bundle.min.js と swiper-bundle.min.css をコピーして使用しています。この時点の最新版は 6.3.2 ですが、右上のセレクトメニューでバージョンを指定することもできます。
| ファイル | ソースコード | タイプ | この例でのファイル名 |
|---|---|---|---|
| swiper-bundle.min.js | RAW | JavaScript | swiper.js |
| swiper-bundle.min.css | RAW | CSS | swiper.css |
ブロックのプラグインのフォルダ(dynamic-slider)の中に assets というフォルダを作成し、その中にコピーしたファイルとスライダーを初期化するための JavaScript ファイル(init-swiper.js)を保存します。
ファイル名は上記表に記載されている「この例でのファイル名」に変更しています。
以下は Swiper を初期化するためのファイル init-swiper.js の例です。
let mySwiper = new Swiper ('.swiper-container', {
//スライダーを自動再生
autoplay: {
delay: 4000, //4秒間隔でスライドを自動的に実行
},
//最後に達したら先頭に戻る
loop: true,
//ページネーション表示の設定
pagination: {
el: '.swiper-pagination', //ページネーションの要素
type: 'bullets', //ページネーションの種類
clickable: true, //クリックに反応させる
},
//ナビゲーションボタン(矢印)表示の設定
navigation: {
nextEl: '.swiper-button-next', //「次へボタン」要素の指定
prevEl: '.swiper-button-prev', //「前へボタン」要素の指定
},
//スクロールバー表示の設定
scrollbar: {
el: '.swiper-scrollbar', //要素の指定
},
})
以下はコピーしたファイルの冒頭部分です。
/**
* Swiper 6.3.2
* Most modern mobile touch slider and framework with hardware accelerated transitions
* http://swiperjs.com
*
* Copyright 2014-2020 Vladimir Kharlampidi
*
* Released under the MIT License
*
* Released on: September 28, 2020
*/
!function(e,t){"object"==typeof ・・・以下省略・・・
@charset "UTF-8"; /* 追加 */
/**
* Swiper 6.3.2
* Most modern mobile touch slider and framework with hardware accelerated transitions
* http://swiperjs.com
*
* Copyright 2014-2020 Vladimir Kharlampidi
*
* Released under the MIT License
*
* Released on: September 28, 2020
*/
@font-face{font-family:swiper-icons; ・・・以下省略・・・
スライダーのスクリプトの読み込み
assets フォルダに保存したスライダーのスクリプトとスタイルをプラグインのファイル my-dynamic-slider.php で wp_enqueue_script と wp_enqueue_style を使って、enqueue_block_assets アクションで読み込みます。
この例の場合、エディター側ではスライダーは表示しないのでフロントエンド側でのみ読み込むようにします。そのため以下では ! is_admin() で判定してスクリプトとスタイルをエンキューしています。
function add_my_dynamic_slider_scripts_and_styles() {
$dir = dirname( __FILE__ );
//管理画面以外(フロントエンド側でのみ読み込む)
if(! is_admin()) {
//Swiper の JavaScript ファイルの読み込み(エンキュー)
wp_enqueue_script(
'swiper-slider',
plugins_url( '/assets/swiper.js', __FILE__ ),
array(),
filemtime( "$dir/assets/swiper.js" ),
true
);
//Swiper を初期化するためのファイルの読み込み(エンキュー)
wp_enqueue_script(
'swiper-slider-init',
plugins_url( '/assets/init-swiper.js', __FILE__ ),
//依存ファイルに上記 Swiper の JavaScript を指定
array('swiper-slider'),
filemtime( "$dir/assets/init-swiper.js" ),
true
);
//Swiper の CSS ファイルの読み込み(エンキュー)
wp_enqueue_style(
'swipe-style',
plugins_url( '/assets/swiper.css', __FILE__ ),
array(),
filemtime( "$dir/assets/swiper.css" )
);
}
}
add_action('enqueue_block_assets', 'add_my_dynamic_slider_scripts_and_styles');
Swiper のマークアップ
以下は Swiper を使ってスライダーを表示するための基本的なマークアップの例です。
<!-- スライダーのメインのコンテナー -->
<div class="swiper-container">
<!-- スライダーのラッパー -->
<div class="swiper-wrapper">
<!-- スライド .swiper-slide の中に画像を配置 -->
<div class="swiper-slide"><img src="images/sample_01.jpg" alt=""></div>
<div class="swiper-slide"><img src="images/sample_02.jpg" alt=""></div>
<div class="swiper-slide"><img src="images/sample_03.jpg" alt=""></div>
</div>
<!-- ページネーションの表示 -->
<div class="swiper-pagination"></div>
<!-- ナビゲーションボタンの表示 -->
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
<!-- スクロールバーの表示 -->
<div class="swiper-scrollbar"></div>
</div>
PHP でレンダリング
register_block_type 関数の第2パラメータに追加した render_callback に指定した関数を使ってスライダーをレンダリングします。
render_callback の関数はブロックの出力を return する必要があるので、文字列(HTML)を作成して最後に return します。この例の場合、投稿からアイキャッチ画像を取得して Swiper の構造のマークアップを作成して return します。
以下では、属性 termId の値によりカテゴリーが選択されているかを判定し、何も選択されていなければ空文字列を返し何も表示しません。
カテゴリーが選択されている場合は、属性 termId と numSlides の値をクエリパラメータに指定した WP_Query を使ったサブループで投稿を取得し、投稿のアイキャッチ画像が存在すればスライダーの画像のマークアップを作成します。
アイキャッチ画像は get_post_thumbnail_id() でアイキャッチ画像の ID を取得し、それを元にアイキャッチ画像のオブジェクトを取得して URL とキャプションを取得しています。alt 属性の値は get_post_meta() を使って取得しています。
キャプションやページネーション、ナビゲーションボタン、スクロールバーの表示は属性の値を元に出力しています。
function my_dynamic_slider_render($attributes, $content) {
//カテゴリーが選択されていない場合は空文字列を返す(何も表示しない)
if ($attributes['termId'] === 0) {
return '';
}
// WP_Query を使ったサブループ
$my_Query = new WP_Query([
//属性の値を使って取得する投稿の条件を指定
'posts_per_page' => $attributes['numSlides'],
'cat' => $attributes['termId']
]);
if ($my_Query->have_posts()) {
//該当する投稿があればスライダーのマークアップを組み立てる
$output = '<div class="swiper-container wp-block-wdl-my-dynamic-slider">';
$output .= '<div class="swiper-wrapper">';
while ($my_Query->have_posts()) {
$my_Query->the_post();
//アイキャッチ画像があれば
if (has_post_thumbnail()) {
//アイキャッチ画像の ID を取得
$post_thumbnail_id = get_post_thumbnail_id();
//アイキャッチ画像のオブジェクトを取得
$my_thumbnail = get_post($post_thumbnail_id);
$img_url = esc_url($my_thumbnail -> guid);
$img_caption = esc_html($my_thumbnail -> post_excerpt);
//get_post_meta() でカスタムフィールドの内部的な値である alt 属性を取得
$my_thumbnail_meta = get_post_meta($post_thumbnail_id);
$img_alt = $my_thumbnail_meta["_wp_attachment_image_alt"][0];
$output .= '<div class="swiper-slide"><img src="' . $img_url . '" alt="' . $img_alt .'" />';
//キャプションを表示する場合
if($attributes['showCaption']) {
if($img_caption) {
$output .= '<div class="caption">'. $img_caption . '</div>';
}
}
$output .= '</div>';
}
}
wp_reset_postdata(); //グローバル変数 $post を復元
$output .= '</div>';
//ページネーションを表示する場合
if($attributes['showPagination']) {
$output .= '<div class="swiper-pagination"></div>';
}
//ナビゲーションボタンを表示する場合
if($attributes['showNavigationButton']) {
$output .= '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>';
}
//スクロールバーを表示する場合
if($attributes['showScrollbar']) {
$output .= '<div class="swiper-scrollbar"></div>';
}
$output .= '</div>';
return $output;
} else {
return '';
}
}
ブロックの外側の要素はスライダーの外側のクラス swiper-container と WordPress が自動的にブロックに付与するクラス wp-block-wdl-my-dynamic-slider を指定した div 要素でマークアップしています。
<?php
/**
* Plugin Name: My Dynamic Slider
* Description: Example block written with ESNext standard and JSX support – build step required.
* Version: 0.1.0
* Author: The WordPress Contributors
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-dynamic-slider
*
* @package wdl
*/
/**
* Registers all block assets so that they can be enqueued through the block editor
* in the corresponding context.
*
* @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/applying-styles-with-stylesheets/
*/
function wdl_my_dynamic_slider_block_init() {
$dir = dirname( __FILE__ );
$script_asset_path = "$dir/build/index.asset.php";
if ( ! file_exists( $script_asset_path ) ) {
throw new Error(
'You need to run `npm start` or `npm run build` for the "wdl/my-dynamic-slider" block first.'
);
}
$index_js = 'build/index.js';
$script_asset = require( $script_asset_path );
wp_register_script(
'wdl-my-dynamic-slider-block-editor',
plugins_url( $index_js, __FILE__ ),
$script_asset['dependencies'],
$script_asset['version']
);
wp_set_script_translations( 'wdl-my-dynamic-slider-block-editor', 'my-dynamic-slider' );
$editor_css = 'build/index.css';
wp_register_style(
'wdl-my-dynamic-slider-block-editor',
plugins_url( $editor_css, __FILE__ ),
array(),
filemtime( "$dir/$editor_css" )
);
$style_css = 'build/style-index.css';
wp_register_style(
'wdl-my-dynamic-slider-block',
plugins_url( $style_css, __FILE__ ),
array(),
filemtime( "$dir/$style_css" )
);
register_block_type( 'wdl/my-dynamic-slider', array(
'editor_script' => 'wdl-my-dynamic-slider-block-editor',
'editor_style' => 'wdl-my-dynamic-slider-block-editor',
'style' => 'wdl-my-dynamic-slider-block',
//render_callback を追加
'render_callback' => 'my_dynamic_slider_render',
//属性を追加
'attributes' => [
//アイキャッチ画像のカテゴリーのID
'termId' => [
'type' => 'number',
'default' => 0
],
//スライダーに表示する画像の数
'numSlides' => [
'type' => 'number',
'default' => 3
],
//ナビゲーションボタンの表示・非表示
'showNavigationButton' => [
'type' => 'boolean',
'default' => true
],
//ページネーションの表示・非表示
'showPagination' => [
'type' => 'boolean',
'default' => true
],
//スクロールバーンの表示・非表示
'showScrollbar' => [
'type' => 'boolean',
'default' => true
],
//キャプションの表示・非表示
'showCaption' => [
'type' => 'boolean',
'default' => true
],
]
));
}
add_action( 'init', 'wdl_my_dynamic_slider_block_init' );
function my_dynamic_slider_render($attributes, $content) {
//カテゴリーが選択されていない場合は空文字列を返す(何も表示しない)
if ($attributes['termId'] === 0) {
return '';
}
// WP_Query を使ったサブループ
$my_Query = new WP_Query([
//属性の値を使って取得する投稿の条件を指定
'posts_per_page' => $attributes['numSlides'],
'cat' => $attributes['termId']
]);
if ($my_Query->have_posts()) {
//該当する投稿があればスライダーのマークアップを組み立てる
$output = '<div class="swiper-container wp-block-wdl-my-dynamic-slider">';
$output .= '<div class="swiper-wrapper">';
while ($my_Query->have_posts()) {
$my_Query->the_post();
//アイキャッチ画像があれば
if (has_post_thumbnail()) {
//アイキャッチ画像の ID を取得
$post_thumbnail_id = get_post_thumbnail_id();
//アイキャッチ画像のオブジェクトを取得
$my_thumbnail = get_post($post_thumbnail_id);
$img_url = esc_url($my_thumbnail -> guid);
$img_caption = esc_html($my_thumbnail -> post_excerpt);
//get_post_meta() でカスタムフィールドの内部的な値である alt 属性を取得
$my_thumbnail_meta = get_post_meta($post_thumbnail_id);
$img_alt = $my_thumbnail_meta["_wp_attachment_image_alt"][0];
$output .= '<div class="swiper-slide"><img src="' . $img_url . '" alt="' . $img_alt .'" />';
//キャプションを表示する場合
if($attributes['showCaption']) {
if($img_caption) {
$output .= '<div class="caption">'. $img_caption . '</div>';
}
}
$output .= '</div>';
}
}
wp_reset_postdata(); //グローバル変数 $post を復元
$output .= '</div>';
//ページネーションを表示する場合
if($attributes['showPagination']) {
$output .= '<div class="swiper-pagination"></div>';
}
//ナビゲーションボタンを表示する場合
if($attributes['showNavigationButton']) {
$output .= '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>';
}
//スクロールバーを表示する場合
if($attributes['showScrollbar']) {
$output .= '<div class="swiper-scrollbar"></div>';
}
$output .= '</div>';
return $output;
} else {
return '';
}
}
function add_my_dynamic_slider_scripts_and_styles() {
$dir = dirname( __FILE__ );
//管理画面以外(フロントエンド側でのみ読み込む)
if(! is_admin()) {
//Swiper の JavaScript ファイルの読み込み(エンキュー)
wp_enqueue_script(
'swiper-slider',
plugins_url( '/assets/swiper.js', __FILE__ ),
array(),
filemtime( "$dir/assets/swiper.js" ),
true
);
//Swiper を初期化するためのファイルの読み込み(エンキュー)
wp_enqueue_script(
'swiper-slider-init',
plugins_url( '/assets/init-swiper.js', __FILE__ ),
//依存ファイルに上記 Swiper の JavaScript を指定
array('swiper-slider'),
filemtime( "$dir/assets/init-swiper.js" ),
true
);
//Swiper の CSS ファイルの読み込み(エンキュー)
wp_enqueue_style(
'swipe-style',
plugins_url( '/assets/swiper.css', __FILE__ ),
array(),
filemtime( "$dir/assets/swiper.css" )
);
}
}
add_action('enqueue_block_assets', 'add_my_dynamic_slider_scripts_and_styles');
スライダーのスタイル
表示するスライダーのスタイルは src/style.scss で設定することができます。
以下ではスライダーのマークアップで指定したクラス swiper-container などを使ってキャプションとページネーションのスタイルを指定しています。
.swiper-container .caption {
background-color: rgba(0,0,0,0.7);
color: #fefefe;
text-align: center;
position: absolute;
bottom: 0px;
width: 100%;
}
.swiper-container .swiper-pagination.swiper-pagination-bullets {
bottom: 30px;
}
以下はフロントエンド側の表示例です。
ここまでのコードのサンプル
以下はここまでのコードのファイル構成とファイルです。
npm run build でビルドを実行すると、以下のような構成になります。
本番環境で必要なのは、assets と build 内の全てのファイルと my-dynamic-slider.php になります。
my-dynamic-slider
├── assets
│ ├── init-swiper.js
│ ├── swiper.css
│ └── swiper.js
├── block.json
├── build
│ ├── index.asset.php
│ ├── index.css
│ ├── index.js
│ └── style-index.css
├── node_modules
├── my-dynamic-slider.php
├── package-lock.json
├── package.json
├── readme.txt
└── src
├── category-select.js
├── edit.js
├── editor.scss
├── index.js
└── style.scss
import { withSelect } from '@wordpress/data';
import { MenuGroup, MenuItem } from '@wordpress/components';
const CategorySelect = (props) => {
const { terms, selectedTermId, selectTerm } = props;
return(
<MenuGroup
className="my-category-select"
>
{terms && (
terms.map((item) => (
<MenuItem
role="menuitemradio"
isSelected={item.id == selectedTermId}
icon={item.id == selectedTermId ? 'yes' : 'marker'}
onClick={() => selectTerm(item.id)}
>
{item.name}
</MenuItem>
))
)}
</MenuGroup>
);
}
export default withSelect((select, props) => {
return {
terms: select('core').getEntityRecords('taxonomy', 'category', {per_page: -1})
}
})(CategorySelect);
import './editor.scss';
import { InspectorControls } from '@wordpress/block-editor';
import { Placeholder, PanelBody, PanelRow, RangeControl, ToggleControl } from '@wordpress/components';
import CategorySelect from './category-select';
export default function Edit( props ) {
const {className, attributes, setAttributes} = props;
const selectTerm = (termId) => {
setAttributes({ termId: termId });
}
const getInspectorControls = () => {
return (
<InspectorControls>
<PanelBody
title='Slider Settings'
initialOpen={true}
>
<PanelRow>
<RangeControl
label='Number of slides'
value={attributes.numSlides}
onChange={(val) => setAttributes({ numSlides: val })}
min={1}
max={10}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ナビゲーションボタン"
checked={attributes.showNavigationButton}
onChange={(val) => setAttributes({ showNavigationButton: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="ページネーション"
checked={attributes.showPagination}
onChange={(val) => setAttributes({ showPagination: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="スクロールバー"
checked={attributes.showScrollbar}
onChange={(val) => setAttributes({ showScrollbar: val })}
/>
</PanelRow>
<PanelRow>
<ToggleControl
label="キャプション"
checked={attributes.showCaption}
onChange={(val) => setAttributes({ showCaption: val })}
/>
</PanelRow>
</PanelBody>
</InspectorControls>
);
}
return (
[
getInspectorControls(), //インスペクター
<div className={className}>
<Placeholder
label='スライダーカテゴリー'
icon='format-image'
instructions='スライダーに表示するアイキャッチ画像のカテゴリーを選択'
>
<CategorySelect
selectedTermId={attributes.termId}
selectTerm={selectTerm}
/>
</Placeholder>
</div>
]
);
}
import { registerBlockType } from '@wordpress/blocks';
import './style.scss';
import Edit from './edit';
registerBlockType( 'wdl/my-dynamic-slider', {
title: 'My Dynamic Slider',
description:'Example block written with ESNext standard and JSX support',
category: 'widgets',
icon: 'smiley',
supports: {
html: false,
},
edit: Edit,
save: () => { return null }
} );
.my-category-select {
max-height: 200px;
overflow: hidden scroll;
border: 1px solid #C0BCBC;
background: #fcfcfc;
}
.swiper-container .caption {
background-color: rgba(0,0,0,0.7);
color: #fefefe;
text-align: center;
position: absolute;
bottom: 0px;
width: 100%;
}
.swiper-container .swiper-pagination.swiper-pagination-bullets {
bottom: 30px;
}
<?php
/**
* Plugin Name: My Dynamic Slider
* Description: Example block written with ESNext standard and JSX support – build step required.
* Version: 0.1.0
* Author: The WordPress Contributors
* License: GPL-2.0-or-later
* License URI: https://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: my-dynamic-slider
*
* @package wdl
*/
/**
* Registers all block assets so that they can be enqueued through the block editor
* in the corresponding context.
*
* @see https://developer.wordpress.org/block-editor/tutorials/block-tutorial/applying-styles-with-stylesheets/
*/
function wdl_my_dynamic_slider_block_init() {
$dir = dirname( __FILE__ );
$script_asset_path = "$dir/build/index.asset.php";
if ( ! file_exists( $script_asset_path ) ) {
throw new Error(
'You need to run `npm start` or `npm run build` for the "wdl/my-dynamic-slider" block first.'
);
}
$index_js = 'build/index.js';
$script_asset = require( $script_asset_path );
wp_register_script(
'wdl-my-dynamic-slider-block-editor',
plugins_url( $index_js, __FILE__ ),
$script_asset['dependencies'],
$script_asset['version']
);
wp_set_script_translations( 'wdl-my-dynamic-slider-block-editor', 'my-dynamic-slider' );
$editor_css = 'build/index.css';
wp_register_style(
'wdl-my-dynamic-slider-block-editor',
plugins_url( $editor_css, __FILE__ ),
array(),
filemtime( "$dir/$editor_css" )
);
$style_css = 'build/style-index.css';
wp_register_style(
'wdl-my-dynamic-slider-block',
plugins_url( $style_css, __FILE__ ),
array(),
filemtime( "$dir/$style_css" )
);
register_block_type( 'wdl/my-dynamic-slider', array(
'editor_script' => 'wdl-my-dynamic-slider-block-editor',
'editor_style' => 'wdl-my-dynamic-slider-block-editor',
'style' => 'wdl-my-dynamic-slider-block',
//render_callback を追加
'render_callback' => 'my_dynamic_slider_render',
//属性を追加
'attributes' => [
//アイキャッチ画像のカテゴリーのID
'termId' => [
'type' => 'number',
'default' => 0
],
//スライダーに表示する画像の数
'numSlides' => [
'type' => 'number',
'default' => 3
],
//ナビゲーションボタンの表示・非表示
'showNavigationButton' => [
'type' => 'boolean',
'default' => true
],
//ページネーションの表示・非表示
'showPagination' => [
'type' => 'boolean',
'default' => true
],
//スクロールバーンの表示・非表示
'showScrollbar' => [
'type' => 'boolean',
'default' => true
],
//キャプションの表示・非表示
'showCaption' => [
'type' => 'boolean',
'default' => true
],
]
));
}
add_action( 'init', 'wdl_my_dynamic_slider_block_init' );
function my_dynamic_slider_render($attributes, $content) {
//カテゴリーが選択されていない場合は空文字列を返す(何も表示しない)
if ($attributes['termId'] === 0) {
return '';
}
// WP_Query を使ったサブループ
$my_Query = new WP_Query([
//属性の値を使って取得する投稿の条件を指定
'posts_per_page' => $attributes['numSlides'],
'cat' => $attributes['termId']
]);
if ($my_Query->have_posts()) {
//該当する投稿があればスライダーのマークアップを組み立てる
$output = '<div class="swiper-container wp-block-wdl-my-dynamic-slider">';
$output .= '<div class="swiper-wrapper">';
while ($my_Query->have_posts()) {
$my_Query->the_post();
//アイキャッチ画像があれば
if (has_post_thumbnail()) {
//アイキャッチ画像の ID を取得
$post_thumbnail_id = get_post_thumbnail_id();
//アイキャッチ画像のオブジェクトを取得
$my_thumbnail = get_post($post_thumbnail_id);
$img_url = esc_url($my_thumbnail -> guid);
$img_caption = esc_html($my_thumbnail -> post_excerpt);
//get_post_meta() でカスタムフィールドの内部的な値である alt 属性を取得
$my_thumbnail_meta = get_post_meta($post_thumbnail_id);
$img_alt = $my_thumbnail_meta["_wp_attachment_image_alt"][0];
$output .= '<div class="swiper-slide"><img src="' . $img_url . '" alt="' . $img_alt .'" />';
//キャプションを表示する場合
if($attributes['showCaption']) {
if($img_caption) {
$output .= '<div class="caption">'. $img_caption . '</div>';
}
}
$output .= '</div>';
}
}
wp_reset_postdata(); //グローバル変数 $post を復元
$output .= '</div>';
//ページネーションを表示する場合
if($attributes['showPagination']) {
$output .= '<div class="swiper-pagination"></div>';
}
//ナビゲーションボタンを表示する場合
if($attributes['showNavigationButton']) {
$output .= '<div class="swiper-button-prev"></div><div class="swiper-button-next"></div>';
}
//スクロールバーを表示する場合
if($attributes['showScrollbar']) {
$output .= '<div class="swiper-scrollbar"></div>';
}
$output .= '</div>';
return $output;
} else {
return '';
}
}
function add_my_dynamic_slider_scripts_and_styles() {
$dir = dirname( __FILE__ );
//管理画面以外(フロントエンド側でのみ読み込む)
if(! is_admin()) {
//Swiper の JavaScript ファイルの読み込み(エンキュー)
wp_enqueue_script(
'swiper-slider',
plugins_url( '/assets/swiper.js', __FILE__ ),
array(),
filemtime( "$dir/assets/swiper.js" ),
true
);
//Swiper を初期化するためのファイルの読み込み(エンキュー)
wp_enqueue_script(
'swiper-slider-init',
plugins_url( '/assets/init-swiper.js', __FILE__ ),
//依存ファイルに上記 Swiper の JavaScript を指定
array('swiper-slider'),
filemtime( "$dir/assets/init-swiper.js" ),
true
);
//Swiper の CSS ファイルの読み込み(エンキュー)
wp_enqueue_style(
'swipe-style',
plugins_url( '/assets/swiper.css', __FILE__ ),
array(),
filemtime( "$dir/assets/swiper.css" )
);
}
}
add_action('enqueue_block_assets', 'add_my_dynamic_slider_scripts_and_styles');
let mySwiper = new Swiper ('.swiper-container', {
autoplay: {
delay: 4000,
},
loop: true,
pagination: {
el: '.swiper-pagination',
type: 'bullets', //ページネーションの種類
clickable: true, //クリックに反応させる
},
navigation: {
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
scrollbar: {
el: '.swiper-scrollbar', //要素の指定
},
})
swiper.css(https://unpkg.com/swiper@6.3.2/swiper-bundle.min.css)
swiper.js(https://unpkg.com/swiper@6.3.2/swiper-bundle.min.js)











