WordPress幻灯片功能的完整代码实现。它创建了一个自定义帖子类型“幻灯片”,左侧大图轮播,右侧小图垂直滚动,所有图片数量、推荐和置顶状态均在后台可设。
<?php
/**
* Plugin Name: 高级幻灯片功能
* Description: 左侧大图轮播 + 右侧小图垂直滚动,支持后台管理图片、推荐和置顶
* Version: 1.0
* Author: Your Name
*/
// 安全起见,防止直接访问
if (!defined('ABSPATH')) {
exit;
}
class AdvancedSlider {
public function __construct() {
add_action('init', array($this, 'register_slider_post_type'));
add_action('add_meta_boxes', array($this, 'add_slider_meta_boxes'));
add_action('save_post', array($this, 'save_slider_meta'));
add_shortcode('advanced_slider', array($this, 'render_slider_shortcode'));
add_action('wp_enqueue_scripts', array($this, 'enqueue_slider_assets'));
// 添加图片上传相关钩子
add_action('admin_enqueue_scripts', array($this, 'admin_enqueue_scripts'));
}
// 注册自定义文章类型
public function register_slider_post_type() {
$labels = array(
'name' => '幻灯片',
'singular_name' => '幻灯片项目',
'menu_name' => '高级幻灯片',
'add_new' => '添加新幻灯片',
'add_new_item' => '添加新幻灯片项目',
'edit_item' => '编辑幻灯片项目',
'new_item' => '新幻灯片项目',
'view_item' => '查看幻灯片项目',
'search_items' => '搜索幻灯片',
'not_found' => '未找到幻灯片',
'not_found_in_trash' => '回收站中没有幻灯片',
);
$args = array(
'labels' => $labels,
'public' => false,
'publicly_queryable' => false,
'show_ui' => true,
'show_in_menu' => true,
'query_var' => false,
'rewrite' => false,
'capability_type' => 'post',
'has_archive' => false,
'hierarchical' => false,
'menu_position' => 20,
'menu_icon' => 'dashicons-images-alt2',
'supports' => array('title'),
);
register_post_type('slider_item', $args);
}
// 添加元数据框
public function add_slider_meta_boxes() {
add_meta_box(
'slider_settings',
'幻灯片设置',
array($this, 'render_slider_meta_box'),
'slider_item',
'normal',
'high'
);
}
// 渲染元数据框
public function render_slider_meta_box($post) {
wp_nonce_field('slider_meta_box', 'slider_meta_box_nonce');
$image_url = get_post_meta($post->ID, '_slider_image_url', true);
$link_url = get_post_meta($post->ID, '_slider_link_url', true);
$is_sticky = get_post_meta($post->ID, '_slider_sticky', true);
$is_featured = get_post_meta($post->ID, '_slider_featured', true);
$slide_text = get_post_meta($post->ID, '_slider_text', true);
$slide_order = get_post_meta($post->ID, '_slider_order', true);
?>
<style>
.slider-meta-field {
margin-bottom: 15px;
}
.slider-meta-field label {
display: inline-block;
width: 120px;
font-weight: bold;
vertical-align: top;
}
.slider-meta-field input[type="text"],
.slider-meta-field textarea {
width: 70%;
}
.slider-image-preview {
margin-left: 125px;
margin-top: 5px;
}
.slider-image-preview img {
max-width: 200px;
max-height: 150px;
border: 1px solid #ddd;
padding: 2px;
}
</style>
<div class="slider-meta-field">
<label>图片URL:</label>
<input type="text" name="slider_image_url" id="slider_image_url" value="<?php echo esc_url($image_url); ?>" style="width: 60%;" />
<button type="button" class="button upload_image_button">上传图片</button>
<div class="slider-image-preview">
<?php if ($image_url) : ?>
<img src="<?php echo esc_url($image_url); ?>" alt="预览图片" />
<?php endif; ?>
</div>
</div>
<div class="slider-meta-field">
<label>链接URL (可选):</label>
<input type="text" name="slider_link_url" value="<?php echo esc_url($link_url); ?>" style="width: 70%;" />
<p class="description">点击幻灯片时跳转的链接</p>
</div>
<div class="slider-meta-field">
<label>文字说明 (可选):</label>
<textarea name="slider_text" rows="3" style="width: 70%;"><?php echo esc_textarea($slide_text); ?></textarea>
</div>
<div class="slider-meta-field">
<label>排序权重:</label>
<input type="number" name="slider_order" value="<?php echo intval($slide_order); ?>" style="width: 100px;" />
<p class="description">数值越小越靠前,用于自定义顺序</p>
</div>
<div class="slider-meta-field">
<label>置顶:</label>
<input type="checkbox" name="slider_sticky" value="1" <?php checked($is_sticky, '1'); ?> />
<span>置顶的幻灯片会显示在右侧小图区域的最前面</span>
</div>
<div class="slider-meta-field">
<label>推荐:</label>
<input type="checkbox" name="slider_featured" value="1" <?php checked($is_featured, '1'); ?> />
<span>推荐的幻灯片会在左侧大图中优先显示</span>
</div>
<?php
}
// 保存元数据
public function save_slider_meta($post_id) {
if (!isset($_POST['slider_meta_box_nonce']) || !wp_verify_nonce($_POST['slider_meta_box_nonce'], 'slider_meta_box')) {
return;
}
if (defined('DOING_AUTOSAVE') && DOING_AUTOSAVE) {
return;
}
if (!current_user_can('edit_post', $post_id)) {
return;
}
if (isset($_POST['slider_image_url'])) {
update_post_meta($post_id, '_slider_image_url', esc_url_raw($_POST['slider_image_url']));
}
if (isset($_POST['slider_link_url'])) {
update_post_meta($post_id, '_slider_link_url', esc_url_raw($_POST['slider_link_url']));
}
if (isset($_POST['slider_text'])) {
update_post_meta($post_id, '_slider_text', sanitize_textarea_field($_POST['slider_text']));
}
if (isset($_POST['slider_order'])) {
update_post_meta($post_id, '_slider_order', intval($_POST['slider_order']));
}
$sticky = isset($_POST['slider_sticky']) ? '1' : '0';
update_post_meta($post_id, '_slider_sticky', $sticky);
$featured = isset($_POST['slider_featured']) ? '1' : '0';
update_post_meta($post_id, '_slider_featured', $featured);
}
// 后台加载媒体上传器
public function admin_enqueue_scripts($hook) {
global $post_type;
if ('slider_item' === $post_type) {
wp_enqueue_media();
wp_add_inline_script('media-upload', '
jQuery(document).ready(function($) {
$(".upload_image_button").click(function(e) {
e.preventDefault();
var button = $(this);
var customUploader = wp.media({
title: "选择图片",
button: {
text: "使用此图片"
},
multiple: false
}).on("select", function() {
var attachment = customUploader.state().get("selection").first().toJSON();
button.siblings("#slider_image_url").val(attachment.url);
button.siblings(".slider-image-preview").html("<img src=\"" + attachment.url + "\" style=\"max-width:200px;\" />");
}).open();
});
});
');
}
}
// 加载前端样式和脚本
public function enqueue_slider_assets() {
if (has_shortcode(get_post()->post_content, 'advanced_slider')) {
wp_enqueue_style('advanced-slider-style', plugin_dir_url(__FILE__) . 'assets/slider-style.css', array(), '1.0');
wp_enqueue_script('advanced-slider-script', plugin_dir_url(__FILE__) . 'assets/slider-script.js', array('jquery'), '1.0', true);
wp_localize_script('advanced-slider-script', 'sliderAjax', array(
'ajaxurl' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('slider_nonce')
));
}
}
// 获取幻灯片数据
private function get_slider_items() {
// 获取左侧大图(推荐)
$featured_args = array(
'post_type' => 'slider_item',
'posts_per_page' => -1,
'meta_query' => array(
array(
'key' => '_slider_featured',
'value' => '1',
'compare' => '='
)
),
'meta_key' => '_slider_order',
'orderby' => array(
'meta_value_num' => 'ASC',
'date' => 'DESC'
),
'order' => 'ASC'
);
// 获取置顶和普通右侧小图
$right_args = array(
'post_type' => 'slider_item',
'posts_per_page' => -1,
'meta_query' => array(
'relation' => 'OR',
array(
'key' => '_slider_sticky',
'value' => '1',
'compare' => '='
),
array(
'key' => '_slider_sticky',
'value' => '0',
'compare' => '='
)
),
'meta_key' => '_slider_order',
'orderby' => array(
'meta_value_num' => 'ASC',
'date' => 'DESC'
),
'order' => 'ASC'
);
$featured_items = get_posts($featured_args);
$all_items = get_posts($right_args);
// 如果没有推荐项,则从所有项中取
if (empty($featured_items)) {
$featured_args['meta_query'] = null;
$featured_items = get_posts($featured_args);
}
// 处理右侧项:置顶优先
$sticky_items = array();
$normal_items = array();
foreach ($all_items as $item) {
$is_sticky = get_post_meta($item->ID, '_slider_sticky', true);
if ($is_sticky == '1') {
$sticky_items[] = $item;
} else {
$normal_items[] = $item;
}
}
$right_items = array_merge($sticky_items, $normal_items);
return array(
'left_items' => $featured_items,
'right_items' => $right_items
);
}
// 渲染短代码
public function render_slider_shortcode($atts) {
$atts = shortcode_atts(array(
'left_count' => 5, // 左侧大图数量
'right_count' => 10, // 右侧小图显示数量
), $atts);
$items = $this->get_slider_items();
$left_items = array_slice($items['left_items'], 0, intval($atts['left_count']));
$right_items = array_slice($items['right_items'], 0, intval($atts['right_count']));
ob_start();
?>
<div class="advanced-slider-container">
<div class="slider-left">
<div class="main-slider">
<?php if (!empty($left_items)) : ?>
<?php foreach ($left_items as $index => $item) :
$image_url = get_post_meta($item->ID, '_slider_image_url', true);
$link_url = get_post_meta($item->ID, '_slider_link_url', true);
$text = get_post_meta($item->ID, '_slider_text', true);
?>
<div class="slide-item <?php echo $index === 0 ? 'active' : ''; ?>" data-index="<?php echo $index; ?>">
<?php if ($link_url) : ?>
<a href="<?php echo esc_url($link_url); ?>">
<img src="<?php echo esc_url($image_url); ?>" alt="<?php echo esc_attr($item->post_title); ?>">
<?php if ($text) : ?>
<div class="slide-caption"><?php echo esc_html($text); ?></div>
<?php endif; ?>
</a>
<?php else : ?>
<img src="<?php echo esc_url($image_url); ?>" alt="<?php echo esc_attr($item->post_title); ?>">
<?php if ($text) : ?>
<div class="slide-caption"><?php echo esc_html($text); ?></div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php endforeach; ?>
<div class="slider-nav">
<span class="prev-slide">❮</span>
<span class="next-slide">❯</span>
</div>
<div class="slider-dots">
<?php foreach ($left_items as $index => $item) : ?>
<span class="dot <?php echo $index === 0 ? 'active' : ''; ?>" data-index="<?php echo $index; ?>"></span>
<?php endforeach; ?>
</div>
<?php else : ?>
<p>暂无幻灯片内容,请在后台添加。</p>
<?php endif; ?>
</div>
</div>
<div class="slider-right">
<div class="thumb-scroll-container">
<div class="thumb-list">
<?php foreach ($right_items as $item) :
$image_url = get_post_meta($item->ID, '_slider_image_url', true);
$title = $item->post_title;
$is_sticky = get_post_meta($item->ID, '_slider_sticky', true);
?>
<div class="thumb-item <?php echo $is_sticky ? 'sticky' : ''; ?>" data-id="<?php echo $item->ID; ?>">
<img src="<?php echo esc_url($image_url); ?>" alt="<?php echo esc_attr($title); ?>">
<div class="thumb-title"><?php echo esc_html($title); ?></div>
<?php if ($is_sticky) : ?>
<span class="sticky-badge">置顶</span>
<?php endif; ?>
</div>
<?php endforeach; ?>
</div>
</div>
</div>
</div>
<?php
return ob_get_clean();
}
}
// 初始化插件
new AdvancedSlider();
// 创建assets目录和CSS/JS文件
function advanced_slider_create_assets() {
$upload_dir = plugin_dir_path(__FILE__);
$assets_dir = $upload_dir . 'assets/';
if (!file_exists($assets_dir)) {
mkdir($assets_dir, 0755, true);
}
// CSS文件
$css_content = <<<CSS
.advanced-slider-container {
display: flex;
gap: 20px;
max-width: 1200px;
margin: 0 auto;
position: relative;
font-family: Arial, sans-serif;
}
.slider-left {
flex: 2;
position: relative;
}
.main-slider {
position: relative;
overflow: hidden;
border-radius: 8px;
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.slide-item {
display: none;
position: relative;
}
.slide-item.active {
display: block;
animation: fadeIn 0.5s ease-in-out;
}
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.slide-item img {
width: 100%;
height: 400px;
object-fit: cover;
display: block;
}
.slide-caption {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(0,0,0,0.7);
color: white;
padding: 10px;
text-align: center;
}
.slider-nav {
position: absolute;
top: 50%;
width: 100%;
transform: translateY(-50%);
display: flex;
justify-content: space-between;
padding: 0 10px;
box-sizing: border-box;
}
.prev-slide, .next-slide {
cursor: pointer;
background: rgba(0,0,0,0.5);
color: white;
padding: 10px 15px;
border-radius: 50%;
font-size: 18px;
transition: 0.3s;
}
.prev-slide:hover, .next-slide:hover {
background: rgba(0,0,0,0.8);
}
.slider-dots {
text-align: center;
padding: 10px 0;
position: absolute;
bottom: 10px;
left: 0;
right: 0;
}
.dot {
cursor: pointer;
height: 12px;
width: 12px;
margin: 0 5px;
background-color: #bbb;
border-radius: 50%;
display: inline-block;
transition: background-color 0.3s;
}
.dot.active, .dot:hover {
background-color: #717171;
}
.slider-right {
flex: 1;
}
.thumb-scroll-container {
height: 400px;
overflow-y: auto;
border-radius: 8px;
background: #f5f5f5;
padding: 10px;
}
.thumb-list {
display: flex;
flex-direction: column;
gap: 10px;
}
.thumb-item {
position: relative;
background: white;
border-radius: 6px;
overflow: hidden;
cursor: pointer;
transition: transform 0.2s, box-shadow 0.2s;
box-shadow: 0 1px 3px rgba(0,0,0,0.1);
}
.thumb-item:hover {
transform: translateX(-5px);
box-shadow: 0 3px 10px rgba(0,0,0,0.2);
}
.thumb-item.sticky {
border-left: 4px solid #ff9800;
}
.thumb-item img {
width: 100%;
height: 80px;
object-fit: cover;
display: block;
}
.thumb-title {
padding: 8px;
font-size: 14px;
background: white;
text-align: center;
font-weight: bold;
color: #333;
}
.sticky-badge {
position: absolute;
top: 5px;
right: 5px;
background: #ff9800;
color: white;
padding: 2px 6px;
border-radius: 3px;
font-size: 10px;
font-weight: bold;
}
/* 滚动条样式 */
.thumb-scroll-container::-webkit-scrollbar {
width: 8px;
}
.thumb-scroll-container::-webkit-scrollbar-track {
background: #f1f1f1;
border-radius: 10px;
}
.thumb-scroll-container::-webkit-scrollbar-thumb {
background: #888;
border-radius: 10px;
}
.thumb-scroll-container::-webkit-scrollbar-thumb:hover {
background: #555;
}
/* 响应式 */
@media (max-width: 768px) {
.advanced-slider-container {
flex-direction: column;
}
.slide-item img {
height: 250px;
}
.thumb-scroll-container {
height: 300px;
}
}
CSS;
file_put_contents($assets_dir . 'slider-style.css', $css_content);
// JS文件
$js_content = <<<JS
jQuery(document).ready(function($) {
var currentIndex = 0;
var slideItems = $('.slide-item');
var totalSlides = slideItems.length;
var autoPlayInterval;
function showSlide(index) {
if (index < 0) index = totalSlides - 1;
if (index >= totalSlides) index = 0;
slideItems.removeClass('active');
$(slideItems[index]).addClass('active');
$('.dot').removeClass('active');
$('.dot[data-index="' + index + '"]').addClass('active');
currentIndex = index;
}
function nextSlide() {
showSlide(currentIndex + 1);
}
function prevSlide() {
showSlide(currentIndex - 1);
}
function startAutoPlay() {
if (autoPlayInterval) clearInterval(autoPlayInterval);
autoPlayInterval = setInterval(nextSlide, 5000);
}
function stopAutoPlay() {
if (autoPlayInterval) {
clearInterval(autoPlayInterval);
autoPlayInterval = null;
}
}
if (totalSlides > 0) {
$('.next-slide').on('click', function() {
nextSlide();
stopAutoPlay();
startAutoPlay();
});
$('.prev-slide').on('click', function() {
prevSlide();
stopAutoPlay();
startAutoPlay();
});
$('.dot').on('click', function() {
var index = $(this).data('index');
showSlide(index);
stopAutoPlay();
startAutoPlay();
});
// 右侧缩略图点击事件 - 切换到对应的大图
$('.thumb-item').on('click', function() {
var thumbId = $(this).data('id');
// 查找左侧大图中对应的幻灯片(根据图片URL或标题匹配)
var thumbImg = $(this).find('img').attr('src');
var foundIndex = -1;
slideItems.each(function(index) {
var slideImg = $(this).find('img').attr('src');
if (slideImg === thumbImg) {
foundIndex = index;
return false;
}
});
if (foundIndex !== -1) {
showSlide(foundIndex);
stopAutoPlay();
startAutoPlay();
}
});
// 鼠标悬停时暂停自动播放
$('.main-slider').hover(function() {
stopAutoPlay();
}, function() {
startAutoPlay();
});
// 启动自动播放
startAutoPlay();
}
});
JS;
file_put_contents($assets_dir . 'slider-script.js', $js_content);
}
register_activation_hook(__FILE__, 'advanced_slider_create_assets');
安装步骤
1. 创建插件文件
将上面的完整代码保存为一个PHP文件,例如 advanced-slider.php,然后放到:
/wp-content/plugins/advanced-slider/advanced-slider.php
2. 激活插件
进入 WordPress 后台 → 插件 → 找到”高级幻灯片功能” → 点击激活
插件激活时会自动在插件目录下创建
assets文件夹和所需的CSS/JS文件
使用方法
第一步:添加幻灯片内容
进入后台 → 高级幻灯片 → 添加新幻灯片
每个幻灯片需要填写:
- 标题:幻灯片的名称(用于右侧小图显示)
- 图片URL:点击”上传图片”按钮选择图片
- 链接URL(可选):点击大图时跳转的链接
- 文字说明(可选):显示在大图底部的文字
- 排序权重:数值越小越靠前
- 置顶:勾选后会在右侧小图区域置顶显示(带橙色标记)
- 推荐:勾选后会显示在左侧大图轮播区
第二步:在页面中显示幻灯片
在任意页面或文章的编辑器中,添加短代码:
[advanced_slider]
第三步:可选参数调整数量
[advanced_slider left_count="3" right_count="6]
参数说明:
left_count:左侧大图显示数量(默认5)right_count:右侧小图显示数量(默认10)
功能说明
| 区域 | 功能 |
|---|---|
| 左侧大图 | 自动轮播(5秒切换),支持点击箭头或圆点切换,鼠标悬停时暂停 |
| 右侧小图 | 垂直滚动列表,点击小图可切换到对应大图 |
| 置顶功能 | 右侧小图中置顶项显示橙色边框和”置顶”标签 |
| 推荐功能 | 推荐项优先显示在左侧大图区 |
常见问题
Q:右侧小图滚动速度能调吗?
A:滚动速度由CSS控制,可以修改 assets/slider-style.css 中的滚动条样式。
Q:可以修改自动轮播间隔吗?
A:在 assets/slider-script.js 中找到 5000(毫秒),改成您想要的值即可。
Q:图片尺寸建议?
A:左侧大图建议 800×400px,右侧小图建议 300×80px(会自动裁剪适应)。