记录效果

定位 API 服务
市面上有太多免费的 API 接口服务了,笔者测试了很多不同服务商的,当然也包括腾讯、高德、百度这些大厂,总结来说大厂的东西确实更好用,但作为个人开发者每天有限额,比如腾讯的地图服务大概是每天 6000 次的调用量,当然这个量级对于一个博客站来说已经完全够用了,但是配置过于复杂。经过三番比较,笔者最终选择了 Nice 猫,只能说这大概是笔者见过的最稳定最好用的 API 服务商之一。
注册并获取 API Key
打开 Nice 猫,注册并登录,随后在密钥管理中找您的API KEY 密钥同时根据需要配置安全校验方式 ,建议配置。

访客信息侧边栏源码
<style>
/* 居中对齐样式 */
.align-center {
text-align: center
}
/* 字体颜色样式 - 天蓝色 */
.font-color {
color: deepskyblue
}
/* IP地址遮罩样式
.ip-mask {
cursor: pointer;
/* 鼠标悬停时显示手型光标 */
user-select: none;
/* 禁止用户选择文本 */
transition: all .3s ease;
/* 添加过渡动画效果 */
filter: blur(4px)
/* 默认模糊效果 */
}
*/
/* IP地址遮罩悬停效果 */
.ip-mask:hover {
filter: none
/* 悬停时取消模糊效果 */
}
</style>
<!-- 欢迎信息区域 -->
<div id="welcomeMessage" class="align-center" style="margin-top:13px">
<p>🌍 小伙伴你好呀! 🌍</p>
<p>正在寻找你的足迹...</p>
</div>
<hr />
<script>
/**
* 根据当前时间获取问候语和建议
* @returns {Object} 包含问候语(greeting)和建议(advice)的对象
*/
function getGreetingAndAdvice() {
const hour = new Date().getHours(); // 获取当前小时数
// 根据不同时间段返回相应的问候语和建议
if (hour < 6) {
return {
greeting: "🌛 深夜好呀 👋",
advice: "🌙不要熬夜 早点休息啦🌙"
}
}
else if (hour < 11) {
return {
greeting: "🌞 早上好呀 👋",
advice: "💪新的一天 充满活力💪"
}
}
else if (hour < 13) {
return {
greeting: "🍽️ 中午好呀 👋",
advice: "🍔别忘了享受一顿美味的午餐🍔"
}
}
else if (hour < 18) {
return {
greeting: "☕ 下午好呀 👋",
advice: "🍵休息一下 喝杯咖啡吧🍵"
}
}
else if (hour < 22) {
return {
greeting: "🌜 晚上好呀 👋",
advice: "🌃放松心情 享受夜晚的宁静🌃"
}
}
else {
return {
greeting: "🌛 深夜好呀 👋",
advice: "🌙不要熬夜 早点休息啦🌙"
}
}
}
/**
* 角度转弧度函数
* @param {number} degrees - 角度值
* @returns {number} 弧度值
*/
function toRadians(degrees) {
return degrees * (Math.PI / 180)
}
/**
* 计算两点间距离(Haversine公式)
* @param {number} lat - 纬度
* @param {number} lng - 经度
* @returns {string} 格式化后的距离(公里)
*/
function calculateDistance(lat, lng) {
const R = 6371; // 地球半径(公里)103.88,36.05
const customLat = 36.05; // 自定义纬度(站点位置)
const customLng = 103.87; // 自定义经度(站点位置)
// 计算经纬度差值并转换为弧度
const dLat = toRadians(lat - customLat);
const dLon = toRadians(lng - customLng);
// Haversine公式计算距离
const a = Math.sin(dLat / 2) ** 2 +
Math.cos(toRadians(customLat)) *
Math.cos(toRadians(lat)) *
Math.sin(dLon / 2) ** 2;
const c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
return (R * c).toFixed(2) // 返回格式化后的距离
}
/**
* 获取用户地理位置信息
* @returns {Promise<Object|null>} 用户位置信息对象或null
*/
async function fetchLocation() {
// API配置数组
const apis = [{
url: "https://api.nsmao.net/api/ip/query?key=tgnAG80e07EhQFVQXX1uFTLL37", provinceField: "prov" // 省份字段名
},
{
url: "https://api.nsmao.net/api/ipip/query?key=tgnAG80e07EhQF",
provinceField: "province" // 省份字段名
}
];
// 遍历API尝试获取位置信息
for (const api of apis) {
try {
const res = await fetch(api.url); // 发起请求
const { code, data } = await res.json(); // 解析响应
if (code === 200) { // 请求成功
return {
ip: data.ip, // IP地址
country: data.country, // 国家
province: data[api.provinceField], // 省份
city: data.city, // 城市
district: data.district, // 区县
adcode: data.adcode, // 行政区划代码
length: calculateDistance(data.lat, data.lng) // 距离
}
}
}
catch (e) {
console.error(`获取地理位置失败 (${api.url}):`, e);
continue // 出错继续下一个API
}
}
return null // 所有API都失败返回null
}
/**
* 渲染欢迎信息
* @param {Object} location - 位置信息对象
*/
function renderWelcomeMessage(location) {
const { greeting, advice } = getGreetingAndAdvice(); // 获取问候语
let locationHtml = ""; // 构建位置HTML字符串
// 按优先级拼接位置信息
if (location.province) {
locationHtml += `<strong class="font-color">${location.province} </strong>`
}
if (location.city) {
locationHtml += `<strong class="font-color">${location.city} </strong>`
}
if (location.district) {
locationHtml += `<strong class="font-color">${location.district}</strong>`
}
// 更新欢迎信息内容
document.getElementById("welcomeMessage").innerHTML =
`<p class="align-center"><strong>${greeting}</strong></p>` +
`<p>欢迎来自 ${locationHtml} 的小伙伴!</p>` +
`<p class="align-center">${advice}</p>` +
`<p class="align-center">🌍 您当前的 IP 是<strong><span class="ip-mask font-color">${location.ip}</span></strong> 🌍</p>` +
`<p class="align-center">📍 距离 <strong class="font-color">本站</strong> 约<strong class="font-color">${location.length}</strong> 公里哦!📍</p>`
}
/**
* 初始化函数
*/
async function init() {
const location = await fetchLocation(); // 获取位置信息
if (location) {
renderWelcomeMessage(location); // 渲染欢迎信息
}
else {
// 获取失败时显示错误信息
document.getElementById("welcomeMessage").innerHTML =
`<p>🌍 这位小伙伴,你似乎迷失了~🌍</p><p>获取位置信息失败,请稍后再试~😅<p>`
}
}
// 页面加载完成后执行初始化
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", init)
}
else {
init()
}
</script>
以上有几个需要进行配置的地方:
-
customLat(纬度)和customLng(经度)分别代表自定义的经纬度,默认是0.0,你可以设置成任何位置,同时也可以一并修改描述信息<strong class="font-color">本站</strong>,将本站改为你的目标地点名称。 -
const url = "https://api.nsmao.net/api/ip/query?key=";这里的 key 需要自行拼接上刚才在 Nice 猫生成的 key
经纬度的获取也非常方便,直接使用百度坐标拾取器就行,不过百度可能偏差比较大,最好使用高德拾取器
1、高德地图坐标拾取器
2、百度地图坐标拾取器
最后,把代码复制进自定义模块侧边栏的侧边栏内容里就大功告成了。

本站侧边栏使用的 key
评论