前言
昨天晚上再 b 站刷视频,看到有个 up 主,使用 nw.js 实现在电脑系统桌面加载佐伊模型,看了一下觉得很有意思,就像能不能在编辑器中加载这个模型呢,试了一下竟然可以。
视频地址:www.bilibili.com/video/BV1EH…
视频里有提取英雄联盟其他英雄模型的教程,你可以根据教程提取你喜欢的英雄模型展示。
效果展示
原理
实现原理和我以前实现的 wukong 视频插件原理一样。
大家都知道 vscode 使用electron 开发的,electron渲染页面实际上是加载的 html,我们只要在源码中找到这个 html文件,把我们的js代码放进去就行了。
使用教程
找到vscode应用程序文件夹,/Applications/Visual Studio Code.app/Contents/Resources/app/out/vs/code/electron-sandbox/workbench
,mac 电脑基本都是在这个路径。
windows系统可以点击 vscode 图标,查看所在目录, 然后进入这个目录\resources\app\out\vs\code\electron-sandbox\workbench
。。
在当前文件夹下创建model.html
文件,把下面代码复制进去。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>zoe</title>
<style>
html body {
margin: 0;
}
</style>
<script type="importmap">
{
"imports": {
"three": "https://cdn.jsdelivr.net/npm/three@0.163.0/build/three.module.js",
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.163.0/examples/jsm/"
}
}
</script>
</head>
<body>
</body>
<script type="module">
import * as THREE from 'https://cdn.jsdelivr.net/npm/three@0.163.0/build/three.module.js';
import { OrbitControls } from 'https://cdn.jsdelivr.net/npm/three@0.163.0/examples/jsm/controls/OrbitControls.js';
import { GLTFLoader } from 'https://cdn.jsdelivr.net/npm/three@0.163.0/examples/jsm/loaders/GLTFLoader.js';
const modelPath = './Zoe.glb'; // 替换为你的模型路径
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
renderer.shadowMap.enabled = true;
document.body.appendChild(renderer.domElement);
camera.position.set(1, 1, 1);
camera.lookAt(new THREE.Vector3(0, 0, 0));
let mixer;
const loader = new GLTFLoader();
loader.load(
modelPath,
function (gltf) {
const model = gltf.scene;
const box = new THREE.Box3().setFromObject(model);
const size = box.getSize(new THREE.Vector3());
const scale = (1 / size.y);
model.scale.set(scale, scale, scale);
model.position.y = -0.5;
mixer = new THREE.AnimationMixer(model);
const action = mixer.clipAction(gltf.animations[0]);
action.play();
const meshes = ['Zoe_Base_Mat', "Zoe_Base_Hair_Mat"]
model.traverse(function (child) {
if (child instanceof THREE.SkinnedMesh) {
child.castShadow = true;
child.visible = meshes.includes(child.material.name);
}
});
scene.add(model);
renderer.render(scene, camera);
},
undefined,
function (error) {
console.error('加载失败:', error);
}
);
// 创建控制器
const controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
// 环境光
const ambientLight = new THREE.AmbientLight(0xffffff, 0.5);
scene.add(ambientLight);
// 点光源
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(0, 1, 1);
pointLight.castShadow = true;
scene.add(pointLight);
const shadow = new THREE.Mesh(
new THREE.PlaneGeometry(100, 100),
new THREE.ShadowMaterial({ opacity: 0.2 })
)
shadow.rotation.x = -Math.PI / 2;
shadow.position.y = -0.5;
shadow.receiveShadow = true;
scene.add(shadow);
const clock = new THREE.Clock();
// 动画循环
function animate() {
const delta = clock.getDelta();
requestAnimationFrame(animate);
renderer.render(scene, camera);
mixer && mixer.update(delta);
}
animate();
</script>
</html>
然后在当前文件夹下创建 model.js 文件,把下面代码复制进去
const box = document.createElement('div');
box.style.width = '200px';
box.style.height = '200px';
box.style.position = 'absolute';
box.style.bottom = '200px';
box.style.right = '40px';
box.style.zIndex = '9999';
const iframe = document.createElement('iframe');
iframe.src = './model.html';
iframe.style.width = '100%';
iframe.style.height = '100%';
iframe.style.border = 'none';
iframe.style.position = 'absolute';
iframe.style.bottom = '0';
iframe.style.right = '0';
iframe.style.pointerEvents = 'none';
box.appendChild(iframe);
document.body.appendChild(box);
// 实现鼠标拖动 iframe
let isDragging = false;
let offset = { x: 0, y: 0 };
box.addEventListener('mousedown', (e) => {
console.log(333333)
isDragging = true;
offset = {
x: e.clientX - box.getBoundingClientRect().left,
y: e.clientY - box.getBoundingClientRect().top
};
});
document.addEventListener('mousemove', (e) => {
if (isDragging) {
box.style.left = `${e.clientX - offset.x}px`;
box.style.top = `${e.clientY - offset.y}px`;
}
});
document.addEventListener('mouseup', () => {
isDragging = false;
})
然后修改 workbench.html,把当前 js 引入进去
<!-- Copyright (C) Microsoft Corporation. All rights reserved. -->
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="
default-src
'none'
;
img-src
'self'
data:
blob:
vscode-remote-resource:
vscode-managed-remote-resource:
https:
;
media-src
'self'
;
frame-src
'self'
vscode-webview:
;
script-src
'self'
'unsafe-eval'
blob:
;
style-src
'self'
'unsafe-inline'
;
connect-src
'self'
https:
ws:
;
font-src
'self'
vscode-remote-resource:
vscode-managed-remote-resource:
https://*.vscode-unpkg.net
;
require-trusted-types-for
'script'
;
trusted-types
amdLoader
cellRendererEditorText
defaultWorkerFactory
diffEditorWidget
diffReview
domLineBreaksComputer
dompurify
editorGhostText
editorViewLayer
notebookRenderer
stickyScrollViewLayer
tokenizeToString
notebookChatEditController
;
" />
<!-- Workbench CSS -->
<link rel="stylesheet" href="../../../workbench/workbench.desktop.main.css">
</head>
<body aria-label="">
</body>
<!-- Startup (do not modify order of script tags!) -->
<script src="./workbench.js" type="module"></script>
<script src="./model.js" type="module"></script>
</html>
最后一步把 3d 模型文件Zoe.glb
复制进去,再重启 vscode 就行了。
提示
如果想改成自己喜欢的英雄模型,可以使用视频中的教程提取,然后把glb 文件,复制到当前目录下,然后修改 model.html 里模型地址。
修改源码后,可能会一直提示文件损坏,这个不用管,可以设置不再提示。
大家可以到 github 上下载代码文件和资源文件
最后祝大家五一劳动节假期快乐