优化导航栏、分享海报等显示效果;优化代码及性能
This commit is contained in:
@@ -2,18 +2,21 @@
|
||||
|
||||
> 基于原作者v1.2.5代码修改
|
||||
|
||||
#### v1.2.5-7补丁
|
||||
#### v1.2.5-8
|
||||
1. 重写作文目录、置顶样式
|
||||
2. 更换(通知书等)域名
|
||||
3. 修复搜索结果无法PJAX跳转(依赖搜索插件v1.7.1-1)
|
||||
4. 修复日记过多时无法搜索(依赖瞬间插件v1.13.1-1,基于源仓库)
|
||||
5. 朋友圈内容支持搜索与跳转(依赖朋友圈插件v1.4.3-5)
|
||||
5. 朋友圈内容支持搜索与跳转;大幅优化性能(依赖朋友圈插件v1.4.3-6)
|
||||
6. 压缩、更换图片
|
||||
7. 模板端全面支持page与tag参数(常驻显示,同步新增向上翻阅功能)
|
||||
8. 取消自动恢复源内容功能
|
||||
9. 前台编辑、发布日记将采用PJAX更新
|
||||
10. 手机端播放器新增进度条
|
||||
11. 清除无效代码
|
||||
11. 抽象重复代码至函数、清理无效代码
|
||||
12. 当前激活的标签将在导航栏中居中显示
|
||||
13. 优化不同宽度下的显示效果
|
||||
14. 重构分享海报布局
|
||||
|
||||
#### v1.2.5-7
|
||||
1. 适配新接口(基于新版API-Python)
|
||||
|
||||
@@ -5599,7 +5599,7 @@ a.m_loop {
|
||||
width: 330px;
|
||||
padding: 5px;
|
||||
border-radius: 5px;
|
||||
min-height: 550px;
|
||||
min-height: 450px;
|
||||
}
|
||||
|
||||
.poster_box .loading_box {
|
||||
|
||||
@@ -218,7 +218,7 @@
|
||||
|
||||
/**
|
||||
* 小屏平板 (<= 960px)
|
||||
* 保持原样
|
||||
* 540-960px 增加手机端底部导航
|
||||
*/
|
||||
@media only screen and (max-width:960px) {
|
||||
|
||||
@@ -276,6 +276,35 @@
|
||||
.top_menu_box {
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
/* 540-960px 也显示手机端底部导航,但不显示发布按钮 */
|
||||
.footer_menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.footer_nav_box {
|
||||
top: 56px;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.footer_nav_box .footer_player {
|
||||
min-height: auto;
|
||||
}
|
||||
|
||||
body.mod_third_s .footer_nav_box .right {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.footer_main {
|
||||
position: relative;
|
||||
padding-bottom: 110px;
|
||||
}
|
||||
|
||||
.footer_menu a.playing-music,
|
||||
.footer_menu a.playing-music i,
|
||||
.footer_menu a.playing-music .title {
|
||||
color: #4CAF50;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -595,6 +595,9 @@ function init_douban_page() {
|
||||
requestList(1, state.type, false, {
|
||||
onSuccess: function () {
|
||||
$this.addClass('active').parent().siblings().children('.cat-link').removeClass('active');
|
||||
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
|
||||
pix.centerCategoryNavActive($this);
|
||||
}
|
||||
|
||||
var currentUrl = new URL(window.location.href);
|
||||
if (!targetTag || targetTag === '全部') {
|
||||
@@ -653,12 +656,18 @@ function init_douban_page() {
|
||||
}).first();
|
||||
if ($matchedTag.length > 0) {
|
||||
$matchedTag.addClass('active').parent().siblings().children('.cat-link').removeClass('active');
|
||||
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
|
||||
pix.centerCategoryNavActive($matchedTag);
|
||||
}
|
||||
state.type = $matchedTag.attr('data-type') || '';
|
||||
} else {
|
||||
state.type = $('.douban_cat_nav .cat-link.active').attr('data-type') || '';
|
||||
}
|
||||
} else {
|
||||
state.type = $('.douban_cat_nav .cat-link.active').attr('data-type') || '';
|
||||
if (window.pix && typeof pix.centerCategoryNavActive === 'function') {
|
||||
pix.centerCategoryNavActive($('.douban_cat_nav .cat-link.active').first());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+320
-352
File diff suppressed because it is too large
Load Diff
@@ -163,6 +163,31 @@ var pix = {
|
||||
|
||||
},
|
||||
|
||||
centerCategoryNavActive: function ($link) {
|
||||
var $activeLink = $link && $link.length ? $link : $('.moment_cat_nav .active, .posts_cat_nav .active, .photos_cat_nav .active, .douban_cat_nav .active, .friends_cat_nav .active').first();
|
||||
if (!$activeLink || !$activeLink.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var navEl = $activeLink.closest('.moment_cat_nav, .posts_cat_nav, .photos_cat_nav, .douban_cat_nav, .friends_cat_nav').find('ul').get(0);
|
||||
if (!navEl) {
|
||||
return;
|
||||
}
|
||||
|
||||
var linkEl = $activeLink.get(0);
|
||||
var maxScrollLeft = navEl.scrollWidth - navEl.clientWidth;
|
||||
if (maxScrollLeft <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var navRect = navEl.getBoundingClientRect();
|
||||
var linkRect = linkEl.getBoundingClientRect();
|
||||
var targetScrollLeft = navEl.scrollLeft + (linkRect.left - navRect.left) - (navRect.width / 2 - linkRect.width / 2);
|
||||
targetScrollLeft = Math.max(0, Math.min(maxScrollLeft, targetScrollLeft));
|
||||
|
||||
$(navEl).stop(true).animate({ scrollLeft: targetScrollLeft }, 220);
|
||||
},
|
||||
|
||||
topCategoriesBarScroll: function () {
|
||||
if (document.getElementById("cat_nav_items")) {
|
||||
let xscroll = document.getElementById("cat_nav_items");
|
||||
|
||||
@@ -361,10 +361,9 @@ function mu_box_show() {
|
||||
function mu_box_hide(time = 2000) {
|
||||
clearTimeout(trigger);
|
||||
trigger = setTimeout(function () {
|
||||
// 获取屏幕宽度判断是否为手机端(与歌词容器响应式逻辑保持一致)
|
||||
const isMobile = $(window).width() <= 767;
|
||||
// 手机端隐藏时额外向下偏移50px(可根据需要调整数值),非手机端保持默认0px
|
||||
const hideTop = isMobile ? "50px" : "0px";
|
||||
const hasBottomMenu = $(window).width() <= 960;
|
||||
// 底部导航可见时,播放器收起到导航栏后面。
|
||||
const hideTop = hasBottomMenu ? "50px" : "0px";
|
||||
|
||||
// 执行隐藏动画
|
||||
$('.footer_nav_box').animate({
|
||||
|
||||
@@ -5,7 +5,7 @@ const poster = (function() {
|
||||
const DEBUG = false
|
||||
|
||||
const WIDTH = 700
|
||||
const HEIGHT = 1160
|
||||
const HEIGHT = 850
|
||||
|
||||
/**
|
||||
* 将图片URL加载为Image对象,并返回Promise
|
||||
@@ -47,9 +47,12 @@ const poster = (function() {
|
||||
const $title = createDom('canvas', 'id', 'title')
|
||||
const $content = createDom('canvas', 'id', 'content')
|
||||
const $logo = createDom('canvas', 'id', 'logo')
|
||||
const $siteName = createDom('canvas', 'id', 'siteName')
|
||||
const $description = createDom('canvas', 'id', 'description')
|
||||
const $customText1 = createDom('canvas', 'id', 'customText1')
|
||||
const $customText2 = createDom('canvas', 'id', 'customText2')
|
||||
|
||||
appendChilds($wrapper, $canvas, $day, $date, $title, $content, $logo, $description)
|
||||
appendChilds($wrapper, $canvas, $day, $siteName, $date, $title, $content, $logo, $description, $customText1, $customText2)
|
||||
$container.appendChild($wrapper)
|
||||
|
||||
const date = new Date()
|
||||
@@ -83,6 +86,58 @@ const poster = (function() {
|
||||
titleStyle.position = (config.titleStyle && config.titleStyle.position) || titleStyle.position
|
||||
drawMoreLines($title, titleStyle, config.title)
|
||||
|
||||
// site name canvas
|
||||
const siteNameStyle = {
|
||||
font: '40px Helvetica',
|
||||
lineHeight: 1.3,
|
||||
color: 'rgba(255, 255, 255, 0.95)',
|
||||
position: 'left'
|
||||
}
|
||||
siteNameStyle.font = (config.siteNameStyle && config.siteNameStyle.font) || siteNameStyle.font
|
||||
siteNameStyle.color = (config.siteNameStyle && config.siteNameStyle.color) || siteNameStyle.color
|
||||
siteNameStyle.lineHeight = (config.siteNameStyle && config.siteNameStyle.lineHeight) || siteNameStyle.lineHeight
|
||||
siteNameStyle.position = (config.siteNameStyle && config.siteNameStyle.position) || siteNameStyle.position
|
||||
drawMoreLines($siteName, siteNameStyle, config.siteName)
|
||||
|
||||
// description canvas
|
||||
const descriptionStyle = {
|
||||
font: '25px Helvetica',
|
||||
color: 'rgba(236, 241, 255, 1)',
|
||||
lineHeight: 1.2,
|
||||
position: 'left'
|
||||
}
|
||||
descriptionStyle.font = (config.descriptionStyle && config.descriptionStyle.font) || descriptionStyle.font
|
||||
descriptionStyle.color = (config.descriptionStyle && config.descriptionStyle.color) || descriptionStyle.color
|
||||
descriptionStyle.lineHeight = (config.descriptionStyle && config.descriptionStyle.lineHeight) || descriptionStyle.lineHeight
|
||||
descriptionStyle.position = (config.descriptionStyle && config.descriptionStyle.position) || descriptionStyle.position
|
||||
drawMoreLines($description, descriptionStyle, config.description)
|
||||
|
||||
// custom text 1 canvas
|
||||
const customText1Style = {
|
||||
font: '28px Helvetica',
|
||||
lineHeight: 1.3,
|
||||
position: 'left',
|
||||
color: 'rgba(0, 0, 0, 1)'
|
||||
}
|
||||
customText1Style.font = (config.customText1Style && config.customText1Style.font) || customText1Style.font
|
||||
customText1Style.color = (config.customText1Style && config.customText1Style.color) || customText1Style.color
|
||||
customText1Style.lineHeight = (config.customText1Style && config.customText1Style.lineHeight) || customText1Style.lineHeight
|
||||
customText1Style.position = (config.customText1Style && config.customText1Style.position) || customText1Style.position
|
||||
drawMoreLines($customText1, customText1Style, config.customText1 || '')
|
||||
|
||||
// custom text 2 canvas
|
||||
const customText2Style = {
|
||||
font: '28px Helvetica',
|
||||
lineHeight: 1.3,
|
||||
position: 'left',
|
||||
color: 'rgba(0, 0, 0, 1)'
|
||||
}
|
||||
customText2Style.font = (config.customText2Style && config.customText2Style.font) || customText2Style.font
|
||||
customText2Style.color = (config.customText2Style && config.customText2Style.color) || customText2Style.color
|
||||
customText2Style.lineHeight = (config.customText2Style && config.customText2Style.lineHeight) || customText2Style.lineHeight
|
||||
customText2Style.position = (config.customText2Style && config.customText2Style.position) || customText2Style.position
|
||||
drawMoreLines($customText2, customText2Style, config.customText2 || '')
|
||||
|
||||
// content canvas
|
||||
const contentStyle = {
|
||||
font: '22px Helvetica',
|
||||
@@ -96,15 +151,6 @@ const poster = (function() {
|
||||
contentStyle.position = (config.contentStyle && config.contentStyle.position) || contentStyle.position
|
||||
drawMoreLines($content, contentStyle, config.content);
|
||||
|
||||
// description canvas
|
||||
const descriptionStyle = {
|
||||
font: '24px Helvetica',
|
||||
color: 'rgba(180, 180, 180, 1)',
|
||||
lineHeight: 1.2,
|
||||
position: 'left'
|
||||
}
|
||||
drawMoreLines($description, descriptionStyle, config.description)
|
||||
|
||||
|
||||
// ------------------ 【修复点 1:使用 Promise.all 等待所有图片加载】 ------------------
|
||||
Promise.all([
|
||||
@@ -126,7 +172,7 @@ const poster = (function() {
|
||||
ctx.drawImage(image, imgRect.sx, imgRect.sy, imgRect.sWidth, imgRect.sHeight, 20, 20, $canvas.width - 40, $canvas.height / 1.2 - 40);
|
||||
|
||||
// 3. 绘制覆盖层
|
||||
ctx.fillStyle="rgba(0, 0, 0, 0.3)";
|
||||
ctx.fillStyle="rgba(0, 0, 0, 0.6)";
|
||||
ctx.fillRect(20, 20, $canvas.width - 40, $canvas.height / 1.2 - 40);
|
||||
|
||||
// 4. 绘制时间 (使用预先绘制好的 Canvas)
|
||||
@@ -134,17 +180,20 @@ const poster = (function() {
|
||||
ctx.drawImage($date, -21, 125)
|
||||
|
||||
// 5. 绘制 Logo
|
||||
var logoh = 60;
|
||||
var logoh = 140;
|
||||
var cwidth = logoh * (logo.width / logo.height);
|
||||
ctx.drawImage(logo, 60, $canvas.height / 1.2 + 30, cwidth, logoh);
|
||||
ctx.drawImage(logo, 20, $canvas.height / 1.2 - 10, cwidth, logoh);
|
||||
|
||||
// 6. 绘制二维码
|
||||
ctx.drawImage(qrcode, $canvas.width - 160, $canvas.height / 1.2 + 20, 120, 120);
|
||||
ctx.drawImage(qrcode, $canvas.width - 150, $canvas.height / 1.2 + 10, 120, 120);
|
||||
|
||||
// 7. 绘制文字 (使用预先绘制好的 Canvas)
|
||||
ctx.drawImage($title, 20, $canvas.height / 2 + 20)
|
||||
ctx.drawImage($siteName, 10, 60)
|
||||
ctx.drawImage($description, 10, 120)
|
||||
ctx.drawImage($customText1, 270, $canvas.height / 2 + 310)
|
||||
ctx.drawImage($customText2, 215, $canvas.height / 2 + 360)
|
||||
ctx.drawImage($title, 20, $canvas.height / 2 + 60)
|
||||
ctx.drawImage($content, 20, $canvas.height / 2 + 120)
|
||||
ctx.drawImage($description, 20, $canvas.height / 1.2 + 110)
|
||||
ctx.strokeStyle = 'rgba(122, 122, 122, 0.5)';
|
||||
|
||||
// 8. 转换并显示最终图片
|
||||
@@ -204,19 +253,14 @@ const poster = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// 覆盖函数(不变)
|
||||
// 覆盖函数:按目标区域等比缩放并居中裁切,尽量不留白
|
||||
function coverImg(box_w, box_h, source_w, source_h) {
|
||||
var sx = 0,
|
||||
sy = 0,
|
||||
sWidth = source_w,
|
||||
sHeight = source_h;
|
||||
if (source_w > source_h || (source_w == source_h && box_w < box_h)) {
|
||||
sWidth = box_w * sHeight / box_h;
|
||||
sx = (source_w - sWidth) / 2;
|
||||
} else if (source_w < source_h || (source_w == source_h && box_w > box_h)) {
|
||||
sHeight = box_h * sWidth / box_w;
|
||||
sY = (source_h - sHeight) / 2;
|
||||
}
|
||||
const scale = Math.max(box_w / source_w, box_h / source_h);
|
||||
const sWidth = box_w / scale;
|
||||
const sHeight = box_h / scale;
|
||||
const sx = (source_w - sWidth) / 2;
|
||||
const sy = (source_h - sHeight) / 2;
|
||||
|
||||
return {
|
||||
sx,
|
||||
sy,
|
||||
@@ -397,7 +441,8 @@ $('body').on('click', '.cr_poster', function () {
|
||||
var content = content_element.innerText;
|
||||
var content_length = content.length;
|
||||
var permalink = t_content.length > 0 ? window.location.origin + '/moments/' + post_id : window.location.origin + window.location.pathname;
|
||||
var title = t_content.length > 0 ? Theme.site_title + '-瞬间' : document.title;
|
||||
var title = t_content.length > 0 ? '瞬间' : (document.title || '').split(' - ')[0];
|
||||
var siteName = Theme.site_title;
|
||||
|
||||
// 确保 QRious 库可用
|
||||
if (typeof QRious === 'undefined') {
|
||||
@@ -430,7 +475,7 @@ $('body').on('click', '.cr_poster', function () {
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
if (content_length > 120) {
|
||||
content = content.substring(0, 80) + '...'
|
||||
content = content.substring(0, 82) + '...'
|
||||
}
|
||||
|
||||
// 海报生成回调
|
||||
@@ -456,10 +501,21 @@ $('body').on('click', '.cr_poster', function () {
|
||||
selector: modal + ' .poster_box',
|
||||
container: $posterBox[0],
|
||||
title: title,
|
||||
siteName: siteName,
|
||||
description: Theme.admin_des,
|
||||
content: content,
|
||||
logo: Theme.site_logo,
|
||||
qrcode: $('#twoCode').attr('src'),
|
||||
description: Theme.admin_des,
|
||||
customText1: '扫描右侧二维码',
|
||||
customText2: '或访问:https://anian.net',
|
||||
customText1Style: {
|
||||
font: '24px Helvetica',
|
||||
color: 'rgba(0, 0, 0, 1)'
|
||||
},
|
||||
customText2Style: {
|
||||
font: '24px Helvetica',
|
||||
color: 'rgba(0, 0, 0, 1)'
|
||||
},
|
||||
callback: Posterdown
|
||||
});
|
||||
});
|
||||
|
||||
+9
-16
@@ -9,9 +9,8 @@
|
||||
<th:block th:replace="~{modules/header}" />
|
||||
|
||||
<div id="pjax-container" th:with="
|
||||
page = ${#lists.isEmpty(param.page) ? 1 : param.page[0]},
|
||||
tag = ${#lists.isEmpty(param.tag) ? null : param.tag[0]},
|
||||
friendPage = ${#strings.isEmpty(tag) ? (#lists.isEmpty(param.page) ? friends : friendFinder.list(page, friends.size)) : friendFinder.list({'page': page, 'size': friends.size, 'author': tag})}
|
||||
selectedTag = ${#lists.isEmpty(param.tag) ? null : param.tag[0]},
|
||||
friendPage = ${friends}
|
||||
">
|
||||
|
||||
<div class="blog_list">
|
||||
@@ -23,16 +22,16 @@
|
||||
<li>
|
||||
<!-- 全部按钮 -->
|
||||
<a th:attr="data-href=@{/friends}"
|
||||
th:classappend="${#strings.isEmpty(tag) ? 'active' : ''}" class="cat-link">
|
||||
th:classappend="${#strings.isEmpty(selectedTag) ? 'active' : ''}" class="cat-link">
|
||||
全部<span></span>
|
||||
</a>
|
||||
</li>
|
||||
<!-- 遍历所有作者 -->
|
||||
<th:block th:each="author : ${authors}">
|
||||
<th:block th:each="authorLink : ${authors}">
|
||||
<li>
|
||||
<a th:attr="data-href=@{/friends(tag=${author})}"
|
||||
th:classappend="${#strings.equals(tag, author) ? 'active' : ''}"
|
||||
th:text="${author}" class="cat-link">
|
||||
<a th:attr="data-href=@{/friends(tag=${authorLink.spec.displayName})}"
|
||||
th:classappend="${#strings.equals(selectedTag, authorLink.spec.displayName) ? 'active' : ''}"
|
||||
th:text="${authorLink.spec.displayName}" class="cat-link">
|
||||
<span></span>
|
||||
</a>
|
||||
</li>
|
||||
@@ -115,14 +114,8 @@
|
||||
<!-- 分页:必须保持在 blog_list_inner 里面 -->
|
||||
<th:block th:if="${friendPage.totalPages>1}">
|
||||
<div id="t_pagination">
|
||||
<div class="post-paging" th:if="${friendPage.hasNext()}"
|
||||
th:with="_page = ${friendPage.page+1}">
|
||||
<a th:if="${#strings.isEmpty(tag)}"
|
||||
th:data="@{/friends(page=${_page})}"
|
||||
th:text="${theme.config.base_set.site_page}">
|
||||
</a>
|
||||
<a th:unless="${#strings.isEmpty(tag)}"
|
||||
th:data="@{/friends(tag=${tag},page=${_page})}"
|
||||
<div class="post-paging" th:if="${friendPage.hasNext()}">
|
||||
<a th:data="${friendPage.nextUrl}"
|
||||
th:text="${theme.config.base_set.site_page}">
|
||||
</a>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<th:block th:fragment="footer">
|
||||
<th:block th:with="customJsVersion='1.2.5-7-TYIL'">
|
||||
<th:block th:with="customJsVersion='1.2.5-8'">
|
||||
|
||||
<!-- 奇遇容器 -->
|
||||
<div class="center-img-container" id="centerImgContainer">
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<th:block th:fragment="head" th:with="customJsVersion=${'1.2.5-7-DFQP'}">
|
||||
<th:block th:fragment="head" th:with="customJsVersion=${'1.2.5-8'}">
|
||||
<th:block th:replace="~{'modules/variables/msg'}" />
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1.0,minimum-scale=1.0,user-scalable=no">
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<i class="ri-play-list-line"></i>
|
||||
</a>
|
||||
</div>
|
||||
<div th:if="${theme.config.style.theme_set != 'dark-theme'}" class="t_dark top_tool icon_color"><a><i class="ri-contrast-2-line"></i></a></div>
|
||||
<!-- <div th:if="${theme.config.style.theme_set != 'dark-theme'}" class="t_dark top_tool icon_color"><a><i class="ri-contrast-2-line"></i></a></div> -->
|
||||
</div>
|
||||
<a class="go_top" href="#page" uk-scroll=""><i class="ri-arrow-up-s-line"></i></a>
|
||||
</div>
|
||||
|
||||
+1
-1
@@ -17,7 +17,7 @@ spec:
|
||||
issues: "https://github.com/chengzhongxue/halo-theme-pix/issues"
|
||||
settingName: "theme-pix-setting"
|
||||
configMapName: "theme-pix-configMap"
|
||||
version: "1.2.5-7"
|
||||
version: "1.2.5-8"
|
||||
require: ">=2.20.0"
|
||||
customTemplates:
|
||||
page:
|
||||
|
||||
Reference in New Issue
Block a user