Skip to content

Commit 0a11d5b

Browse files
authored
chore: make examples into a package (#2800)
* chore: add example package
1 parent d312ce4 commit 0a11d5b

16 files changed

+925
-121
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
tmp
44
.idea
55
/node_modules
6+
/*/node_modules
67
/packages/*/node_modules
78
/packages/*/types
89
/packages/*/doc

examples/index.html

Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
<!DOCTYPE html>
2+
<html lang="en" class="w-full h-full">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Galacean Playground</title>
7+
<link rel="icon" href="https://mdn.alipayobjects.com/huamei_dc3kgb/afts/img/A*yHe-TqU1TOkAAAAAAAAAAAAADuiaAQ/original" />
8+
<script src="https://cdn.tailwindcss.com"></script>
9+
<script>
10+
tailwind.config = {
11+
theme: {
12+
extend: {
13+
colors: {
14+
'galacean': {
15+
50: '#f0f9ff',
16+
100: '#e0f2fe',
17+
500: '#0ea5e9',
18+
600: '#0284c7',
19+
700: '#0369a1',
20+
900: '#0c4a6e'
21+
}
22+
},
23+
fontFamily: {
24+
'sans': ['Inter', 'system-ui', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'sans-serif']
25+
}
26+
}
27+
}
28+
}
29+
</script>
30+
<style>
31+
/* Custom styles */
32+
.search-input {
33+
background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 24 24' stroke-width='1.5' stroke='%236b7280'%3e%3cpath stroke-linecap='round' stroke-linejoin='round' d='M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z' /%3e%3c/svg%3e");
34+
background-position: 12px center;
35+
background-repeat: no-repeat;
36+
background-size: 16px 16px;
37+
}
38+
39+
.item-list .hide {
40+
height: 0 !important;
41+
opacity: 0;
42+
overflow: hidden;
43+
}
44+
45+
.item-list a.active {
46+
background: linear-gradient(135deg, #0ea5e9 0%, #0284c7 100%) !important;
47+
}
48+
49+
.item-list a.active .demo-item {
50+
background: transparent !important;
51+
}
52+
53+
.item-list a.active .demo-item span {
54+
color: white !important;
55+
}
56+
57+
.item-list a.active .demo-item .w-2 {
58+
background-color: white !important;
59+
}
60+
61+
.sidebar-gradient {
62+
background: linear-gradient(180deg, #f8fafc 0%, #f1f5f9 100%);
63+
border-right: 1px solid #e2e8f0;
64+
}
65+
66+
.category-title {
67+
background: linear-gradient(135deg, #64748b 0%, #475569 100%);
68+
-webkit-background-clip: text;
69+
-webkit-text-fill-color: transparent;
70+
background-clip: text;
71+
}
72+
73+
.demo-item {
74+
transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
75+
}
76+
77+
.demo-item:hover {
78+
background: linear-gradient(135deg, #f1f5f9 0%, #e2e8f0 100%);
79+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
80+
}
81+
82+
.fullscreen-btn {
83+
transition: all 0.2s ease;
84+
filter: grayscale(1);
85+
}
86+
87+
.fullscreen-btn:hover {
88+
filter: grayscale(0);
89+
transform: scale(1.1);
90+
}
91+
</style>
92+
</head>
93+
<body class="m-0 w-full h-full overflow-hidden font-sans text-slate-800 bg-white antialiased">
94+
<div class="flex h-full">
95+
<div class="sidebar-gradient w-80 flex flex-col shadow-xl">
96+
<div class="px-6 py-6 border-b border-slate-200/60">
97+
<div class="flex items-center justify-between mb-6">
98+
<a class="flex items-center space-x-3 text-slate-900 hover:text-galacean-600 transition-colors duration-200"
99+
href="https://galacean.antgroup.com/" target="Home">
100+
<div class="w-8 h-8 rounded-lg bg-white flex items-center justify-center shadow-lg">
101+
<img
102+
class="w-6 h-6"
103+
src="https://mdn.alipayobjects.com/huamei_qbugvr/afts/img/A*ppQsSphM7uUAAAAAAAAAAAAADtKFAQ/original"
104+
alt="Galacean Logo"
105+
/>
106+
</div>
107+
<div>
108+
<h1 class="text-lg font-semibold tracking-tight">Galacean</h1>
109+
<p class="text-xs text-slate-500 font-medium">Playground</p>
110+
</div>
111+
</a>
112+
113+
<button
114+
id="fullScreen"
115+
class="fullscreen-btn w-9 h-9 rounded-lg bg-white border border-slate-200 flex items-center justify-center hover:bg-slate-50 hover:border-slate-300 shadow-sm"
116+
title="Open in fullscreen"
117+
>
118+
<img
119+
class="w-4 h-4"
120+
src="https://mdn.alipayobjects.com/huamei_dmxymu/afts/img/A*lmbpRpr9QugAAAAAAAAAAAAADuuHAQ/original"
121+
alt="Fullscreen"
122+
/>
123+
</button>
124+
</div>
125+
126+
<div class="relative">
127+
<input
128+
placeholder="Search examples..."
129+
class="search-input w-full pl-10 pr-4 py-3 bg-white border border-slate-200 rounded-xl text-sm placeholder-slate-400 focus:outline-none focus:ring-2 focus:ring-galacean-500 focus:border-transparent shadow-sm transition-all duration-200"
130+
id="searchBar"
131+
autocorrect="off"
132+
autocapitalize="off"
133+
spellcheck="false"
134+
/>
135+
</div>
136+
</div>
137+
<div class="item-list flex-1 overflow-y-auto px-4 py-4" id="itemList">
138+
</div>
139+
</div>
140+
141+
<div class="flex-1 bg-slate-50">
142+
<iframe
143+
id="iframe"
144+
allowfullscreen
145+
src=""
146+
frameborder="0"
147+
class="w-full h-full bg-white shadow-inner"
148+
></iframe>
149+
</div>
150+
</div>
151+
152+
<script type="module" src="./index.js"></script>
153+
</body>
154+
</html>

examples/index.js

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import demoList from "./dist/.demoList.json";
2+
const itemListDOM = document.getElementById("itemList");
3+
const searchBarDOM = document.getElementById("searchBar");
4+
const fullScreenDOM = document.getElementById("fullScreen");
5+
const iframe = document.getElementById("iframe");
6+
const items = []; // itemDOM,label
7+
8+
Object.keys(demoList).forEach((group, groupIndex) => {
9+
const demos = demoList[group];
10+
const groupDOM = document.createElement("div");
11+
const titleDOM = document.createElement("div");
12+
const demosDOM = document.createElement("div");
13+
14+
// Create modern category title
15+
titleDOM.innerHTML = `
16+
<div class="flex items-center space-x-2 mb-3">
17+
<div class="w-1 h-4 bg-gradient-to-b from-galacean-500 to-galacean-700 rounded-full"></div>
18+
<h3 class="category-title text-sm font-semibold uppercase tracking-wider">${group}</h3>
19+
</div>
20+
`;
21+
22+
// Add spacing between groups
23+
if (groupIndex > 0) {
24+
groupDOM.classList.add("mt-6");
25+
}
26+
27+
itemListDOM.appendChild(groupDOM);
28+
groupDOM.appendChild(titleDOM);
29+
groupDOM.appendChild(demosDOM);
30+
31+
// Style the demos container
32+
demosDOM.classList.add("space-y-1", "mb-4");
33+
34+
demos.forEach((item) => {
35+
const { label, src } = item;
36+
const itemDOM = document.createElement("a");
37+
38+
itemDOM.innerHTML = `
39+
<div class="flex items-center space-x-3 p-3 rounded-lg demo-item group">
40+
<div class="w-2 h-2 rounded-full bg-slate-300 group-hover:bg-galacean-500 transition-colors duration-200"></div>
41+
<span class="text-sm font-medium text-slate-700 group-hover:text-slate-900">${label}</span>
42+
</div>
43+
`;
44+
45+
itemDOM.title = `${src}`;
46+
itemDOM.classList.add(
47+
"block",
48+
"cursor-pointer",
49+
"transition-all",
50+
"duration-200",
51+
"overflow-hidden",
52+
"no-underline",
53+
"rounded-lg"
54+
);
55+
56+
itemDOM.onclick = function () {
57+
clickItem(itemDOM);
58+
};
59+
demosDOM.appendChild(itemDOM);
60+
61+
items.push({
62+
itemDOM,
63+
label,
64+
src
65+
});
66+
});
67+
});
68+
69+
searchBarDOM.oninput = () => {
70+
updateFilter(searchBarDOM.value);
71+
};
72+
73+
fullScreenDOM.onclick = () => {
74+
const itemName = location.hash.split("#dist/")[1];
75+
76+
if (itemName) {
77+
location.href = location.origin + `/dist/${itemName}.html`;
78+
}
79+
};
80+
81+
function updateFilter(value) {
82+
const reg = new RegExp(value, "i");
83+
84+
items.forEach(({ itemDOM, label, src }) => {
85+
reg.lastIndex = 0;
86+
if (reg.test(label) || reg.test(src)) {
87+
itemDOM.classList.remove("hide");
88+
} else {
89+
itemDOM.classList.add("hide");
90+
}
91+
});
92+
}
93+
94+
function clickItem(itemDOM) {
95+
window.location.hash = `#dist/${itemDOM.title}`;
96+
}
97+
98+
function onHashChange() {
99+
const hashPath = window.location.hash.split("#")[1];
100+
if (!hashPath) {
101+
clickItem(items[0].itemDOM);
102+
return;
103+
}
104+
105+
iframe.src = hashPath + ".html";
106+
107+
items.forEach(({ itemDOM }) => {
108+
const itemPath = `dist/${itemDOM.title}`;
109+
if (itemPath === hashPath) {
110+
itemDOM.classList.add("active");
111+
} else {
112+
itemDOM.classList.remove("active");
113+
}
114+
});
115+
}
116+
117+
window.onhashchange = onHashChange;
118+
119+
// init
120+
onHashChange();

examples/package.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "@galacean/engine-examples",
3+
"version": "1.5.10",
4+
"private": true,
5+
"license": "MIT",
6+
"main": "dist/main.js",
7+
"module": "dist/module.js",
8+
"types": "types/index.d.ts",
9+
"debug": "src/index.ts",
10+
"scripts": {
11+
"b:types": "tsc",
12+
"dev": "vite serve . --config vite.config.js"
13+
},
14+
"dependencies": {
15+
"@galacean/engine": "workspace:*",
16+
"@galacean/engine-core": "workspace:*",
17+
"@galacean/engine-design": "workspace:*",
18+
"@galacean/engine-loader": "workspace:*",
19+
"@galacean/engine-math": "workspace:*",
20+
"@galacean/engine-physics-lite": "workspace:*",
21+
"@galacean/engine-rhi-webgl": "workspace:*",
22+
"@galacean/engine-shader-shaderlab": "workspace:*",
23+
"@galacean/engine-shaderlab": "workspace:*",
24+
"@galacean/engine-toolkit": "latest",
25+
"@galacean/engine-ui": "workspace:*"
26+
},
27+
"devDependencies": {
28+
"dat.gui": "^0.7.9",
29+
"vite": "^4.4.4"
30+
}
31+
}
Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
Script,
1414
Vector3,
1515
WebGLEngine,
16-
WebGLMode,
16+
WebGLMode
1717
} from "@galacean/engine";
1818
import { OrbitControl } from "@galacean/engine-toolkit";
1919

@@ -22,7 +22,7 @@ async function main() {
2222
const htmlCanvas = document.getElementById("canvas") as HTMLCanvasElement;
2323
const engine = await WebGLEngine.create({
2424
canvas: htmlCanvas,
25-
graphicDeviceOptions: { webGLMode: WebGLMode.Auto },
25+
graphicDeviceOptions: { webGLMode: WebGLMode.Auto }
2626
});
2727

2828
engine.canvas.resizeByClientSize();
@@ -47,10 +47,7 @@ async function main() {
4747
// Add dom element
4848
const dom = document.createElement("div");
4949
dom.innerHTML = "Hello world!!!";
50-
dom.setAttribute(
51-
"style",
52-
"padding:10px;position:absolute;top:0;left:0;background:white;border-radius:5px"
53-
);
50+
dom.setAttribute("style", "padding:10px;position:absolute;top:0;left:0;background:white;border-radius:5px");
5451
document.body.appendChild(dom);
5552

5653
// Add script
@@ -81,10 +78,7 @@ class LocationTrackingScript extends Script {
8178

8279
onUpdate() {
8380
// Convert world coordinates to screen coordinates
84-
this.camera.worldToScreenPoint(
85-
this.entity.transform.position,
86-
this.screenPoint
87-
);
81+
this.camera.worldToScreenPoint(this.entity.transform.position, this.screenPoint);
8882
const style = this.dom.style;
8983
style.left = `${this.screenPoint.x / this.widthRatio}px`;
9084
style.top = `${this.screenPoint.y / this.heightRatio}px`;

0 commit comments

Comments
 (0)