侧边栏
公告欢迎卡片
- 修改主题配置文件,引入 jquery、welcome.js
yml
inject:
head:
- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
bottom:
- <script src="https://blog.xdog.run/js/welcome.js"></script>
- 修改主题配置文件,开启公告侧边栏
yml
aside:
card_announcement:
enable: true
content: '<div id="welcome-info"></div>'
welcome.js 代码备份
js
js
/**
* @Author: 糖丸
* @Date: 2023-06-18 16:18:51
* @LastEditTime: 2023-07-27 12:33:20
* @FilePath: \theme\source\js\welcome.js
* @Tips: 纵使前路黑暗,也有可以照亮你的星光,而你自身就是光!
*/
//get请求
$.ajax({
type: 'get',
url: 'https://apis.map.qq.com/ws/location/v1/ip',
data: {
key: 'PV3BZ-HMSCT-UW6XY-VBKAB-6PV5E-7UFSX',
output: 'jsonp',
},
dataType: 'jsonp',
success: function (res) {
// ipLocation = ipToNumber(res);
ipLocation = res;
}
})
// function ipToNumber(ip) {
// var numbers = ip.split(".");
// return parseInt(numbers[0])*256*256*256 +
// parseInt(numbers[1])*256*256 +
// parseInt(numbers[2])*256 +
// parseInt(numbers[3]);
// }
// function numberToIp(number) {
// return (Math.floor(number/(256*256*256))) + "." +
// (Math.floor(number%(256*256*256)/(256*256))) + "." +
// (Math.floor(number%(256*256)/256)) + "." +
// (Math.floor(number%256));
// }
function getDistance(e1, n1, e2, n2) {
const R = 6371
const { sin, cos, asin, PI, hypot } = Math
let getPoint = (e, n) => {
e *= PI / 180
n *= PI / 180
return { x: cos(n) * cos(e), y: cos(n) * sin(e), z: sin(n) }
}
let a = getPoint(e1, n1)
let b = getPoint(e2, n2)
let c = hypot(a.x - b.x, a.y - b.y, a.z - b.z)
let r = asin(c / 2) * 2 * R
return Math.round(r);
}
function showWelcome() {
// 针对 pjax 的优化,防止在非公告页面也执行下面代码
if(document.getElementById("welcome-info") === null){return;}
let dist = getDistance(30.313172,120.382477, ipLocation.result.location.lng, ipLocation.result.location.lat); //这里记得换成自己的经纬度
let pos = ipLocation.result.ad_info.nation;
let ip;
let posdesc;
//根据国家、省份、城市信息自定义欢迎语
switch (ipLocation.result.ad_info.nation) {
case "日本":
posdesc = "よろしく,一起去看樱花吗";
break;
case "美国":
posdesc = "Let us live in peace!";
break;
case "英国":
posdesc = "想同你一起夜乘伦敦眼";
break;
case "俄罗斯":
posdesc = "干了这瓶伏特加!";
break;
case "法国":
posdesc = "C'est La Vie";
break;
case "德国":
posdesc = "Die Zeit verging im Fluge.";
break;
case "澳大利亚":
posdesc = "一起去大堡礁吧!";
break;
case "加拿大":
posdesc = "拾起一片枫叶赠予你";
break;
case "中国":
pos = ipLocation.result.ad_info.province + " " + ipLocation.result.ad_info.city + " " + ipLocation.result.ad_info.district;
ip = ipLocation.result.ip;
switch (ipLocation.result.ad_info.province) {
case "北京市":
posdesc = "北——京——欢迎你~~~";
break;
case "天津市":
posdesc = "讲段相声吧";
break;
case "河北省":
posdesc = "山势巍巍成壁垒,天下雄关铁马金戈由此向,无限江山";
break;
case "山西省":
posdesc = "展开坐具长三尺,已占山河五百余";
break;
case "内蒙古自治区":
posdesc = "天苍苍,野茫茫,风吹草低见牛羊";
break;
case "辽宁省":
posdesc = "我想吃烤鸡架!";
break;
case "吉林省":
posdesc = "状元阁就是东北烧烤之王";
break;
case "黑龙江省":
posdesc = "很喜欢哈尔滨大剧院";
break;
case "上海市":
posdesc = "众所周知,中国只有两个城市";
break;
case "江苏省":
switch (ipLocation.result.ad_info.city) {
case "南京市":
posdesc = "这是我挺想去的城市啦";
break;
case "苏州市":
posdesc = "上有天堂,下有苏杭";
break;
default:
posdesc = "散装是必须要散装的";
break;
}
break;
case "浙江省":
posdesc = "东风渐绿西湖柳,雁已还人未南归!博主家乡~ 欢迎来玩~";
break;
case "河南省":
switch (ipLocation.result.ad_info.city) {
case "郑州市":
posdesc = "豫州之域,天地之中";
break;
case "南阳市":
posdesc = "臣本布衣,躬耕于南阳此南阳非彼南阳!";
break;
case "驻马店市":
posdesc = "峰峰有奇石,石石挟仙气嵖岈山的花很美哦!";
break;
case "开封市":
posdesc = "刚正不阿包青天";
break;
case "洛阳市":
posdesc = "洛阳牡丹甲天下";
break;
default:
posdesc = "可否带我品尝河南烩面啦?";
break;
}
break;
case "安徽省":
switch (ipLocation.result.ad_info.city) {
case "合肥市":
posdesc = "一座让你“乐不思蜀”的城市!";
break;
case "安庆市":
switch (ipLocation.result.ad_info.district) {
case "潜山市":
posdesc = "我在天柱山很想你😘";
break;
}
break;
default:
posdesc = "千里轻帆外,层层见水楼";
break;
}
break;
case "福建省":
posdesc = "井邑白云间,岩城远带山";
break;
case "江西省":
posdesc = "落霞与孤鹜齐飞,秋水共长天一色";
break;
case "山东省":
posdesc = "遥望齐州九点烟,一泓海水杯中泻";
break;
case "湖北省":
switch (ipLocation.result.ad_info.city) {
case "黄冈市":
posdesc = "红安将军县!辈出将才!";
break;
default:
posdesc = "来碗热干面~";
break;
}
break;
case "湖南省":
posdesc = "74751,长沙斯塔克";
break;
case "广东省":
switch (ipLocation.result.ad_info.city) {
case "广州市":
posdesc = "看小蛮腰,喝早茶了嘛~";
break;
case "深圳市":
posdesc = "今天你逛商场了嘛~";
break;
case "阳江市":
posdesc = "阳春合水!";
break;
default:
posdesc = "来两斤福建人~";
break;
}
break;
case "广西壮族自治区":
posdesc = "桂林山水甲天下";
break;
case "海南省":
posdesc = "朝观日出逐白浪,夕看云起收霞光";
break;
case "四川省":
posdesc = "康康川妹子";
break;
case "贵州省":
posdesc = "茅台,学生,再塞200";
break;
case "云南省":
posdesc = "玉龙飞舞云缠绕,万仞冰川直耸天";
break;
case "西藏自治区":
posdesc = "躺在茫茫草原上,仰望蓝天";
break;
case "陕西省":
posdesc = "来份臊子面加馍";
break;
case "甘肃省":
posdesc = "羌笛何须怨杨柳,春风不度玉门关";
break;
case "青海省":
posdesc = "牛肉干和老酸奶都好好吃";
break;
case "宁夏回族自治区":
posdesc = "大漠孤烟直,长河落日圆";
break;
case "新疆维吾尔自治区":
posdesc = "驼铃古道丝绸路,胡马犹闻唐汉风";
break;
case "台湾省":
posdesc = "我在这头,大陆在那头";
break;
case "香港特别行政区":
posdesc = "永定贼有残留地鬼嚎,迎击光非岁玉";
break;
case "澳门特别行政区":
posdesc = "性感荷官,在线发牌";
break;
default:
posdesc = "带我去你的城市逛逛吧!";
break;
}
break;
default:
posdesc = "带我去你的国家逛逛吧";
break;
}
//根据本地时间切换欢迎语
let timeChange;
let date = new Date();
if (date.getHours() >= 5 && date.getHours() < 11) timeChange = "<span>🌤️ 早上好,一日之计在于晨</span>";
else if (date.getHours() >= 11 && date.getHours() < 13) timeChange = "<span>☀️ 中午好,记得午休喔~</span>";
else if (date.getHours() >= 13 && date.getHours() < 17) timeChange = "<span>🕞 下午好,饮茶先啦!</span>";
else if (date.getHours() >= 17 && date.getHours() < 19) timeChange = "<span>🚶♂️ 即将下班,记得按时吃饭~</span>";
else if (date.getHours() >= 19 && date.getHours() < 24) timeChange = "<span>🌙 晚上好,夜生活嗨起来!</span>";
else timeChange = "夜深了,早点休息,少熬夜";
try {
//自定义文本和需要放的位置
document.getElementById("welcome-info").innerHTML =
`欢迎来自<br><span style="font-size: 12px;"><b><span style="color: #49B1F5;">${pos}</span></b> 的小友💖</span><br><span style="font-size: 12px;">当前位置距博主约 <b><span style="color: #49B1F5;">${dist}</span></b> 公里!<br>您的IP地址为: <b><span>${ip}</span></b><br>${timeChange} <br></span>`;
// `欢迎来自<br><b><span style="color: var(--kouseki-ip-color);font-size: var(--kouseki-gl-size);">${pos}</span></b> 的小友💖<br><span style="font-size: 12px;"> ${posdesc}🍂</span><br>当前位置距博主约 <b><span style="color: var(--kouseki-ip-color);">${dist}</span></b> 公里!<br>您的IP地址为: <b><span>${ip}</span></b><br>${timeChange} <br>`;
} catch (err) {
console.log("Pjax无法获取元素")
}
}
window.onload = showWelcome;
// 如果使用了pjax在加上下面这行代码
document.addEventListener('pjax:complete', showWelcome);
如腾讯地图key额度用完自行申请:https://lbs.qq.com/service/webService/webServiceGuide/position/webServiceIp
注意:有一个小问题,ajax请求的 第三方 cookie 会导致浏览器控制台出现三个
Third-party cookie will be blocked. Learn more in the Issues tab.
提示,在浏览器设置阻止第三方cookie即可
彩色标签云
自带的彩色标签云太丑了,以前就觉得typecho的那种很好看,直接拿来!
- 修改
themes\butterfly\scripts\helpers\page.js
diff
hexo.extend.helper.register('cloudTags', function (options = {}) {
const env = this
let { source, minfontsize, maxfontsize, limit, unit = 'px', orderby, order } = options
+ source = source.sort('length').reverse() //标签从大到小排序
if (limit > 0) {
source = source.limit(limit)
}
const sizes = [...new Set(source.map(tag => tag.length).sort((a, b) => a - b))]
- const getRandomColor = () => {
- const randomColor = () => Math.floor(Math.random() * 201)
- const r = randomColor()
- const g = randomColor()
- const b = randomColor()
- return `rgb(${Math.max(r, 50)}, ${Math.max(g, 50)}, ${Math.max(b, 50)})`
- }
+ const getRandomColor = () => {
+ const colors = [
+ 'rgb(66, 139, 202)', // 蓝色
+ 'rgb(236, 169, 167)', // 粉色
+ 'rgb(218, 153, 255)', // 紫色
+ 'rgb(174, 220, 174)', // 绿色
+ 'rgb(217, 185, 153)', // 棕色
+ 'rgb(255, 179, 128)' // 黄色
+ ];
+ return colors[Math.floor(Math.random() * colors.length)]
+ }
const generateStyle = (size, unit) =>
- `font-size: ${parseFloat(size.toFixed(2)) + unit}; color: ${getRandomColor()};`
+ `font-size: ${parseFloat(size.toFixed(2)) + unit}; margin: 2px 2px;color: white;border-radius: 10px;background-color: ${getRandomColor()};`
const length = sizes.length - 1
const result = source.sort(orderby, order).map(tag => {
const ratio = length ? sizes.indexOf(tag.length) / length : 0
const size = minfontsize + ((maxfontsize - minfontsize) * ratio)
const style = generateStyle(size, unit)
- return `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}</a>`
+ return `<a href="${env.url_for(tag.path)}" style="${style}">${tag.name}<sup>${tag.length}</sup></a>` //添加标签数量角标
}).join('')
return result
})
- 去除侧边栏彩色标签字体大小变化,修改
themes\butterfly\layout\includes\widget\card_tags.pug
diff
if theme.aside.card_tags.color
- .card-tag-cloud!= cloudTags({source: site.tags, orderby: orderby, order: order, minfontsize: 1.15, maxfontsize: 1.45, limit: limit, unit: 'em'})
+ .card-tag-cloud!= cloudTags({source: site.tags, orderby: orderby, order: order, minfontsize: 0.9, maxfontsize: 1.1, limit: limit, unit: 'em'})
else
.card-tag-cloud!= tagcloud({orderby: orderby, order: order, min_font: 1.1, max_font: 1.5, amount: limit , color: true, start_color: '#999', end_color: '#99a9bf', unit: 'em'})
- CSS
css
#aside-content .card-tag-cloud a {
font-weight: 600;
}
#aside-content .card-tag-cloud a:hover {
color: #fff !important;
transform: translateY(-2px);
background-color: var(--btn-hover-color) !important;
}
- 最后在主题配置里开启侧边栏标签颜色即可
yml
aside:
card_tags:
color: true
移动端侧边栏增加标签云
- 修改
themes\butterfly\layout\includes\sidebar.pug
,替换为以下内容
diff
hr.custom-hr
!=partial('includes/header/menu_item', {}, {cache: true})
+ if theme.aside.card_tags.enable
+ if site.tags.length
+ .card-widget.card-tags
+ span= _p('aside.card_tags')
+
+ - let { limit, orderby, order } = theme.aside.card_tags
+ - limit = limit === 0 ? 0 : limit || 40
+
+ if theme.aside.card_tags.color
+ .card-tag-cloud!= cloudTags({source: site.tags, orderby: orderby, order: order, minfontsize: 0.9, maxfontsize: 1.1, limit: limit, unit: 'em'})
+ else
+ .card-tag-cloud!= tagcloud({orderby: orderby, order: order, min_font: 1.1, max_font: 1.5, amount: limit , color: true, start_color: '#999', end_color: '#99a9bf', unit: 'em'})
- css
css
#sidebar #sidebar-menus .card-tag-cloud {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 20px;
}
#sidebar #sidebar-menus .card-tag-cloud a {
padding: 0 4px;
}
微信公众号引流卡片
- 新建文件
source\_data\widget.yml
yml
bottom:
- class_name: wechat-widget
id_name: card-wechat
name:
icon:
order: 1
html: '
<div id="flip-wrapper">
<div id="flip-content">
<div class="face"
style="background:url(https://cdn.xdog.top/site/face.png) center center/100% no-repeat">
</div>
<div class="back face"
style="background:url(https://cdn.xdog.top/site/back_face.png) center center/100% no-repeat">
</div>
</div>
</div>
'
- CSS
CSS
css
#aside-content .card-widget#card-wechat {
background: #57bd6a;
display: flex;
justify-content: center;
align-content: center;
padding: 0;
cursor: pointer;
border: none;
height: 110px;
}
#flip-wrapper {
position: relative;
width: 235px;
height: 110px;
z-index: 1;
}
#flip-content {
width: 100%;
height: 100%;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
transition: cubic-bezier(0,0,0,1.29) .3s;
}
#aside-content #flip-wrapper #flip-content .face {
position: absolute;
width: 100%;
height: 100%;
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
background-size: 100%;
}
#aside-content #flip-wrapper #flip-content .back.face {
display: block;
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
box-sizing: border-box;
background-size: 100%;
}
#flip-wrapper:hover #flip-content {
-webkit-transform: rotateY(180deg);
transform: rotateY(180deg);
}
人生倒计时侧边栏
- 修改主题配置文件,引入 jquery
yml
inject:
head:
- <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
bottom:
- 新建文件
source\_data\widget.yml
yml
bottom:
- class_name: aside aside-count
id_name:
name: 人生倒计时
icon: fas fa-hourglass-half
order: 1
html: '<div class="content">
<div class="item" id="dayProgress">
<div class="title">今日已经过去<span></span>小时</div>
<div class="progress">
<div class="progress-bar">
<div class="progress-inner progress-inner-1"></div>
</div>
<div class="progress-percentage"></div>
</div>
</div>
<div class="item" id="weekProgress">
<div class="title">这周已经过去<span></span>天</div>
<div class="progress">
<div class="progress-bar">
<div class="progress-inner progress-inner-2"></div>
</div>
<div class="progress-percentage"></div>
</div>
</div>
<div class="item" id="monthProgress">
<div class="title">本月已经过去<span></span>天</div>
<div class="progress">
<div class="progress-bar">
<div class="progress-inner progress-inner-3"></div>
</div>
<div class="progress-percentage"></div>
</div>
</div>
<div class="item" id="yearProgress">
<div class="title">今年已经过去<span></span>个月</div>
<div class="progress">
<div class="progress-bar">
<div class="progress-inner progress-inner-4"></div>
</div>
<div class="progress-percentage"></div>
</div>
</div>
</div>'
- css
CSS
CSS
/*人生倒计时侧边栏*/
.aside-count .content .item {
margin-bottom: 5px;
line-height: initial;
}
.aside-count .content .item:last-child {
margin-bottom: 0
}
.aside-count .content .item .title {
font-size: 12px;
color: var(--minor);
display: flex;
align-items: center
}
.aside-count .content .item .title span {
color: var(--theme);
font-weight: 500;
font-size: 14px;
margin: 0 5px
}
.aside-count .content .item .progress {
display: flex;
align-items: center
}
.aside-count .content .item .progress .progress-bar {
height: 10px;
border-radius: 5px;
overflow: hidden;
background: var(--classC);
width: 0;
min-width: 0;
flex: 1;
margin-right: 5px
}
@keyframes progress {
0% {
background-position: 0 0
}
100% {
background-position: 30px 0
}
}
.aside-count .content .item .progress .progress-bar .progress-inner {
width: 0;
height: 100%;
border-radius: 5px;
transition: width 0.35s;
-webkit-animation: progress 750ms linear infinite;
animation: progress 750ms linear infinite
}
.aside-count .content .item .progress .progress-bar .progress-inner-1 {
background: #bde6ff;
background-image: linear-gradient(135deg, #50bfff 25%, transparent 25%, transparent 50%, #50bfff 50%, #50bfff 75%, transparent 75%, transparent 100%);
background-size: 30px 30px
}
.aside-count .content .item .progress .progress-bar .progress-inner-2 {
background: #ffd980;
background-image: linear-gradient(135deg, #f7ba2a 25%, transparent 25%, transparent 50%, #f7ba2a 50%, #f7ba2a 75%, transparent 75%, transparent 100%);
background-size: 30px 30px
}
.aside-count .content .item .progress .progress-bar .progress-inner-3 {
background: #ffa9a9;
background-image: linear-gradient(135deg, #ff4949 25%, transparent 25%, transparent 50%, #ff4949 50%, #ff4949 75%, transparent 75%, transparent 100%);
background-size: 30px 30px
}
.aside-count .content .item .progress .progress-bar .progress-inner-4 {
background: #67c23a;
background-image: linear-gradient(135deg, #4f9e28 25%, transparent 25%, transparent 50%, #4f9e28 50%, #4f9e28 75%, transparent 75%, transparent 100%);
background-size: 30px 30px
}
- js
JS
js
/*人生倒计时侧边栏*/
function init_life_time() {
if (document.querySelector('.aside-count') == null) { return; }
function getAsideLifeTime() {
let nowDate = +new Date();
let todayStartDate = new Date(new Date().toLocaleDateString()).getTime();
let todayPassHours = (nowDate - todayStartDate) / 1000 / 60 / 60;
let todayPassHoursPercent = (todayPassHours / 24) * 100;
$('#dayProgress .title span').html(parseInt(todayPassHours));
$('#dayProgress .progress .progress-inner').css('width', parseInt(todayPassHoursPercent) + '%');
$('#dayProgress .progress .progress-percentage').html(parseInt(todayPassHoursPercent) + '%');
let weeks = {
0: 7,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
6: 6
};
let weekDay = weeks[new Date().getDay()];
let weekDayPassPercent = (weekDay / 7) * 100;
$('#weekProgress .title span').html(weekDay);
$('#weekProgress .progress .progress-inner').css('width', parseInt(weekDayPassPercent) + '%');
$('#weekProgress .progress .progress-percentage').html(parseInt(weekDayPassPercent) + '%');
let year = new Date().getFullYear();
let date = new Date().getDate();
let month = new Date().getMonth() + 1;
let monthAll = new Date(year, month, 0).getDate();
let monthPassPercent = (date / monthAll) * 100;
$('#monthProgress .title span').html(date);
$('#monthProgress .progress .progress-inner').css('width', parseInt(monthPassPercent) + '%');
$('#monthProgress .progress .progress-percentage').html(parseInt(monthPassPercent) + '%');
let yearPass = (month / 12) * 100;
$('#yearProgress .title span').html(month);
$('#yearProgress .progress .progress-inner').css('width', parseInt(yearPass) + '%');
$('#yearProgress .progress .progress-percentage').html(parseInt(yearPass) + '%');
}
getAsideLifeTime();
setInterval(() => {
getAsideLifeTime();
}, 1000);
}
init_life_time()