<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8" />
<title>流萤</title>
<!-- 引入 Spine Player 样式 -->
<link rel="stylesheet" href="./spine-player.css" />
<!-- 引入 Spine Player JS(IIFE 版本) -->
<script src="./spine-player.js"></script>
<script>
// ✅ 添加:强制启用 WebGL alpha 通道
(function () {
const original = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function (type, attributes) {
if (type === "webgl" || type === "experimental-webgl") {
return original.call(this, type, Object.assign({ alpha: true }, attributes));
}
return original.call(this, type, attributes);
};
})();
</script>
<style>
body,
html {
margin: 0;
padding: 0;
overflow: hidden;
background: rgba(0, 0, 0, 0);
/* 使用白色背景代替透明 */
width: 100%;
height: 100%;
}
#spine-container {
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
pointer-events: none;
background: rgba(0, 0, 0, 0);
/* 使用白色背景代替透明 */
}
/* 确保Spine Player创建的canvas也是白色 */
canvas {
background-color: rgba(0, 0, 0, 0) !important;
background: rgba(0, 0, 0, 0) !important;
}
/* 覆盖Spine Player可能的默认样式 */
.spine-player {
background-color: rgba(0, 0, 0, 0) !important;
background: rgba(0, 0, 0, 0) !important;
}
.spine-player-canvas {
background-color: rgba(0, 0, 0, 0) !important;
background: rgba(0, 0, 0, 0) !important;
}
/* 备用方案:如果需要透明,可以尝试使用特定颜色 */
/*
.spine-player, .spine-player-canvas, canvas {
background-color: rgba(0,0,0,0) !important;
}
*/
</style>
</head>
<body>
<!-- Spine 容器 -->
<div id="spine-container"></div>
<script>
// 🔧 重要:在 new SpinePlayer 之前拦截 getContext,强制启用 alpha
(function patchWebGLAlpha() {
const originalGetContext = HTMLCanvasElement.prototype.getContext;
HTMLCanvasElement.prototype.getContext = function (type, attributes) {
if (type === "webgl" || type === "experimental-webgl") {
attributes = Object.assign({
alpha: true,
premultipliedAlpha: false,
antialias: true,
stencil: true,
preserveDrawingBuffer: true
}, attributes);
console.log("WebGL context created with alpha:", attributes.alpha);
}
return originalGetContext.call(this, type, attributes);
};
})();
let player = null;
window.addEventListener('load', function () {
if (typeof spine === 'undefined') {
console.error('❌ spine 未定义!请检查 spine-player.js 是否加载成功');
return;
}
const container = document.getElementById("spine-container");
try {
// 尝试使用rgba(0,0,0,0)代替transparent
player = new spine.SpinePlayer(container, {
jsonUrl: "./assets/1310.json",
atlasUrl: "./assets/1310.atlas",
animation: "idle",
showControls: false,
// ✅ 背景设为透明(使用rgba格式)
backgroundColor: "#00000000",
// ✅ 关键配置:启用透明渲染
premultipliedAlpha: false,
realtimeRendering: true,
clearColor: "#00000000",
preserveDrawingBuffer: true,
useWebGL: true,
viewport: {
debugClipping: false,
padLeft: 0.1,
padRight: 0.1,
padTop: 0.1,
padBottom: 0.1
},
success: function (instance) {
console.log("✅ Spine Player 加载成功!");
player = instance;
// 方法:通过 canvas 获取 WebGL 上下文并设置透明清屏色
const canvas = document.querySelector('#spine-container canvas');
if (canvas) {
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if (gl) {
gl.clearColor(0, 0, 0, 0); // 完全透明
gl.clear(gl.COLOR_BUFFER_BIT);
console.log("✅ WebGL 背景已设为透明");
} else {
console.warn("⚠️ 无法获取 WebGL 上下文");
}
} else {
console.warn("⚠️ 未找到 canvas 元素");
}
// 处理挂起的动画请求
while (pendingAnimations.length > 0) {
const { name, loop } = pendingAnimations.shift();
window.playAnimation(name, loop);
}
},
error: function (err) {
console.error("❌ Spine 加载失败:", err);
if (err.xhr) {
console.error(`HTTP ${err.xhr.status}:`, err.xhr.statusText);
console.error("响应内容:", err.xhr.responseText);
}
alert("Spine 资源加载失败,请检查路径或服务器环境!");
}
});
} catch (e) {
console.error("Spine Player 初始化异常:", e);
}
});
// 提供给外部调用的方法
window.playAnimation = function (name, loop = true) {
if (!player || !player.state || !player.skeletonData) {
console.warn("Spine player 尚未就绪,无法播放动画:", name);
return;
}
const anim = player.skeletonData.findAnimation(name);
if (!anim) {
console.warn(`⚠️ 动画 "${name}" 未找到,请检查名称拼写`);
return;
}
player.state.data.defaultMix = 0.2; // 淡入淡出时间
player.state.setAnimation(0, name, loop);
};
</script>
</body>
</html>
window.playAnimation = function (name, loop = true) {
if (!player || !player.state || !player.skeletonData) {
console.warn("Spine player 尚未就绪,无法播放动画:", name);
return;
}
const anim = player.skeletonData.findAnimation(name);
if (!anim) {
console.warn(`⚠️ 动画 "${name}" 未找到,请检查名称拼写`);
return;
}
player.state.data.defaultMix = 0.2; // 淡入淡出时间
player.state.setAnimation(0, name, loop);
};
加载问题是这里