v1.4 — Photo 详情页画廊
- 灯箱画廊:点击图片全屏查看,多图左右切换 - 单图隐藏左右箭头,边界隐藏对应方向键 - 画廊顶部显示'标题 · 作者' - 文章导航保留在灯箱底部 - 图片去重(特色图与正文图片不重复) - 纯黑背景 - 已知限制:画廊内切换文章后灯箱不保持(AJAX 模式未稳定)
This commit is contained in:
+16
-1
@@ -210,10 +210,25 @@ function kjweji_register_photo() {
|
||||
),
|
||||
'public' => true,
|
||||
'has_archive' => false,
|
||||
'rewrite' => array('slug' => 'photo'),
|
||||
'rewrite' => array('slug' => 'photo/%post_id%'),
|
||||
'show_in_rest' => true,
|
||||
'supports' => array('title', 'editor', 'author', 'thumbnail'),
|
||||
'menu_position' => 26,
|
||||
'menu_icon' => 'dashicons-format-gallery',
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
|
||||
add_filter('post_type_link', function($link, $post) {
|
||||
if ($post->post_type === 'photo' && $post->post_status === 'publish') {
|
||||
return home_url(user_trailingslashit('/photo/' . $post->ID . '/' . $post->post_name));
|
||||
}
|
||||
return $link;
|
||||
}, 10, 2);
|
||||
|
||||
// 匹配 /photo/123/slug/ 格式
|
||||
add_action('init', function() {
|
||||
add_rewrite_rule('^photo/([0-9]+)/([^/]+)/?$', 'index.php?post_type=photo&p=$matches[1]', 'top');
|
||||
add_rewrite_rule('^photo/([0-9]+)/?$', 'index.php?post_type=photo&p=$matches[1]', 'top');
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ get_header();
|
||||
$photo_query = new WP_Query(array(
|
||||
'post_type' => 'photo',
|
||||
'posts_per_page' => -1,
|
||||
'meta_key' => '_thumbnail_id',
|
||||
));
|
||||
?>
|
||||
|
||||
|
||||
+132
-9
@@ -1,18 +1,53 @@
|
||||
<?php get_header(); ?>
|
||||
|
||||
<?php while (have_posts()) : the_post(); ?>
|
||||
<div class="photo-detail">
|
||||
<?php
|
||||
// 收集所有图片 URL(去重)
|
||||
$gallery = array();
|
||||
$seen = array();
|
||||
// 正文中的图片(先收,因为特色图和正文第一张可能重复)
|
||||
$content_raw = get_the_content();
|
||||
if (preg_match_all('/<img[^>]+src="([^"]+)"/', $content_raw, $m)) {
|
||||
foreach ($m[1] as $url) {
|
||||
$key = basename(parse_url($url, PHP_URL_PATH));
|
||||
if (!isset($seen[$key])) {
|
||||
$seen[$key] = true;
|
||||
$gallery[] = $url;
|
||||
}
|
||||
}
|
||||
}
|
||||
// 特色图(如果没有出现在正文中则加入)
|
||||
if (has_post_thumbnail()) {
|
||||
$thumb_url = get_the_post_thumbnail_url(null, 'large');
|
||||
$key = basename(parse_url($thumb_url, PHP_URL_PATH));
|
||||
if (!isset($seen[$key])) {
|
||||
$gallery[] = $thumb_url;
|
||||
}
|
||||
}
|
||||
$gallery_json = json_encode($gallery);
|
||||
$content = $content_raw;
|
||||
?>
|
||||
|
||||
<div class="photo-detail" id="photo-detail"
|
||||
data-gallery="<?php echo esc_attr($gallery_json); ?>"
|
||||
data-title="<?php echo esc_attr(get_the_title()); ?>"
|
||||
data-author="<?php echo esc_attr(get_avatar(get_the_author_meta('ID'), 18) . ' ' . get_the_author_meta('display_name')); ?>">
|
||||
<a href="/photos/" class="back-link">← 返回拾影</a>
|
||||
|
||||
<div class="photo-detail__image">
|
||||
<?php if (has_post_thumbnail()) : ?>
|
||||
<?php // 多图文章的特色图已在正文中,不重复显示
|
||||
if (!preg_match('/<img[^>]+src=/', $content) && has_post_thumbnail()) : ?>
|
||||
<div class="photo-detail__image" onclick="openPhotoGallery(0)">
|
||||
<?php the_post_thumbnail('medium_large', array('alt' => get_the_title())); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if (get_the_content()) : ?>
|
||||
<?php if ($content) : ?>
|
||||
<div class="photo-detail__body">
|
||||
<?php the_content(); ?>
|
||||
<?php
|
||||
// 图片换成可点击版本
|
||||
$content = preg_replace('/<img[^>]+src="([^"]+)"[^>]*>/', '<img src="$1" alt="" onclick="event.stopPropagation(); openPhotoImage(\'' . esc_js('$1') . '\')" />', $content);
|
||||
echo $content;
|
||||
?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
@@ -27,9 +62,8 @@
|
||||
</div>
|
||||
|
||||
<?php
|
||||
// 拾影列表按日期从新到旧,导航遵循同一方向
|
||||
$left = get_adjacent_post(false, '', false); // 更新的(列表左侧)
|
||||
$right = get_adjacent_post(false, '', true); // 更早的(列表右侧)
|
||||
$left = get_adjacent_post(false, '', false);
|
||||
$right = get_adjacent_post(false, '', true);
|
||||
if ($left || $right) : ?>
|
||||
<div class="photo-detail__nav">
|
||||
<?php if ($left) : ?>
|
||||
@@ -45,4 +79,93 @@
|
||||
</div>
|
||||
<?php endwhile; ?>
|
||||
|
||||
<!-- 照片灯箱 — 文章导航内联,不跳页面 -->
|
||||
<div class="photo-lightbox" id="photo-lightbox" onclick="closePhotoLightbox()">
|
||||
<span class="photo-lightbox__brand"><?php bloginfo('name'); ?></span>
|
||||
<span class="photo-lightbox__close" onclick="closePhotoLightbox()">×</span>
|
||||
<span class="photo-lightbox__counter" id="photo-lightbox-counter"></span>
|
||||
<span class="photo-lightbox__nav photo-lightbox__prev" onclick="event.stopPropagation(); navigatePhoto(-1)">‹</span>
|
||||
<span class="photo-lightbox__nav photo-lightbox__next" onclick="event.stopPropagation(); navigatePhoto(1)">›</span>
|
||||
<div onclick="event.stopPropagation()">
|
||||
<div class="photo-lightbox__info" id="photo-lightbox-info"></div>
|
||||
<div class="photo-lightbox__content">
|
||||
<img id="photo-lightbox-img" src="" alt="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="photo-lightbox__postnav" id="photo-lightbox-postnav"></div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
(function() {
|
||||
var detail = document.getElementById('photo-detail');
|
||||
if (!detail) return;
|
||||
var gallery = JSON.parse(detail.getAttribute('data-gallery') || '[]');
|
||||
var lb = document.getElementById('photo-lightbox');
|
||||
var lbImg = document.getElementById('photo-lightbox-img');
|
||||
var lbCounter = document.getElementById('photo-lightbox-counter');
|
||||
var idx = 0;
|
||||
|
||||
window.openPhotoGallery = function(i) {
|
||||
idx = i;
|
||||
show();
|
||||
updateNavButtons();
|
||||
updatePhotoInfo();
|
||||
lb.classList.add('active');
|
||||
document.body.style.overflow = 'hidden';
|
||||
showPostNav();
|
||||
};
|
||||
function updatePhotoInfo() {
|
||||
var info = document.getElementById('photo-lightbox-info');
|
||||
if (!info) return;
|
||||
var title = detail.getAttribute('data-title') || '';
|
||||
var author = detail.getAttribute('data-author') || '';
|
||||
// 提取作者纯文本(去掉 img 标签)
|
||||
var tmp = document.createElement('div');
|
||||
tmp.innerHTML = author;
|
||||
var author_text = tmp.textContent.trim();
|
||||
info.innerHTML = '<span class="photo-lightbox__photo-title">' + title + ' · ' + author_text + '</span>';
|
||||
}
|
||||
window.openPhotoImage = function(url) {
|
||||
var i = gallery.indexOf(url);
|
||||
if (i >= 0) openPhotoGallery(i);
|
||||
else { idx = -1; lbImg.src = url; lbCounter.textContent = ''; lb.classList.add('active'); document.body.style.overflow = 'hidden'; }
|
||||
};
|
||||
window.navigatePhoto = function(d) {
|
||||
idx = (idx + d + gallery.length) % gallery.length;
|
||||
show();
|
||||
};
|
||||
window.closePhotoLightbox = function() {
|
||||
lb.classList.remove('active');
|
||||
document.body.style.overflow = '';
|
||||
};
|
||||
function showPostNav() {
|
||||
var nav = document.querySelector('.photo-detail__nav');
|
||||
var pn = document.getElementById('photo-lightbox-postnav');
|
||||
if (nav && pn) pn.innerHTML = nav.innerHTML;
|
||||
}
|
||||
function show() {
|
||||
lbImg.src = gallery[idx];
|
||||
lbCounter.textContent = gallery.length > 1 ? (idx + 1) + ' / ' + gallery.length : '';
|
||||
updateNavButtons();
|
||||
}
|
||||
function updateNavButtons() {
|
||||
var prev = lb.querySelector('.photo-lightbox__prev');
|
||||
var next = lb.querySelector('.photo-lightbox__next');
|
||||
if (gallery.length <= 1) {
|
||||
prev.style.display = 'none';
|
||||
next.style.display = 'none';
|
||||
} else {
|
||||
prev.style.display = idx > 0 ? '' : 'none';
|
||||
next.style.display = idx < gallery.length - 1 ? '' : 'none';
|
||||
}
|
||||
}
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (!lb.classList.contains('active')) return;
|
||||
if (e.key === 'ArrowLeft') navigatePhoto(-1);
|
||||
if (e.key === 'ArrowRight') navigatePhoto(1);
|
||||
if (e.key === 'Escape') closePhotoLightbox();
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
||||
<?php get_footer(); ?>
|
||||
|
||||
@@ -407,3 +407,84 @@ echo "done"
|
||||
border-top: 2px dashed var(--border);
|
||||
}
|
||||
.photo-detail__meta { border-top: none; padding-top: 0; }
|
||||
|
||||
.photo-detail__body img {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: auto;
|
||||
margin: 20px 0;
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
.photo-detail__body p {
|
||||
margin: 16px 0;
|
||||
text-align: center;
|
||||
font-style: italic;
|
||||
color: var(--ink-light);
|
||||
}
|
||||
|
||||
/* 照片灯箱 */
|
||||
.photo-lightbox {
|
||||
display: none;
|
||||
position: fixed; top: 0; left: 0; width: 100%; height: 100%;
|
||||
background: #000;
|
||||
z-index: 9999;
|
||||
justify-content: center; align-items: center;
|
||||
}
|
||||
.photo-lightbox.active { display: flex; }
|
||||
.photo-lightbox__content { max-width: 90vw; max-height: 90vh; }
|
||||
.photo-lightbox__content img { max-width: 90vw; max-height: 85vh; object-fit: contain; border-radius: var(--radius); }
|
||||
.photo-lightbox__close { position: absolute; top: 24px; right: 36px; font-size: 42px; color: #fff; cursor: pointer; opacity: 0.8; z-index: 2; }
|
||||
.photo-lightbox__close:hover { opacity: 1; }
|
||||
.photo-lightbox__counter { position: absolute; bottom: 30px; left: 50%; transform: translateX(-50%); color: #fff; font-size: 14px; opacity: 0.7; z-index: 2; }
|
||||
.photo-lightbox__nav { position: absolute; top: 50%; transform: translateY(-50%); font-size: 56px; color: #fff; cursor: pointer; user-select: none; padding: 24px; opacity: 0.7; z-index: 2; }
|
||||
.photo-lightbox__nav:hover { opacity: 1; }
|
||||
.photo-lightbox__prev { left: 16px; }
|
||||
.photo-lightbox__next { right: 16px; }
|
||||
|
||||
/* 图片可点击提示 */
|
||||
.photo-detail__image { cursor: zoom-in; }
|
||||
.photo-detail__body img { cursor: zoom-in; }
|
||||
|
||||
|
||||
.photo-lightbox__postnav {
|
||||
position: absolute;
|
||||
bottom: 18px;
|
||||
left: 0; right: 0;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0 40px;
|
||||
z-index: 2;
|
||||
}
|
||||
.photo-lightbox__postnav a {
|
||||
color: rgba(255,255,255,0.6);
|
||||
text-decoration: none;
|
||||
font-size: 14px;
|
||||
}
|
||||
.photo-lightbox__postnav a:hover { color: #fff; }
|
||||
.photo-lightbox__postnav span { color: transparent; }
|
||||
.photo-lightbox__counter { bottom: 60px; }
|
||||
|
||||
.photo-lightbox__brand {
|
||||
position: absolute;
|
||||
top: 24px;
|
||||
left: 36px;
|
||||
color: rgba(255,255,255,0.25);
|
||||
font-size: 16px;
|
||||
letter-spacing: 0.1em;
|
||||
z-index: 2;
|
||||
font-family: "Noto Serif SC", "STSong", "Songti SC", serif;
|
||||
}
|
||||
|
||||
.photo-lightbox__info {
|
||||
text-align: center;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.photo-lightbox__photo-title {
|
||||
color: rgba(255,255,255,0.5);
|
||||
font-size: 15px;
|
||||
font-weight: 400;
|
||||
letter-spacing: 0.04em;
|
||||
}
|
||||
|
||||
|
||||
.photo-lightbox__content img { border-radius: 6px; }
|
||||
|
||||
Reference in New Issue
Block a user