koishi-plugin-tmp-bot
Version:
欧洲卡车模拟2 TMP查询插件,不会部署的可以直接使用此机器人->QQ:3523283907
242 lines (216 loc) • 6.54 kB
HTML
<html lang="en">
<head>
<meta charset="UTF-8">
<title>玩家足迹展示</title>
<link href="./package/leaflet/leaflet.min.css" rel="stylesheet">
<script src="./package/leaflet/leaflet.min.js"></script>
<style>
@font-face {
font-family: 'segui-emj';
src: url('./package/SEGUIEMJ.TTF');
font-weight: normal;
font-style: normal;
}
body, html {
margin: 0;
padding: 0;
font-family: 'segui-emj', "微软雅黑", serif;
}
#container {
width: 800px;
height: 600px;
background: #1a1a1a;
overflow: hidden;
position: relative;
}
.status-bar {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 32px;
background-color: rgba(0, 0, 0, 0.5);
backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px);
display: flex;
align-items: center;
padding: 0 12px;
box-shadow: 0 -2px 10px rgba(0, 0, 0, .5);
z-index: 1001;
border-top: 1px solid rgba(255, 255, 255, 0.1);
font-size: 13px;
box-sizing: border-box;
}
.status-bar .avatar {
width: 20px;
height: 20px;
border-radius: 4px;
border: 1px solid rgba(255, 255, 255, 0.3);
margin-right: 8px;
}
.status-bar .info {
flex: 1;
display: flex;
align-items: center;
}
.status-bar .info .name {
color: #b0c7ff;
font-weight: 600;
}
.status-bar .stats {
display: flex;
align-items: center;
color: #aaaaaa;
}
.status-bar .stats .label {
margin-right: 6px;
}
.status-bar .stats .value {
font-weight: bold;
color: #54d354;
}
#map-box {
width: 100%;
height: 100%;
}
#map {
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.25);
}
.marker-label {
background: rgba(0, 0, 0, 0.6);
border: 1px solid rgba(255, 255, 255, 0.2);
border-radius: 4px;
color: #fff;
padding: 2px 6px;
font-size: 12px;
white-space: nowrap;
}
</style>
</head>
<body>
<div id="container">
<div id="map-box">
<div id="map"></div>
</div>
<div class="status-bar">
<img class="avatar" id="avatar" src="https://static.truckersmp.com/avatarsN/small/defaultavatar.png" alt="avatar"/>
<div class="info">
<div class="name" id="username">测试玩家</div>
</div>
<div class="stats" id="stats-box">
<span class="label">今日里程</span>
<span class="value" id="distance">0.0 km</span>
</div>
</div>
</div>
<script src="./package/ets-map.js"></script>
<script>
function calculateDistance(p1, p2) {
return Math.sqrt(Math.pow(p1.axisX - p2.axisX, 2) + Math.pow(p1.axisY - p2.axisY, 2));
}
function parseTime(timeStr) {
return new Date(timeStr.replace(/-/g, '/')).getTime();
}
function init(data) {
if (!data) return;
document.getElementById('username').innerText = (data.name || 'Unknown') + ' 的今日行驶足迹';
if (data.smallAvatarUrl) {
document.getElementById('avatar').src = data.smallAvatarUrl;
}
const points = (data.points || []).filter(p => !(p.axisX === 0 && p.axisY === 0 && p.heading === 0));
// 使用传入的今日里程数据(米转千米)
const mileage = data.todayMileage || 0;
const km = (mileage / 1000).toFixed(1);
document.getElementById('distance').innerText = `${km} km`;
if (points.length === 0) {
return;
}
const lines = [];
let currentLine = [];
if (points.length > 0) {
let first = points[0];
currentLine.push({ x: first.axisX, y: first.axisY });
for (let i = 1; i < points.length; i++) {
const prev = points[i - 1];
const curr = points[i];
let dist = calculateDistance(prev, curr);
dist = dist * 19;
const isDistJump = dist > 30000; // > 30km
let timeDiff = 0;
try {
timeDiff = (parseTime(curr.updateTime) - parseTime(prev.updateTime)) / 1000;
} catch (e) { }
const isTimeJump = timeDiff > 90;
const isServerJump = prev.serverId !== curr.serverId;
if (isDistJump || isTimeJump || isServerJump) {
if (currentLine.length > 0) lines.push(currentLine);
currentLine = [];
}
currentLine.push({ x: curr.axisX, y: curr.axisY });
}
if (currentLine.length > 0) lines.push(currentLine);
}
render(lines, data.mapType);
}
function render(lines, mapType) {
const config = mapConfig[mapType];
// 边界
let bounds = L.latLngBounds(
map.unproject([0, config.bounds.y], config.maxZoom),
map.unproject([config.bounds.x, 0], config.maxZoom)
);
map.setMaxBounds(bounds);
// 瓦片
L.tileLayer(config.tileUrl, {
minZoom: 0,
maxZoom: 8,
minNativeZoom: 2,
maxNativeZoom: 8,
tileSize: 512,
bounds: bounds,
reuseTiles: true
}).addTo(map);
let allLatlngs = [];
lines.forEach(points => {
if (!points || points.length === 0) return;
let latlngs = [];
points.forEach(xy => {
let unprojected = map.unproject(config.calculateMapCoordinate(xy.x, xy.y), 8);
latlngs.push([unprojected.lat, unprojected.lng]);
allLatlngs.push([unprojected.lat, unprojected.lng]);
});
// 轨迹线
L.polyline(latlngs, {
color: '#3498db',
weight: 4,
opacity: 0.8,
lineJoin: 'round'
}).addTo(map);
// 起点
L.circleMarker(latlngs[0], {
radius: 4,
fillColor: '#2ecc71',
color: '#fff',
weight: 2,
fillOpacity: 1
}).addTo(map);
// 终点
L.circleMarker(latlngs[latlngs.length - 1], {
radius: 4,
fillColor: '#e74c3c',
color: '#fff',
weight: 2,
fillOpacity: 1
}).addTo(map);
});
// 自动适应
if (allLatlngs.length > 0) {
map.fitBounds(L.latLngBounds(allLatlngs), { padding: [50, 50] });
}
}
</script>
</body>
</html>