|
|
|
|
|
<!doctype html>
|
|
|
|
|
|
<html>
|
|
|
|
|
|
|
|
|
|
|
|
<head>
|
|
|
|
|
|
<meta charset="UTF-8">
|
|
|
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
|
|
|
<title>VyesJS - 现代Web组件框架</title>
|
|
|
|
|
|
<link rel="stylesheet" href="https://unpkg.com/animations@latest/css/animate.min.css">
|
|
|
|
|
|
</head>
|
|
|
|
|
|
|
|
|
|
|
|
<style>
|
|
|
|
|
|
:root {
|
|
|
|
|
|
--primary: #2563eb;
|
|
|
|
|
|
--gradient: linear-gradient(135deg, #2563eb 0%, #7c3aed 100%);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
body {
|
|
|
|
|
|
font-family: 'Segoe UI', system-ui;
|
|
|
|
|
|
line-height: 1.6;
|
|
|
|
|
|
overflow-x: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero {
|
|
|
|
|
|
min-height: 100vh;
|
|
|
|
|
|
display: flex;
|
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
background: var(--gradient);
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.hero-canvas {
|
|
|
|
|
|
position: absolute;
|
|
|
|
|
|
width: 100%;
|
|
|
|
|
|
height: 100%;
|
|
|
|
|
|
top: 0;
|
|
|
|
|
|
left: 0;
|
|
|
|
|
|
z-index: 1;
|
|
|
|
|
|
pointer-events: none;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feature-card {
|
|
|
|
|
|
background: rgba(255, 255, 255, 0.1);
|
|
|
|
|
|
border-radius: 16px;
|
|
|
|
|
|
padding: 2rem;
|
|
|
|
|
|
transition: transform 0.3s ease;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.feature-card:hover {
|
|
|
|
|
|
transform: translateY(-10px);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.code-sample {
|
|
|
|
|
|
background: #1e293b;
|
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
|
border-radius: 12px;
|
|
|
|
|
|
position: relative;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
.install-box {
|
|
|
|
|
|
background: white;
|
|
|
|
|
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1);
|
|
|
|
|
|
padding: 1.5rem;
|
|
|
|
|
|
border-radius: 8px;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@media (max-width: 768px) {
|
|
|
|
|
|
.hero {
|
|
|
|
|
|
padding-top: 6rem;
|
|
|
|
|
|
text-align: center;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
</style>
|
|
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<!-- 导航栏 -->
|
|
|
|
|
|
<nav class="fixed w-full bg-white/90 backdrop-blur z-50">
|
|
|
|
|
|
<div class="container mx-auto flex items-center justify-between p-4">
|
|
|
|
|
|
<div class="text-2xl font-bold text-[var(--primary)]">VyesJS</div>
|
|
|
|
|
|
<div class="flex gap-6">
|
|
|
|
|
|
<a href="#features" class="hover:text-[var(--primary)]">特性</a>
|
|
|
|
|
|
<a href="#docs" class="hover:text-[var(--primary)]">文档</a>
|
|
|
|
|
|
<a href="#examples" class="hover:text-[var(--primary)]">示例</a>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</nav>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 首屏内容 -->
|
|
|
|
|
|
<section class="hero">
|
|
|
|
|
|
<canvas class="hero-canvas" id="particleCanvas"></canvas>
|
|
|
|
|
|
<div class="container mx-auto px-4 relative z-20">
|
|
|
|
|
|
<div class="max-w-3xl">
|
|
|
|
|
|
<h1 class="text-6xl font-bold mb-6 animate-fade-in-up">
|
|
|
|
|
|
下一代Web组件框架
|
|
|
|
|
|
</h1>
|
|
|
|
|
|
<p class="text-xl opacity-90 mb-8 animate-fade-in-up delay-100">
|
|
|
|
|
|
用熟悉的HTML语法,构建现代Web应用
|
|
|
|
|
|
</p>
|
|
|
|
|
|
<div class="flex gap-4 animate-fade-in-up delay-200">
|
|
|
|
|
|
<button class="bg-white text-[var(--primary)] px-6 py-3 rounded-full font-semibold hover:shadow-lg transition"
|
|
|
|
|
|
@click="startLearning">
|
|
|
|
|
|
立即开始
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 特性展示 -->
|
|
|
|
|
|
<section id="features" class="py-20 bg-gray-50">
|
|
|
|
|
|
<div class="container mx-auto px-4 grid grid-cols-1 md:grid-cols-3 gap-8">
|
|
|
|
|
|
<div v-for="(feature, index) in features" class="feature-card">
|
|
|
|
|
|
<div class="text-4xl mb-4">{{ feature.emoji }}</div>
|
|
|
|
|
|
<h3 class="text-xl font-semibold mb-2">{{ feature.title }}</h3>
|
|
|
|
|
|
<p class="opacity-90">{{ feature.desc }}</p>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 代码示例 -->
|
|
|
|
|
|
<section class="py-20">
|
|
|
|
|
|
<div class="container mx-auto px-4 grid md:grid-cols-2 gap-8 items-center">
|
|
|
|
|
|
<div class="code-sample">
|
|
|
|
|
|
<pre class="text-sm text-gray-200"><code>
|
|
|
|
|
|
{{codeExample}}
|
|
|
|
|
|
</code></pre>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<h2 class="text-3xl font-bold mb-4">简洁直观的语法</h2>
|
|
|
|
|
|
<p class="text-gray-600 mb-6">使用您熟悉的HTML语法,通过少量增强指令实现现代Web应用开发</p>
|
|
|
|
|
|
<div class="install-box">
|
|
|
|
|
|
<div class="font-mono text-sm">
|
|
|
|
|
|
$ npm install vyesjs
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
|
|
|
|
|
|
<!-- 互动演示 -->
|
|
|
|
|
|
<section class="py-20 bg-[var(--primary)]">
|
|
|
|
|
|
<div class="container mx-auto px-4 text-center">
|
|
|
|
|
|
<h2 class="text-4xl font-bold mb-8">实时体验</h2>
|
|
|
|
|
|
<div class="max-w-2xl mx-auto bg-white/10 p-8 rounded-xl">
|
|
|
|
|
|
<input !value="demoText" @input='demoText=$event.target.value' class="w-full bg-white/20 px-4 py-2 rounded mb-4"
|
|
|
|
|
|
placeholder="输入内容...">
|
|
|
|
|
|
<div class="text-lg">实时预览:{{ demoText }}</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
codeExample = `
|
|
|
|
|
|
<!doctype html>
|
|
|
|
|
|
<html>
|
|
|
|
|
|
|
|
|
|
|
|
<body>
|
|
|
|
|
|
<div class="text-4xl">
|
|
|
|
|
|
{{ count }}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<button @click="increment" class="bg-blue-500 text-white px-4 py-2 rounded">
|
|
|
|
|
|
+1
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</body>
|
|
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
|
count = 0
|
|
|
|
|
|
increment = () => {
|
|
|
|
|
|
count++
|
|
|
|
|
|
}
|
|
|
|
|
|
<\/script>
|
|
|
|
|
|
|
|
|
|
|
|
</html>
|
|
|
|
|
|
`
|
|
|
|
|
|
features = [
|
|
|
|
|
|
{
|
|
|
|
|
|
emoji: "🚀",
|
|
|
|
|
|
title: "闪电般的速度",
|
|
|
|
|
|
desc: "基于现代浏览器特性构建,极致的运行时性能"
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
emoji: "💡",
|
|
|
|
|
|
title: "直观的语法",
|
|
|
|
|
|
desc: "零学习成本,HTML即组件"
|
|
|
|
|
|
},
|
|
|
|
|
|
{
|
|
|
|
|
|
emoji: "⚡",
|
|
|
|
|
|
title: "响应式系统",
|
|
|
|
|
|
desc: "自动依赖追踪,精准更新"
|
|
|
|
|
|
}
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
|
|
demoText = "欢迎体验Vyes!"
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
// 粒子动画初始化
|
|
|
|
|
|
function initParticles() {
|
|
|
|
|
|
const canvas = $node.querySelector('#particleCanvas');
|
|
|
|
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
|
|
|
|
|
|
|
|
let particles = [];
|
|
|
|
|
|
const particleCount = 100;
|
|
|
|
|
|
|
|
|
|
|
|
// 设置画布大小
|
|
|
|
|
|
function resizeCanvas() {
|
|
|
|
|
|
canvas.width = window.innerWidth;
|
|
|
|
|
|
canvas.height = window.innerHeight;
|
|
|
|
|
|
}
|
|
|
|
|
|
resizeCanvas();
|
|
|
|
|
|
window.addEventListener('resize', resizeCanvas);
|
|
|
|
|
|
|
|
|
|
|
|
// 创建粒子类
|
|
|
|
|
|
class Particle {
|
|
|
|
|
|
constructor() {
|
|
|
|
|
|
this.x = Math.random() * canvas.width;
|
|
|
|
|
|
this.y = Math.random() * canvas.height;
|
|
|
|
|
|
this.size = Math.random() * 3 + 1;
|
|
|
|
|
|
this.speedX = Math.random() * 2 - 1;
|
|
|
|
|
|
this.speedY = Math.random() * 2 - 1;
|
|
|
|
|
|
this.opacity = Math.random();
|
|
|
|
|
|
this.color = `rgba(${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${Math.floor(Math.random() * 256)}, ${this.opacity})`;
|
|
|
|
|
|
this.history = []; // 存储粒子的历史位置
|
|
|
|
|
|
this.maxLength = 10; // 阴影线条的最大长度
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
update() {
|
|
|
|
|
|
this.history.push({ x: this.x, y: this.y });
|
|
|
|
|
|
if (this.history.length > this.maxLength) {
|
|
|
|
|
|
this.history.shift(); // 移除最早的历史点
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
this.x += this.speedX;
|
|
|
|
|
|
this.y += this.speedY;
|
|
|
|
|
|
|
|
|
|
|
|
if (this.x > canvas.width || this.x < 0) this.speedX *= -1;
|
|
|
|
|
|
if (this.y > canvas.height || this.y < 0) this.speedY *= -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
draw() {
|
|
|
|
|
|
// 绘制阴影线条
|
|
|
|
|
|
ctx.strokeStyle = this.color;
|
|
|
|
|
|
ctx.lineWidth = this.size / 2;
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
ctx.moveTo(this.history[0].x, this.history[0].y);
|
|
|
|
|
|
for (let i = 1; i < this.history.length; i++) {
|
|
|
|
|
|
ctx.lineTo(this.history[i].x, this.history[i].y);
|
|
|
|
|
|
}
|
|
|
|
|
|
ctx.stroke();
|
|
|
|
|
|
|
|
|
|
|
|
// 绘制粒子
|
|
|
|
|
|
ctx.fillStyle = this.color;
|
|
|
|
|
|
ctx.beginPath();
|
|
|
|
|
|
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
|
|
|
|
|
|
ctx.fill();
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 初始化粒子
|
|
|
|
|
|
function createParticles() {
|
|
|
|
|
|
for (let i = 0; i < particleCount; i++) {
|
|
|
|
|
|
particles.push(new Particle());
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 动画循环
|
|
|
|
|
|
function animate() {
|
|
|
|
|
|
ctx.clearRect(0, 0, canvas.width, canvas.height);
|
|
|
|
|
|
particles.forEach(particle => {
|
|
|
|
|
|
particle.update();
|
|
|
|
|
|
particle.draw();
|
|
|
|
|
|
});
|
|
|
|
|
|
requestAnimationFrame(animate);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
createParticles();
|
|
|
|
|
|
animate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 滚动动画
|
|
|
|
|
|
const observer = new IntersectionObserver((entries) => {
|
|
|
|
|
|
entries.forEach(entry => {
|
|
|
|
|
|
if (entry.isIntersecting) {
|
|
|
|
|
|
entry.target.classList.add('animate-fade-in-up')
|
|
|
|
|
|
}
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
$node.querySelectorAll('.feature-card').forEach(el => {
|
|
|
|
|
|
observer.observe(el)
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
startLearning = () => {
|
|
|
|
|
|
window.scrollTo({
|
|
|
|
|
|
top: $node.querySelector('#features').offsetTop - 80,
|
|
|
|
|
|
behavior: 'smooth'
|
|
|
|
|
|
})
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
initParticles()
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
|
|
</html>
|