aardio 文档

aardio 范例: WebView2 桌面透明窗口 / three.js 三维演示

相关范例 - 机器人(Three.js)

//相关范例 - 机器人(Three.js): https://www.aardio.com/zh-cn/doc/example/WebUI/web.view/OtherApps/Tree.js.html
import win.ui;
/*DSG{{*/
var winform = win.form(text="WebView2 桌面透明窗口 / three.js 三维演示";right=757;bottom=467;border="none")
/*}}*/

import web.view;
var wb = web.view(winform);

// 设置网页窗口为桌面透明背景(独立窗口必须是无边框窗口才能显示为透明效果)
wb.transparent = true; 
/*
如果再添加代码 winform.transparent = true 以启用分层窗口,
WebView2 内网页的所有鼠标事件默认都会穿透到背景窗口(无论背景是否透明)。
可以通过窗口 _WM_NCHITTEST 消息来控制是否穿透,但较麻烦也没有这个必要。

如果仅使用 wb.transparent = true 设置网页背景透明,
则由网页自行处理所有鼠标事件(透明部分也不会穿透到背景窗口)。
*/

wb.external = {
    closeWindow = function(){
        winform.close();
    };
    minimizeWindow = function(){
        winform.hitMin();
    };
    hitCaption = function(){
        winform.hitCaption()
    };
}

wb.html = /********
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Three.js 炫酷3D</title>
  <style>
    * {
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }

    body {
      min-height: 100vh;
      background: transparent;
      overflow: hidden;
    }

    #canvas-container {
      position: fixed;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
    }

    .info {
      position: fixed;
      top: 20px;
      left: 50%;
      transform: translateX(-50%);
      color: #ffffff;
      font-family: 'Segoe UI', Arial, sans-serif;
      font-size: 14px;
      font-weight: 500;
      text-align: center;
      display: flex;
      align-items: center;
      gap: 15px;
      padding: 10px 15px 10px 24px;
      border-radius: 25px;
      background: rgba(0, 0, 0, 0.5);
      backdrop-filter: blur(10px);
      -webkit-backdrop-filter: blur(10px);
      border: 1px solid rgba(255, 255, 255, 0.2);
      box-shadow: 
        0 4px 20px rgba(0, 0, 0, 0.3),
        inset 0 1px 0 rgba(255, 255, 255, 0.1);
      text-shadow: 
        0 1px 2px rgba(0, 0, 0, 0.8),
        0 0 10px rgba(0, 255, 255, 0.5);
    }

    .info-text {
      pointer-events: none;
    }

    .close-btn {
      width: 28px;
      height: 28px;
      border-radius: 50%;
      border: none;
      background: rgba(255, 100, 100, 0.6);
      color: white;
      font-size: 18px;
      font-weight: bold;
      cursor: pointer;
      display: flex;
      align-items: center;
      justify-content: center;
      transition: all 0.3s ease;
      text-shadow: none;
      line-height: 1;
    }

    .close-btn:hover {
      background: rgba(255, 80, 80, 0.9);
      transform: scale(1.1);
      box-shadow: 0 0 15px rgba(255, 100, 100, 0.6);
    }

    .close-btn:active {
      transform: scale(0.95);
    }
  </style>
</head>
<body>
  <div id="canvas-container"></div> 
  <div class="info">
    <span class="info-text">🖱️ 拖拽旋转 | 滚轮缩放 | 右键平移</span>
    <button class="close-btn" onclick="aardio.closeWindow()" title="关闭">×</button>
  </div>

  <script type="importmap">
  {
    "imports": {
      "three": "https://registry.npmmirror.com/three/0.182.0/files/build/three.module.js",
      "three/addons/": "https://registry.npmmirror.com/three/0.182.0/files/examples/jsm/"
    }
  }
  </script>

  <script type="module">
    import * as THREE from 'three';
    import { OrbitControls } from 'three/addons/controls/OrbitControls.js';

    // 场景设置
    const scene = new THREE.Scene();

    // 相机
    const camera = new THREE.PerspectiveCamera(
      75, 
      window.innerWidth / window.innerHeight, 
      0.1, 
      1000
    );
    camera.position.z = 5;

    // 渲染器 - 透明背景
    const renderer = new THREE.WebGLRenderer({ 
      antialias: true, 
      alpha: true 
    });
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2));
    renderer.setClearColor(0x000000, 0); // 透明背景
    document.getElementById('canvas-container').appendChild(renderer.domElement);

    // 鼠标控制
    const controls = new OrbitControls(camera, renderer.domElement);
    controls.enableDamping = true;
    controls.dampingFactor = 0.05;
    controls.autoRotate = true;
    controls.autoRotateSpeed = 1;

    // 创建炫酷的主几何体 - 二十面体
    const geometry = new THREE.IcosahedronGeometry(1.5, 1);

    // 渐变材质
    const material = new THREE.MeshPhysicalMaterial({
      color: 0x00ffff,
      metalness: 0.9,
      roughness: 0.1,
      transparent: true,
      opacity: 0.8,
      side: THREE.DoubleSide,
      emissive: 0x004444,
      emissiveIntensity: 0.3
    });

    const mesh = new THREE.Mesh(geometry, material);
    scene.add(mesh);

    // 线框效果
    const wireframe = new THREE.LineSegments(
      new THREE.WireframeGeometry(geometry),
      new THREE.LineBasicMaterial({ 
        color: 0xffffff, 
        transparent: true, 
        opacity: 0.3 
      })
    );
    mesh.add(wireframe);

    // 内部发光球体
    const innerGlow = new THREE.Mesh(
      new THREE.SphereGeometry(0.5, 32, 32),
      new THREE.MeshBasicMaterial({
        color: 0xff00ff,
        transparent: true,
        opacity: 0.6
      })
    );
    mesh.add(innerGlow);

    // 粒子环绕效果
    const particleCount = 500;
    const particleGeometry = new THREE.BufferGeometry();
    const positions = new Float32Array(particleCount * 3);
    const colors = new Float32Array(particleCount * 3);

    for (let i = 0; i < particleCount; i++) {
      const theta = Math.random() * Math.PI * 2;
      const phi = Math.acos(2 * Math.random() - 1);
      const radius = 2.5 + Math.random() * 1.5;

      positions[i * 3] = radius * Math.sin(phi) * Math.cos(theta);
      positions[i * 3 + 1] = radius * Math.sin(phi) * Math.sin(theta);
      positions[i * 3 + 2] = radius * Math.cos(phi);

      // 随机颜色 (青色到紫色)
      colors[i * 3] = Math.random() * 0.5;
      colors[i * 3 + 1] = Math.random() * 0.5 + 0.5;
      colors[i * 3 + 2] = Math.random() * 0.5 + 0.5;
    }

    particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
    particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));

    const particleMaterial = new THREE.PointsMaterial({
      size: 0.05,
      vertexColors: true,
      transparent: true,
      opacity: 0.8,
      blending: THREE.AdditiveBlending
    });

    const particles = new THREE.Points(particleGeometry, particleMaterial);
    scene.add(particles);

    // 光环
    const ringGeometry = new THREE.TorusGeometry(2.8, 0.02, 16, 100);
    const ringMaterial = new THREE.MeshBasicMaterial({ 
      color: 0x00ffff, 
      transparent: true, 
      opacity: 0.5 
    });

    const ring1 = new THREE.Mesh(ringGeometry, ringMaterial);
    ring1.rotation.x = Math.PI / 2;
    scene.add(ring1);

    const ring2 = new THREE.Mesh(ringGeometry, ringMaterial.clone());
    ring2.rotation.x = Math.PI / 3;
    ring2.rotation.y = Math.PI / 4;
    scene.add(ring2);

    // 灯光
    const ambientLight = new THREE.AmbientLight(0x404040, 0.5);
    scene.add(ambientLight);

    const pointLight1 = new THREE.PointLight(0x00ffff, 2, 50);
    pointLight1.position.set(5, 5, 5);
    scene.add(pointLight1);

    const pointLight2 = new THREE.PointLight(0xff00ff, 2, 50);
    pointLight2.position.set(-5, -5, 5);
    scene.add(pointLight2);

    const pointLight3 = new THREE.PointLight(0xffff00, 1, 50);
    pointLight3.position.set(0, 5, -5);
    scene.add(pointLight3);

    // 动画循环
    function animate() {
      requestAnimationFrame(animate);

      const time = Date.now() * 0.001;

      // 主体缓慢旋转
      mesh.rotation.x = time * 0.2;
      mesh.rotation.y = time * 0.3;

      // 内部发光呼吸效果
      innerGlow.scale.setScalar(0.8 + Math.sin(time * 2) * 0.2);
      innerGlow.material.color.setHSL((time * 0.1) % 1, 1, 0.5);

      // 粒子旋转
      particles.rotation.y = time * 0.1;
      particles.rotation.x = time * 0.05;

      // 光环旋转
      ring1.rotation.z = time * 0.5;
      ring2.rotation.z = -time * 0.3;

      // 主材质颜色变化
      material.color.setHSL((time * 0.05) % 1, 0.8, 0.5);
      material.emissive.setHSL((time * 0.05 + 0.5) % 1, 0.8, 0.2);

      controls.update();
      renderer.render(scene, camera);
    }

    // 窗口大小调整
    window.addEventListener('resize', () => {
      camera.aspect = window.innerWidth / window.innerHeight;
      camera.updateProjectionMatrix();
      renderer.setSize(window.innerWidth, window.innerHeight);
    });

    animate();
  </script>
</body>
</html>

********/

winform.fullscreen(true);
winform.show();
win.loopMessage();
Markdown 格式