update .gitgnore
3
.gitignore
vendored
@ -4,6 +4,9 @@
|
||||
/node_modules
|
||||
/.pnp
|
||||
.pnp.js
|
||||
package-lock.json
|
||||
.idea
|
||||
/public/demo/projects
|
||||
|
||||
# testing
|
||||
/coverage
|
||||
|
49
README.md
@ -1,46 +1,9 @@
|
||||
# Getting Started with Create React App
|
||||
# gemini-viewer-examples
|
||||
Examples and demos for gemini-viewer sdk
|
||||
|
||||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app).
|
||||
# start
|
||||
npm install
|
||||
|
||||
## Available Scripts
|
||||
npm start
|
||||
|
||||
In the project directory, you can run:
|
||||
|
||||
### `npm start`
|
||||
|
||||
Runs the app in the development mode.\
|
||||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser.
|
||||
|
||||
The page will reload if you make edits.\
|
||||
You will also see any lint errors in the console.
|
||||
|
||||
### `npm test`
|
||||
|
||||
Launches the test runner in the interactive watch mode.\
|
||||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information.
|
||||
|
||||
### `npm run build`
|
||||
|
||||
Builds the app for production to the `build` folder.\
|
||||
It correctly bundles React in production mode and optimizes the build for the best performance.
|
||||
|
||||
The build is minified and the filenames include the hashes.\
|
||||
Your app is ready to be deployed!
|
||||
|
||||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information.
|
||||
|
||||
### `npm run eject`
|
||||
|
||||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!**
|
||||
|
||||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project.
|
||||
|
||||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own.
|
||||
|
||||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it.
|
||||
|
||||
## Learn More
|
||||
|
||||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started).
|
||||
|
||||
To learn React, check out the [React documentation](https://reactjs.org/).
|
||||
http://localhost:3000/#/demo
|
30042
package-lock.json
generated
11
package.json
@ -3,6 +3,11 @@
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.3.0",
|
||||
"@codemirror/commands": "^6.1.2",
|
||||
"@codemirror/lang-javascript": "^6.1.1",
|
||||
"@codemirror/state": "^6.1.2",
|
||||
"@codemirror/view": "^6.4.0",
|
||||
"@testing-library/jest-dom": "^5.16.5",
|
||||
"@testing-library/react": "^13.4.0",
|
||||
"@testing-library/user-event": "^13.5.0",
|
||||
@ -10,9 +15,15 @@
|
||||
"@types/node": "^16.18.0",
|
||||
"@types/react": "^18.0.23",
|
||||
"@types/react-dom": "^18.0.7",
|
||||
"@uiw/codemirror-theme-sublime": "^4.12.4",
|
||||
"antd": "^4.24.0",
|
||||
"codemirror": "^6.0.1",
|
||||
"http-proxy-middleware": "^2.0.6",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-router-dom": "^6.4.3",
|
||||
"react-scripts": "5.0.1",
|
||||
"recoil": "^0.7.6",
|
||||
"typescript": "^4.8.4",
|
||||
"web-vitals": "^2.1.4"
|
||||
},
|
||||
|
58
public/config.json
Normal file
@ -0,0 +1,58 @@
|
||||
[{
|
||||
"title": "模型",
|
||||
"subMenus": [{
|
||||
"title": "本地模型加载",
|
||||
"url": "./demo/empty_model_project.html"
|
||||
}, {
|
||||
"title": "technical school",
|
||||
"url": "./demo/technical_school.html"
|
||||
}]
|
||||
}, {
|
||||
"title": "图纸",
|
||||
"subMenus": [{
|
||||
"title": "本地图纸加载",
|
||||
"url": "../demo/empty_dxf_project.html"
|
||||
}, {
|
||||
"title": "Rac Basic Sample Project",
|
||||
"url": "./demo/dxf_0.html"
|
||||
}, {
|
||||
"title": "运维监控楼地下一层 、首层平面图",
|
||||
"url": "./demo/dxf_1.html"
|
||||
}, {
|
||||
"title": "厨房平面",
|
||||
"url": "./demo/dxf_2.html"
|
||||
}, {
|
||||
"title": "图纸对比",
|
||||
"url": "./demo/dxf_3.html"
|
||||
}, {
|
||||
"title": "多屏图纸对比",
|
||||
"url": "./demo/dxf_4.html"
|
||||
}]
|
||||
}, {
|
||||
"title": "全景图",
|
||||
"subMenus": [{
|
||||
"title": "本地全景图加载",
|
||||
"url": "./demo/empty_vr_project.html"
|
||||
}, {
|
||||
"title": "全景图(1张图)",
|
||||
"url": "./demo/vr_0.html"
|
||||
}, {
|
||||
"title": "全景图(6张图)",
|
||||
"url": "./demo/vr_1.html"
|
||||
}, {
|
||||
"title": "全景图(6张图)",
|
||||
"url": "./demo/vr_2.html"
|
||||
}, {
|
||||
"title": "全景图(24张图)",
|
||||
"url": "./demo/vr_3.html"
|
||||
}, {
|
||||
"title": "全景图(模块替换)",
|
||||
"url": "./demo/vr_4.html"
|
||||
}, {
|
||||
"title": "全景图(双屏)",
|
||||
"url": "./demo/vr_5.html"
|
||||
}, {
|
||||
"title": "全景图切换",
|
||||
"url": "./demo/vr_album_0.html"
|
||||
}]
|
||||
}]
|
71
public/demo/compare/compareSidePanel.css
Normal file
@ -0,0 +1,71 @@
|
||||
b {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.hide {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.compare-panel-container {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
right: 0;
|
||||
width: 160px;
|
||||
height: auto;
|
||||
min-height: 200px;
|
||||
padding: 10px;
|
||||
z-index: 100;
|
||||
box-sizing: border-box;
|
||||
background-color: #fff;
|
||||
user-select: none;
|
||||
}
|
||||
.compare-panel-container h3 {
|
||||
position: fixed;
|
||||
margin: 0;
|
||||
padding-left: 5px;
|
||||
line-height: 30px;
|
||||
border-bottom: 1px solid #aaa;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.compare-detail {
|
||||
margin-top: 35px;
|
||||
max-height: 500px;
|
||||
overflow: hidden;
|
||||
cursor: pointer;
|
||||
}
|
||||
.compare-list {
|
||||
margin-top: 6px;
|
||||
}
|
||||
.list-title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.title-icon {
|
||||
padding: 5px;
|
||||
}
|
||||
.title-icon::before {
|
||||
content: '';
|
||||
display: block;
|
||||
width: 0;
|
||||
height: 0;
|
||||
border-right: 8px solid #666;
|
||||
border-top: 8px solid transparent;
|
||||
}
|
||||
.compare-collapse .title-icon::before {
|
||||
transform: rotate(-40deg);
|
||||
}
|
||||
.title-content {
|
||||
font-size: 12px;
|
||||
}
|
||||
.compare-detail ul {
|
||||
margin-left: 18px;
|
||||
max-height: 150px;
|
||||
font-size: 12px;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
||||
.compare-detail ul li {
|
||||
margin: 6px 0;
|
||||
}
|
101
public/demo/compare/compareSidePanel.js
Normal file
@ -0,0 +1,101 @@
|
||||
/* eslint-disable no-undef */
|
||||
export default class CompareSidePanel {
|
||||
compareDetail;
|
||||
container;
|
||||
viewer;
|
||||
|
||||
constructor(viewer, container = document.body) {
|
||||
this.init(viewer, container);
|
||||
}
|
||||
|
||||
init(viewer, container) {
|
||||
this.viewer = viewer;
|
||||
this.container = container;
|
||||
|
||||
this.buildPanel();
|
||||
this.initEvents();
|
||||
}
|
||||
|
||||
buildPanel() {
|
||||
const panelContainer = document.createElement("div");
|
||||
panelContainer.classList.add("compare-panel-container");
|
||||
|
||||
const header = document.createElement("h3");
|
||||
panelContainer.appendChild(header);
|
||||
this.container.appendChild(panelContainer);
|
||||
|
||||
const compareDetail = document.createElement("div");
|
||||
compareDetail.classList.add("compare-detail");
|
||||
panelContainer.appendChild(compareDetail);
|
||||
this.compareDetail = compareDetail;
|
||||
|
||||
const changes = this.viewer.changes;
|
||||
const changesValues = Object.values(changes);
|
||||
|
||||
header.innerHTML = `差异列表(${changesValues.length})`;
|
||||
|
||||
const addedChangesValues = changesValues.filter((val) => val.type === "Added");
|
||||
const deletedChangeValues = changesValues.filter((val) => val.type === "Deleted");
|
||||
const modifiedChanageValues = changesValues.filter((val) => val.type === "Modified");
|
||||
|
||||
if (addedChangesValues.length > 0) {
|
||||
this.buildList(addedChangesValues, "新增");
|
||||
}
|
||||
|
||||
if (deletedChangeValues.length > 0) {
|
||||
this.buildList(deletedChangeValues, "删除");
|
||||
}
|
||||
|
||||
if (modifiedChanageValues.length > 0) {
|
||||
this.buildList(modifiedChanageValues, "修改");
|
||||
}
|
||||
}
|
||||
|
||||
buildList(changesValues, text) {
|
||||
const section = document.createElement("div");
|
||||
section.classList.add("compare-list", "compare-add");
|
||||
this.compareDetail.appendChild(section);
|
||||
this.buildListTitle(section, `${text}(<b>${changesValues.length}</b>)`);
|
||||
const listEle = document.createElement("ul");
|
||||
listEle.classList.add("list", "hide");
|
||||
section.appendChild(listEle);
|
||||
|
||||
let listFragment = "";
|
||||
changesValues.forEach((val) => {
|
||||
listFragment += `<li class="list-item">${val.handle}</li>`;
|
||||
});
|
||||
listEle.innerHTML = listFragment;
|
||||
}
|
||||
|
||||
buildListTitle(group, title) {
|
||||
const listTitle = document.createElement("div");
|
||||
listTitle.classList.add("list-title", "compare-collapse");
|
||||
group.appendChild(listTitle);
|
||||
|
||||
const titleIcon = document.createElement("span");
|
||||
titleIcon.classList.add("title-icon");
|
||||
listTitle.appendChild(titleIcon);
|
||||
|
||||
const titleContent = document.createElement("span");
|
||||
titleContent.classList.add("title-content");
|
||||
titleContent.innerHTML = title;
|
||||
listTitle.appendChild(titleContent);
|
||||
}
|
||||
|
||||
initEvents() {
|
||||
const listTitles = document.querySelectorAll(".list-title");
|
||||
listTitles.forEach((listTitle) => {
|
||||
listTitle.addEventListener("click", () => {
|
||||
listTitle.classList.toggle("compare-collapse");
|
||||
listTitle.nextSibling?.classList.toggle("hide");
|
||||
});
|
||||
});
|
||||
|
||||
const lists = document.querySelectorAll(".list");
|
||||
lists.forEach((list) => {
|
||||
list.addEventListener("click", (e) => {
|
||||
this.viewer.zoomToCompareChange(e.target.innerHTML);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
85
public/demo/config/projects.json
Normal file
@ -0,0 +1,85 @@
|
||||
[
|
||||
{
|
||||
"id": "rac_basic_sample_project",
|
||||
"name": "rac basic sample project",
|
||||
"thumbnail": "projects/rac_basic_sample_project/thumbnail.png",
|
||||
"camera": {
|
||||
"eye": [-65, 37, 41],
|
||||
"look": [-15, 0, 15]
|
||||
},
|
||||
"models": [{
|
||||
"name": "rac basic sample project",
|
||||
"src": "projects/rac_basic_sample_project/rac_basic_sample_project.gltf",
|
||||
"position": [0, 0, 0],
|
||||
"rotation": [-90, 0, 0],
|
||||
"scale": [0.001, 0.001, 0.001],
|
||||
"instantiate": false,
|
||||
"merge": false,
|
||||
"edges": true,
|
||||
"visible": true
|
||||
}]
|
||||
}, {
|
||||
"id": "technical_school",
|
||||
"name": "technical school",
|
||||
"thumbnail": "projects/technical_school/thumbnail.png",
|
||||
"camera": {
|
||||
"eye": [-65, 37, 41],
|
||||
"look": [-15, 0, 15]
|
||||
},
|
||||
"models": [{
|
||||
"name": "technical school",
|
||||
"src": "projects/technical_school/technical_school.gltf",
|
||||
"position": [0, 0, 0],
|
||||
"rotation": [-90, 0, 0],
|
||||
"scale": [0.001, 0.001, 0.001],
|
||||
"instantiate": false,
|
||||
"merge": false,
|
||||
"edges": true,
|
||||
"visible": true
|
||||
}]
|
||||
}, {
|
||||
"id": "misc",
|
||||
"name": "misc",
|
||||
"thumbnail": "projects/misc/thumbnail.png",
|
||||
"camera": {
|
||||
"eye": [30, 40, -100],
|
||||
"look": [30, 5, -20]
|
||||
},
|
||||
"models": [{
|
||||
"name": "building_1.ifc",
|
||||
"src": "projects/misc/building_1.ifc",
|
||||
"position": [0, 0, 0],
|
||||
"edges": true
|
||||
}, {
|
||||
"name": "cgaxis_tree.fbx",
|
||||
"src": "projects/misc/cgaxis_tree.fbx",
|
||||
"position": [20, 0, 0],
|
||||
"scale": [0.05, 0.05, 0.05]
|
||||
}, {
|
||||
"name": "cgaxis_tree.obj",
|
||||
"src": "projects/misc/cgaxis_tree.obj",
|
||||
"position": [30, 0, 0],
|
||||
"scale": [0.05, 0.05, 0.05]
|
||||
}, {
|
||||
"name": "M4A1.dae",
|
||||
"src": "projects/misc/M4A1.dae",
|
||||
"position": [40, 0, 0],
|
||||
"scale": [0.05, 0.05, 0.05],
|
||||
"edges": true
|
||||
}, {
|
||||
"name": "car",
|
||||
"src": "projects/misc/car/car.dae",
|
||||
"position": [50, 0, 0],
|
||||
"rotation": [-90, 0, 0],
|
||||
"edges": true
|
||||
}]
|
||||
}, {
|
||||
"id": "ifc_building",
|
||||
"name": "ifc building",
|
||||
"thumbnail": "projects/ifc_building/thumbnail.png",
|
||||
"models": [{
|
||||
"src": "projects/ifc_building/building_2.ifc",
|
||||
"rotation": [0, 0, 0]
|
||||
}]
|
||||
}
|
||||
]
|
141
public/demo/dxf_0.html
Normal file
@ -0,0 +1,141 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico">
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css">
|
||||
<link rel="stylesheet" type="text/css" href="./demo/iconfont/iconfont.css">
|
||||
<link rel="stylesheet" href="./demo/layerManager/layerManager.css">
|
||||
<link rel="stylesheet" href="./demo/settings/SettingsPanel.css">
|
||||
<style>
|
||||
#myCanvas {
|
||||
position: absolute;
|
||||
width: calc(100% - 100px);
|
||||
width: -moz-calc(100% - 100px);
|
||||
width: -webkit-calc(100% - 100px);
|
||||
height: calc(100% - 80px);
|
||||
height: -moz-calc(100% - 80px);
|
||||
height: -webkit-calc(100vh - 80px);
|
||||
left: 50px;
|
||||
top: 40px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myCanvas" class="renderer-container"></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { DxfViewer } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
import DxfSettingsPanel from './demo/settings/DxfSettingsPanel.js';
|
||||
import LayerManager from './demo/layerManager/LayerManager.js';
|
||||
|
||||
const models= [{
|
||||
modelId: "dxf_0",
|
||||
name: "dxf_0",
|
||||
src: "./demo/projects/dxf_test/dxf_0.dxf",
|
||||
merge: true,
|
||||
visible: true,
|
||||
}, {
|
||||
modelId: "dxf_0_1",
|
||||
name: "dxf_0_1",
|
||||
src: "./demo/projects/dxf_test/dxf_0_1.dxf",
|
||||
merge: true,
|
||||
visible: true,
|
||||
}];
|
||||
const config = {
|
||||
containerId: "myCanvas",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: true,
|
||||
enableToolbar: true,
|
||||
enableSpinner: true,
|
||||
enableProgressBar: true,
|
||||
enableBottomBar: true,
|
||||
enableLayoutBar: true,
|
||||
enableSelection: true,
|
||||
};
|
||||
const viewer = new DxfViewer(config);
|
||||
// const fontFiles = ["three/fonts/Microsoft_YaHei_Regular.typeface.json"];
|
||||
const fontFiles = ["./demo/three/fonts/hztxt.shx", "./demo/three/fonts/simplex.shx"];
|
||||
await viewer.setFont(fontFiles);
|
||||
|
||||
window.viewer = viewer;
|
||||
// loadProjectModel
|
||||
let counter = 0; // to indicate how many models are loading
|
||||
models.forEach((modelCfg) => {
|
||||
if (modelCfg.visible === false) {
|
||||
// visible is true by default
|
||||
return; // only load visible ones
|
||||
}
|
||||
counter++;
|
||||
const onProgress = (event) => {
|
||||
let type = "Loading progress";
|
||||
if (event.type === "parseProgress") {
|
||||
type = "Parsing progress";
|
||||
}
|
||||
const progress = ((event.loaded * 100) / event.total).toFixed(2);
|
||||
console.log(`[Demo] ${type}: ${progress}%`);
|
||||
};
|
||||
try {
|
||||
viewer.loadModelAsync(modelCfg, onProgress).then(() => {
|
||||
console.log(`[Demo] Loaded model ${modelCfg.src}`);
|
||||
if (!viewer.layerManager) {
|
||||
viewer.layerManager = new LayerManager(viewer);
|
||||
}
|
||||
}).finally(() => {
|
||||
counter--;
|
||||
});
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
});
|
||||
|
||||
// as a demo page, add dxfSettingsPanel to window!
|
||||
window.dxfSettingsPanel = new DxfSettingsPanel(viewer);
|
||||
|
||||
const measurementData = [{
|
||||
type: "Distance",
|
||||
id: "measure_data_id_1",
|
||||
layoutName: "Model",
|
||||
points: [[0, -22000], [6000, -22000]],
|
||||
}, {
|
||||
type: "Area",
|
||||
id: "measure_data_id_2",
|
||||
layoutName: "Model",
|
||||
points: [[0, -23000], [6000, -23000], [6000, -25000], [0, -25000], [0, -23000]],
|
||||
}, {
|
||||
type: "Angle",
|
||||
id: "measure_data_id_3",
|
||||
layoutName: "Model",
|
||||
points: [[0, -26000], [6000, -26000], [4000, -29000]],
|
||||
}, {
|
||||
type: "Distance",
|
||||
id: "measure_data_id_4",
|
||||
layoutName: "Layout1",
|
||||
points: [[0, -10000], [0, 10000]],
|
||||
}];
|
||||
|
||||
const markupData = [{
|
||||
type: "Arrow",
|
||||
id: "c6ea70a3-ddb0-4dd0-87c8-bd2491936428",
|
||||
lineWidth: 2,
|
||||
strokeStyle: "#ff0000",
|
||||
fillStyle: "#ff000030",
|
||||
layoutName: "Model",
|
||||
points: [[-15000, -9000], [-11000, -4000]],
|
||||
}, {
|
||||
type: "Rectangle",
|
||||
id: "82aba74f-7cd6-40e7-bac0-78d95a7bbecd",
|
||||
lineWidth: 2,
|
||||
strokeStyle: "#ff0000",
|
||||
fillStyle: "#ff000030",
|
||||
layoutName: "Model",
|
||||
points: [[-7000, -1800], [-1000, -5000]],
|
||||
}];
|
||||
|
||||
viewer.setMeasurements(measurementData);
|
||||
viewer.setMarkups(markupData);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
80
public/demo/dxf_1.html
Normal file
@ -0,0 +1,80 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/iconfont/iconfont.css" />
|
||||
<link rel="stylesheet" href="./demo/layerManager/layerManager.css" />
|
||||
<link rel="stylesheet" href="./demo/settings/SettingsPanel.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myCanvas" class="renderer-container"></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { DxfViewer } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
import DxfSettingsPanel from './demo/settings/DxfSettingsPanel.js';
|
||||
import LayerManager from "./demo/layerManager/LayerManager.js";
|
||||
|
||||
const models = [{
|
||||
modelId: "dxf_1",
|
||||
name: "dxf_1",
|
||||
src: "./demo/projects/dxf_test/dxf_1.dxf",
|
||||
merge: true,
|
||||
visible: true,
|
||||
}];
|
||||
const config = {
|
||||
containerId: "myCanvas",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: true,
|
||||
enableToolbar: true,
|
||||
enableSpinner: true,
|
||||
enableProgressBar: true,
|
||||
enableBottomBar: true,
|
||||
enableLayoutBar: true,
|
||||
};
|
||||
const viewer = new DxfViewer(config);
|
||||
// const fontFiles = ["three/fonts/Microsoft_YaHei_Regular.typeface.json"];
|
||||
const fontFiles = ["./demo/three/fonts/hztxt.shx", "./demo/three/fonts/simplex.shx"];
|
||||
await viewer.setFont(fontFiles);
|
||||
|
||||
// loadProjectModel
|
||||
let counter = 0; // to indicate how many models are loading
|
||||
models.forEach((modelCfg) => {
|
||||
if (modelCfg.visible === false) {
|
||||
// visible is true by default
|
||||
return; // only load visible ones
|
||||
}
|
||||
counter++;
|
||||
const onProgress = (event) => {
|
||||
let type = "Loading progress";
|
||||
if (event.type === "parseProgress") {
|
||||
type = "Parsing progress";
|
||||
}
|
||||
const progress = ((event.loaded * 100) / event.total).toFixed(2);
|
||||
console.log(`[Demo] ${type}: ${progress}%`);
|
||||
};
|
||||
try {
|
||||
viewer
|
||||
.loadModelAsync(modelCfg, onProgress)
|
||||
.then(() => {
|
||||
console.log(`[Demo] Loaded model ${modelCfg.src}`);
|
||||
if (!viewer.layerManager) {
|
||||
viewer.layerManager = new LayerManager(viewer);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
counter--;
|
||||
});
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
});
|
||||
|
||||
// as a demo page, add dxfSettingsPanel to window!
|
||||
window.dxfSettingsPanel = new DxfSettingsPanel(viewer);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
80
public/demo/dxf_2.html
Normal file
@ -0,0 +1,80 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/iconfont/iconfont.css" />
|
||||
<link rel="stylesheet" href="./demo/layerManager/layerManager.css" />
|
||||
<link rel="stylesheet" href="./demo/settings/SettingsPanel.css">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myCanvas" class="renderer-container"></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { DxfViewer } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
import DxfSettingsPanel from './demo/settings/DxfSettingsPanel.js';
|
||||
import LayerManager from "./demo/layerManager/LayerManager.js";
|
||||
|
||||
const models = [{
|
||||
modelId: "dxf_2",
|
||||
name: "dxf_2",
|
||||
src: "./demo/projects/dxf_test/dxf_2.dxf",
|
||||
merge: true,
|
||||
visible: true,
|
||||
}];
|
||||
const config = {
|
||||
containerId: "myCanvas",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: true,
|
||||
enableToolbar: true,
|
||||
enableSpinner: true,
|
||||
enableProgressBar: true,
|
||||
enableBottomBar: true,
|
||||
enableLayoutBar: true,
|
||||
};
|
||||
const viewer = new DxfViewer(config);
|
||||
// const fontFiles = ["three/fonts/Microsoft_YaHei_Regular.typeface.json"];
|
||||
const fontFiles = ["./demo/three/fonts/hztxt.shx", "./demo/three/fonts/simplex.shx"];
|
||||
await viewer.setFont(fontFiles);
|
||||
|
||||
// loadProjectModel
|
||||
let counter = 0; // to indicate how many models are loading
|
||||
models.forEach((modelCfg) => {
|
||||
if (modelCfg.visible === false) {
|
||||
// visible is true by default
|
||||
return; // only load visible ones
|
||||
}
|
||||
counter++;
|
||||
const onProgress = (event) => {
|
||||
let type = "Loading progress";
|
||||
if (event.type === "parseProgress") {
|
||||
type = "Parsing progress";
|
||||
}
|
||||
const progress = ((event.loaded * 100) / event.total).toFixed(2);
|
||||
console.log(`[Demo] ${type}: ${progress}%`);
|
||||
};
|
||||
try {
|
||||
viewer
|
||||
.loadModelAsync(modelCfg, onProgress)
|
||||
.then(() => {
|
||||
console.log(`[Demo] Loaded model ${modelCfg.src}`);
|
||||
if (!viewer.layerManager) {
|
||||
viewer.layerManager = new LayerManager(viewer);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
counter--;
|
||||
});
|
||||
} catch (ex) {
|
||||
console.log(ex);
|
||||
}
|
||||
});
|
||||
|
||||
// as a demo page, add dxfSettingsPanel to window!
|
||||
window.dxfSettingsPanel = new DxfSettingsPanel(viewer);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
62
public/demo/dxf_3.html
Normal file
@ -0,0 +1,62 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/iconfont/iconfont.css" />
|
||||
<link rel="stylesheet" href="./demo/compare/compareSidePanel.css" />
|
||||
<link rel="stylesheet" href="./demo/layerManager/layerManager.css" />
|
||||
<link rel="stylesheet" href="./demo/settings/SettingsPanel.css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myCanvas" class="renderer-container"></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { DxfViewer } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
import DxfCompareSidePanel from "./demo/compare/compareSidePanel.js"
|
||||
import DxfSettingsPanel from "./demo/settings/DxfSettingsPanel.js";
|
||||
import LayerManager from "./demo/layerManager/LayerManager.js";
|
||||
|
||||
const url1 = "./demo/projects/dxf_test/dxf_3.dxf";
|
||||
const url2 = "./demo/projects/dxf_test/dxf_3_1.dxf";
|
||||
const config = {
|
||||
containerId: "myCanvas",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: true,
|
||||
enableToolbar: true,
|
||||
enableSpinner: true,
|
||||
enableProgressBar: true,
|
||||
enableBottomBar: true,
|
||||
enableLayoutBar: true,
|
||||
};
|
||||
const viewer = new DxfViewer(config);
|
||||
// const fontFiles = ["three/fonts/Microsoft_YaHei_Regular.typeface.json"];
|
||||
const fontFiles = ["./demo/three/fonts/hztxt.shx", "./demo/three/fonts/simplex.shx"];
|
||||
await viewer.setFont(fontFiles);
|
||||
|
||||
const onProgress = (event) => {
|
||||
let type = "Loading progress";
|
||||
if (event.type === "parseProgress") {
|
||||
type = "Parsing progress";
|
||||
}
|
||||
const progress = ((event.loaded * 100) / event.total).toFixed(2);
|
||||
console.log(`[Demo] ${type}: ${progress}%`);
|
||||
};
|
||||
await viewer.compare(url1, url2, onProgress).then(() => {
|
||||
console.log(`[Demo] Compared models: ${url1}, ${url2}`);
|
||||
if (!viewer.layerManager) {
|
||||
viewer.layerManager = new LayerManager(viewer);
|
||||
}
|
||||
if (!viewer.dxfCompareSidePanel) {
|
||||
viewer.dxfCompareSidePanel = new DxfCompareSidePanel(viewer);
|
||||
}
|
||||
});
|
||||
|
||||
// as a demo page, add dxfSettingsPanel to window!
|
||||
window.dxfSettingsPanel = new DxfSettingsPanel(viewer);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
115
public/demo/dxf_4.html
Normal file
@ -0,0 +1,115 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/iconfont/iconfont.css" />
|
||||
<link rel="stylesheet" href="./demo/compare/compareSidePanel.css" />
|
||||
<link rel="stylesheet" href="./demo/layerManager/layerManager.css" />
|
||||
<link rel="stylesheet" href="./demo/settings/SettingsPanel.css" />
|
||||
<style>
|
||||
#myCanvas1 {
|
||||
width: 40%;
|
||||
height: 50%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
border: 1px #dddddd solid;
|
||||
}
|
||||
#myCanvas2 {
|
||||
width: 40%;
|
||||
top: 50% !important;
|
||||
height: 50%;
|
||||
left: 0;
|
||||
position: absolute;
|
||||
border: 1px #dddddd solid;
|
||||
}
|
||||
#myCanvas3 {
|
||||
width: 60%;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
border: 1px #dddddd solid;
|
||||
}
|
||||
.title {
|
||||
font-size: 18px;
|
||||
z-index: 3;
|
||||
position: absolute;
|
||||
margin-top: 8px;
|
||||
color: white;
|
||||
top: 0%;
|
||||
left: 18%;
|
||||
}
|
||||
.title2 {
|
||||
top: 50%;
|
||||
left: 18%;
|
||||
}
|
||||
.title3 {
|
||||
left: 68%;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<span class="title">图纸 1</span>
|
||||
<div id="myCanvas1" class="renderer-container"></div>
|
||||
<span class="title title2">图纸 2</span>
|
||||
<div id="myCanvas2" class="renderer-container"></div>
|
||||
<span class="title title3">对比结果</span>
|
||||
<!-- myCanvas3 is the one for compare -->
|
||||
<div id="myCanvas3" class="renderer-container"></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { DxfViewer } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
import DxfCompareSidePanel from "./demo/compare/compareSidePanel.js"
|
||||
import DxfSettingsPanel from "./demo/settings/DxfSettingsPanel.js";
|
||||
import LayerManager from "./demo/layerManager/LayerManager.js";
|
||||
|
||||
const url1 = "./demo/projects/dxf_test/dxf_3.dxf";
|
||||
const url2 = "./demo/projects/dxf_test/dxf_3_1.dxf";
|
||||
const modelConfig1 = { modelId: "dxf_1", name: "dxf 1", src: url1, ignorePaperSpace: true };
|
||||
const modelConfig2 = { modelId: "dxf_2", name: "dxf 2", src: url2, ignorePaperSpace: true };
|
||||
const config = {
|
||||
containerId: "myCanvas3",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: false,
|
||||
enableToolbar: true,
|
||||
enableSpinner: true,
|
||||
enableProgressBar: true,
|
||||
enableBottomBar: true,
|
||||
};
|
||||
const viewer1 = new DxfViewer({ containerId: "myCanvas1"});
|
||||
const viewer2 = new DxfViewer({ containerId: "myCanvas2"});
|
||||
const viewer3 = new DxfViewer(config);
|
||||
const fontFiles = ["./demo/three/fonts/hztxt.shx", "./demo/three/fonts/simplex.shx"];
|
||||
await viewer1.setFont(fontFiles);
|
||||
await viewer2.setFont(fontFiles);
|
||||
await viewer3.setFont(fontFiles);
|
||||
|
||||
const onProgress = (event) => {
|
||||
let type = "Loading progress";
|
||||
if (event.type === "parseProgress") {
|
||||
type = "Parsing progress";
|
||||
}
|
||||
const progress = ((event.loaded * 100) / event.total).toFixed(2);
|
||||
console.log(`[Demo] ${type}: ${progress}%`);
|
||||
};
|
||||
await viewer1.loadModelAsync(modelConfig1, onProgress);
|
||||
await viewer2.loadModelAsync(modelConfig2, onProgress);
|
||||
await viewer3.compare(url1, url2, onProgress).then(() => {
|
||||
console.log(`[Demo] Compared models: ${url1}, ${url2}`);
|
||||
if (!viewer3.layerManager) {
|
||||
viewer3.layerManager = new LayerManager(viewer3);
|
||||
}
|
||||
if (!viewer3.dxfCompareSidePanel) {
|
||||
viewer3.dxfCompareSidePanel = new DxfCompareSidePanel(viewer3);
|
||||
}
|
||||
});
|
||||
|
||||
// as a demo page, add dxfSettingsPanel to window!
|
||||
window.dxfSettingsPanel = new DxfSettingsPanel(viewer3);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
115
public/demo/empty_dxf_project.html
Normal file
@ -0,0 +1,115 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<link rel="stylesheet" href="./demo/layerManager/layerManager.css">
|
||||
<link rel="stylesheet" href="./demo/settings/SettingsPanel.css">
|
||||
<style>
|
||||
.upload-btn {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.upload-btn button {
|
||||
width: 0.1px;
|
||||
height: 0.1px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.upload-btn label {
|
||||
color: #353535;
|
||||
background: gray;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
/*transition: ease 0.2s background-color;*/
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding: 0.625rem 1.25rem;
|
||||
}
|
||||
|
||||
.upload-btn label:hover {
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
.upload-btn svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
fill: currentColor;
|
||||
margin-top: -0.25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myDxfViewerContainer" class="renderer-container"></div>
|
||||
</div>
|
||||
<div style="position: absolute; top: 10px; opacity: 0.6; width: 100%;text-align: center;">
|
||||
<div class="upload-btn" id="uploadBtn">
|
||||
<button id="uploadModelFile" type="button">点此上传本地模型文件</button>
|
||||
<label for="uploadModelFile" title="">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"></path></svg>
|
||||
<span>Upload dxf</span>
|
||||
</label>
|
||||
<div style="margin-top: 1em;">
|
||||
<input id="fileUrlInput" style="display: inline-block; width: 20em; height: 2em;">
|
||||
<button
|
||||
style="width: 8em; height: 2em; color: #fff; overflow: auto; z-index: 1; opacity: 1; background: #000;"
|
||||
id="loadDxf">加载DXF
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { DxfViewer, LocalDxfUploader } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
import DxfSettingsPanel from './demo/settings/DxfSettingsPanel.js';
|
||||
import LayerManager from './demo/layerManager/LayerManager.js';
|
||||
|
||||
const config = {
|
||||
containerId: "myDxfViewerContainer",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: true,
|
||||
enableToolbar: true,
|
||||
enableBottomBar: true,
|
||||
enableSpinner: true,
|
||||
enableProgressBar: true,
|
||||
enableLayoutBar: true,
|
||||
};
|
||||
const viewer = new DxfViewer(config);
|
||||
// const fontFiles = ["three/fonts/Microsoft_YaHei_Regular.typeface.json"];
|
||||
const fontFiles = ["./demo/three/fonts/hztxt.shx", "./demo/three/fonts/simplex.shx"];
|
||||
await viewer.setFont(fontFiles);
|
||||
|
||||
const modelUploader = new LocalDxfUploader(viewer);
|
||||
modelUploader.onSuccess = () => {
|
||||
!viewer.layerManager && (viewer.layerManager = new LayerManager(viewer));
|
||||
}
|
||||
document.getElementById("uploadModelFile").onclick = function() {
|
||||
modelUploader.openFileBrowserToUpload();
|
||||
}
|
||||
document.getElementById("loadDxf").onclick = function() {
|
||||
const url = document.getElementById("fileUrlInput").value;
|
||||
if (url) {
|
||||
viewer.loadModelAsync({ src: url, merge: true }).then(() => {
|
||||
console.log(`[Demo] Loaded model ${url}`);
|
||||
!viewer.layerManager && (viewer.layerManager = new LayerManager(viewer));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// as a demo page, add dxfSettingsPanel to window!
|
||||
window.dxfSettingsPanel = new DxfSettingsPanel(viewer);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
122
public/demo/empty_model_project.html
Normal file
@ -0,0 +1,122 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<style>
|
||||
.upload-btn {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.upload-btn button {
|
||||
width: 0.1px;
|
||||
height: 0.1px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.upload-btn label {
|
||||
color: #353535;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
transition: ease 0.2s;
|
||||
transition-property: background;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding: 0.625rem 1.25rem;
|
||||
}
|
||||
|
||||
.upload-btn label:hover {
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
.upload-btn svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
fill: currentColor;
|
||||
margin-top: -0.25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myBimViewerContainer" class="renderer-container"></div>
|
||||
</div>
|
||||
<div style="position: absolute; top: 10px; opacity: 0.6; width: 100%;text-align: center;">
|
||||
<div class="upload-btn" id="uploadBtn">
|
||||
<button id="uploadModelFile" type="button">点此上传本地模型文件</button>
|
||||
<label for="uploadModelFile" title="支持 gltf, dxf, obj, stl, fbx, ifc, dae等。只支持单模型文件,不支持链接文件。也就是几何体、材质都要内嵌在单一模型文件中。">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"></path></svg>
|
||||
<span>Upload model</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { BimViewer, ToolbarMenuId, LocalModelUploader } from "./demo/libs/gemini-viewer.esm.min.js";
|
||||
|
||||
const project = {
|
||||
id: "empty_project",
|
||||
name: "Empty project",
|
||||
thumbnail: "./demo/projects/empty_project/thumbnail.png",
|
||||
camera: {
|
||||
},
|
||||
models: [{
|
||||
"name": "model 01",
|
||||
"src": "",
|
||||
"rotation": [0, 0, 0],
|
||||
"scale": [1, 1, 1],
|
||||
"merge": false,
|
||||
"visible": false
|
||||
}],
|
||||
};
|
||||
const bimViewer = new BimViewer(
|
||||
{
|
||||
containerId: "myBimViewerContainer",
|
||||
enableAxisGizmo: true,
|
||||
enableStats: true,
|
||||
toolbarMenuConfig: {
|
||||
[ToolbarMenuId.BimTree]: { visible: false },
|
||||
},
|
||||
enableBottomBar: true,
|
||||
enableNavCube: true,
|
||||
enableContextMenu: true,
|
||||
},
|
||||
project.camera
|
||||
);
|
||||
|
||||
// loadProjectModel
|
||||
let counter = 0; // to indicate how many models are loading
|
||||
project.models.forEach((modelCfg) => {
|
||||
if (modelCfg.visible === false) {
|
||||
// visible is true by default
|
||||
return; // only load visible ones
|
||||
}
|
||||
counter++;
|
||||
bimViewer.loadModel(modelCfg, (event) => {
|
||||
console.log(`[Demo] Loading model ${modelCfg.src}`);
|
||||
}, (event) => {
|
||||
console.error(`[Demo] Failed to load ${modelCfg.src}. " + event.message`);
|
||||
}
|
||||
).then(() => {
|
||||
console.log(`[Demo] Loaded model ${modelCfg.src}`);
|
||||
});
|
||||
});
|
||||
|
||||
const modelUploader = new LocalModelUploader(bimViewer);
|
||||
document.getElementById("uploadModelFile").onclick = function() {
|
||||
modelUploader.openFileBrowserToUpload();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
80
public/demo/empty_vr_project.html
Normal file
@ -0,0 +1,80 @@
|
||||
<html>
|
||||
|
||||
<head>
|
||||
<link rel="icon" href="./demo/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="./demo/global.css" />
|
||||
<style>
|
||||
.upload-btn {
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.upload-btn button {
|
||||
width: 0.1px;
|
||||
height: 0.1px;
|
||||
opacity: 0;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
z-index: -1;
|
||||
}
|
||||
|
||||
.upload-btn label {
|
||||
color: #353535;
|
||||
border: 0;
|
||||
border-radius: 3px;
|
||||
transition: ease 0.2s background;
|
||||
font-size: 1rem;
|
||||
font-weight: 700;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
cursor: pointer;
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
padding: 0.625rem 1.25rem;
|
||||
}
|
||||
|
||||
.upload-btn label:hover {
|
||||
background: #DDD;
|
||||
}
|
||||
|
||||
.upload-btn svg {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: middle;
|
||||
fill: currentColor;
|
||||
margin-top: -0.25em;
|
||||
margin-right: 0.25em;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="viewerContainer">
|
||||
<div id="myVRViewerContainer" class="renderer-container"></div>
|
||||
</div>
|
||||
<div style="position: absolute; top: 10px; opacity: 0.6; width: 100%;text-align: center;">
|
||||
<div class="upload-btn" id="uploadBtn">
|
||||
<button id="uploadImage" type="button">点此上传本地图片文件</button>
|
||||
<label for="uploadImage" title="支持 png, jpg 等;请选择 1 张鱼眼图或 6 张图,若为 6 张,图片名须为 right/r, left/l, up/u, down/d, front/f, back/b">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="17" viewBox="0 0 20 17"><path d="M10 0l-5.2 4.9h3.3v5.1h3.8v-5.1h3.3l-5.2-4.9zm9.3 11.5l-3.2-2.1h-2l3.4 2.6h-3.5c-.1 0-.2.1-.2.1l-.8 2.3h-6l-.8-2.2c-.1-.1-.1-.2-.2-.2h-3.6l3.4-2.6h-2l-3.2 2.1c-.4.3-.7 1-.6 1.5l.6 3.1c.1.5.7.9 1.2.9h16.3c.6 0 1.1-.4 1.3-.9l.6-3.1c.1-.5-.2-1.2-.7-1.5z"></path></svg>
|
||||
<span>Upload image</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import { VRViewer, LocalImageUploader } from "./demio/libs/gemini-viewer.esm.min.js";
|
||||
|
||||
const config = {
|
||||
containerId: "myVRViewerContainer",
|
||||
enableAxisGizmo: true,
|
||||
enableBottomBar: true,
|
||||
}
|
||||
const vrViewer = new VRViewer(config);
|
||||
|
||||
const imageUploader = new LocalImageUploader(vrViewer);
|
||||
document.getElementById("uploadImage").onclick = function() {
|
||||
imageUploader.openFileBrowserToUpload();
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
BIN
public/demo/favicon.ico
Normal file
After Width: | Height: | Size: 6.7 KiB |
100
public/demo/global.css
Normal file
@ -0,0 +1,100 @@
|
||||
@charset "utf-8";
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
html {
|
||||
background-color: #fff;
|
||||
color: #000;
|
||||
font-size: 16px;
|
||||
}
|
||||
blockquote, body, button, dd, dl, figure, form, h1, h2, h3, h4, h5, h6, input, legend, ol, p, pre, td, textarea, th, ul, xmp {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
body, button, code, input, kbd, pre, samp, select, textarea, tt, xmp {
|
||||
line-height: 1.5;
|
||||
}
|
||||
big, button, h1, h2, h3, h4, h5, h6, input, select, small, textarea {
|
||||
font-size: 100%;
|
||||
}
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: tahoma, arial, "Hiragino Sans GB", "微软雅黑", simsun, sans-serif;
|
||||
}
|
||||
b, h1, h2, h3, h4, h5, h6, strong {
|
||||
font-weight: 400;
|
||||
}
|
||||
address, cite, dfn, em, i, optgroup, var {
|
||||
font-style: normal;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0;
|
||||
text-align: left;
|
||||
}
|
||||
caption, th {
|
||||
text-align: inherit;
|
||||
}
|
||||
menu, ol, ul {
|
||||
list-style: none;
|
||||
}
|
||||
img {
|
||||
border: 0;
|
||||
}
|
||||
button, img, input, object, select, textarea {
|
||||
vertical-align: middle;
|
||||
}
|
||||
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section {
|
||||
display: block;
|
||||
}
|
||||
audio, canvas, video {
|
||||
display: inline-block;
|
||||
}
|
||||
blockquote:after, blockquote:before, q:after, q:before {
|
||||
content: "\0020";
|
||||
}
|
||||
textarea {
|
||||
overflow: auto;
|
||||
resize: vertical;
|
||||
}
|
||||
a, button, input, select, textarea {
|
||||
border: none;
|
||||
outline: 0 none;
|
||||
}
|
||||
button::-moz-focus-inner, input::-moz-focus-inner {
|
||||
border: 0;
|
||||
padding: 0;
|
||||
}
|
||||
mark {
|
||||
background-color: transparent;
|
||||
}
|
||||
a, del, ins, s, u {
|
||||
text-decoration: none;
|
||||
}
|
||||
sub, sup {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
html {
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
body {
|
||||
color: #333;
|
||||
font-family: Arial, "Microsoft Yahei", "Helvetica Neue", Helvetica, sans-serif;
|
||||
line-height: 1;
|
||||
}
|
||||
a {
|
||||
color: #25a4bb;
|
||||
text-decoration: none;
|
||||
}
|
||||
::-webkit-scrollbar {
|
||||
height: 1px;
|
||||
width: 5px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
background: rgba(0, 0, 0, .1);
|
||||
border-radius: 10px;
|
||||
}
|
||||
::-webkit-scrollbar-track {
|
||||
background: #ededed;
|
||||
border-radius: 4px;
|
||||
}
|
539
public/demo/iconfont/demo.css
Normal file
@ -0,0 +1,539 @@
|
||||
/* Logo 字体 */
|
||||
@font-face {
|
||||
font-family: "iconfont logo";
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834');
|
||||
src: url('https://at.alicdn.com/t/font_985780_km7mi63cihi.eot?t=1545807318834#iefix') format('embedded-opentype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.woff?t=1545807318834') format('woff'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.ttf?t=1545807318834') format('truetype'),
|
||||
url('https://at.alicdn.com/t/font_985780_km7mi63cihi.svg?t=1545807318834#iconfont') format('svg');
|
||||
}
|
||||
|
||||
.logo {
|
||||
font-family: "iconfont logo";
|
||||
font-size: 160px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
/* tabs */
|
||||
.nav-tabs {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.nav-tabs .nav-more {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
height: 42px;
|
||||
line-height: 42px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
#tabs {
|
||||
border-bottom: 1px solid #eee;
|
||||
}
|
||||
|
||||
#tabs li {
|
||||
cursor: pointer;
|
||||
width: 100px;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border-bottom: 2px solid transparent;
|
||||
position: relative;
|
||||
z-index: 1;
|
||||
margin-bottom: -1px;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
|
||||
#tabs .active {
|
||||
border-bottom-color: #f00;
|
||||
color: #222;
|
||||
}
|
||||
|
||||
.tab-container .content {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 页面布局 */
|
||||
.main {
|
||||
padding: 30px 100px;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.main .logo {
|
||||
color: #333;
|
||||
text-align: left;
|
||||
margin-bottom: 30px;
|
||||
line-height: 1;
|
||||
height: 110px;
|
||||
margin-top: -50px;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
font-size: 160px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.helps {
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.helps pre {
|
||||
padding: 20px;
|
||||
margin: 10px 0;
|
||||
border: solid 1px #e7e1cd;
|
||||
background-color: #fffdef;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.icon_lists {
|
||||
width: 100% !important;
|
||||
overflow: hidden;
|
||||
*zoom: 1;
|
||||
}
|
||||
|
||||
.icon_lists li {
|
||||
width: 100px;
|
||||
margin-bottom: 10px;
|
||||
margin-right: 20px;
|
||||
text-align: center;
|
||||
list-style: none !important;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.icon_lists li .code-name {
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.icon_lists .icon {
|
||||
display: block;
|
||||
height: 100px;
|
||||
line-height: 100px;
|
||||
font-size: 42px;
|
||||
margin: 10px auto;
|
||||
color: #333;
|
||||
-webkit-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
-moz-transition: font-size 0.25s linear, width 0.25s linear;
|
||||
transition: font-size 0.25s linear, width 0.25s linear;
|
||||
}
|
||||
|
||||
.icon_lists .icon:hover {
|
||||
font-size: 100px;
|
||||
}
|
||||
|
||||
.icon_lists .svg-icon {
|
||||
/* 通过设置 font-size 来改变图标大小 */
|
||||
width: 1em;
|
||||
/* 图标和文字相邻时,垂直对齐 */
|
||||
vertical-align: -0.15em;
|
||||
/* 通过设置 color 来改变 SVG 的颜色/fill */
|
||||
fill: currentColor;
|
||||
/* path 和 stroke 溢出 viewBox 部分在 IE 下会显示
|
||||
normalize.css 中也包含这行 */
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.icon_lists li .name,
|
||||
.icon_lists li .code-name {
|
||||
color: #666;
|
||||
}
|
||||
|
||||
/* markdown 样式 */
|
||||
.markdown {
|
||||
color: #666;
|
||||
font-size: 14px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.highlight {
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.markdown img {
|
||||
vertical-align: middle;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
color: #404040;
|
||||
font-weight: 500;
|
||||
line-height: 40px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown h2,
|
||||
.markdown h3,
|
||||
.markdown h4,
|
||||
.markdown h5,
|
||||
.markdown h6 {
|
||||
color: #404040;
|
||||
margin: 1.6em 0 0.6em 0;
|
||||
font-weight: 500;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown h1 {
|
||||
font-size: 28px;
|
||||
}
|
||||
|
||||
.markdown h2 {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.markdown h3 {
|
||||
font-size: 16px;
|
||||
}
|
||||
|
||||
.markdown h4 {
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.markdown h5 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown h6 {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.markdown hr {
|
||||
height: 1px;
|
||||
border: 0;
|
||||
background: #e9e9e9;
|
||||
margin: 16px 0;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.markdown p {
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown>p,
|
||||
.markdown>blockquote,
|
||||
.markdown>.highlight,
|
||||
.markdown>ol,
|
||||
.markdown>ul {
|
||||
width: 80%;
|
||||
}
|
||||
|
||||
.markdown ul>li {
|
||||
list-style: circle;
|
||||
}
|
||||
|
||||
.markdown>ul li,
|
||||
.markdown blockquote ul>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown>ul li p,
|
||||
.markdown>ol li p {
|
||||
margin: 0.6em 0;
|
||||
}
|
||||
|
||||
.markdown ol>li {
|
||||
list-style: decimal;
|
||||
}
|
||||
|
||||
.markdown>ol li,
|
||||
.markdown blockquote ol>li {
|
||||
margin-left: 20px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.markdown code {
|
||||
margin: 0 3px;
|
||||
padding: 0 5px;
|
||||
background: #eee;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.markdown strong,
|
||||
.markdown b {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table {
|
||||
border-collapse: collapse;
|
||||
border-spacing: 0px;
|
||||
empty-cells: show;
|
||||
border: 1px solid #e9e9e9;
|
||||
width: 95%;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
white-space: nowrap;
|
||||
color: #333;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.markdown>table th,
|
||||
.markdown>table td {
|
||||
border: 1px solid #e9e9e9;
|
||||
padding: 8px 16px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.markdown>table th {
|
||||
background: #F7F7F7;
|
||||
}
|
||||
|
||||
.markdown blockquote {
|
||||
font-size: 90%;
|
||||
color: #999;
|
||||
border-left: 4px solid #e9e9e9;
|
||||
padding-left: 0.8em;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.markdown blockquote p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.markdown .anchor {
|
||||
opacity: 0;
|
||||
transition: opacity 0.3s ease;
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.markdown .waiting {
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.markdown h1:hover .anchor,
|
||||
.markdown h2:hover .anchor,
|
||||
.markdown h3:hover .anchor,
|
||||
.markdown h4:hover .anchor,
|
||||
.markdown h5:hover .anchor,
|
||||
.markdown h6:hover .anchor {
|
||||
opacity: 1;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.markdown>br,
|
||||
.markdown>p>br {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
|
||||
.hljs {
|
||||
display: block;
|
||||
background: white;
|
||||
padding: 0.5em;
|
||||
color: #333333;
|
||||
overflow-x: auto;
|
||||
}
|
||||
|
||||
.hljs-comment,
|
||||
.hljs-meta {
|
||||
color: #969896;
|
||||
}
|
||||
|
||||
.hljs-string,
|
||||
.hljs-variable,
|
||||
.hljs-template-variable,
|
||||
.hljs-strong,
|
||||
.hljs-emphasis,
|
||||
.hljs-quote {
|
||||
color: #df5000;
|
||||
}
|
||||
|
||||
.hljs-keyword,
|
||||
.hljs-selector-tag,
|
||||
.hljs-type {
|
||||
color: #a71d5d;
|
||||
}
|
||||
|
||||
.hljs-literal,
|
||||
.hljs-symbol,
|
||||
.hljs-bullet,
|
||||
.hljs-attribute {
|
||||
color: #0086b3;
|
||||
}
|
||||
|
||||
.hljs-section,
|
||||
.hljs-name {
|
||||
color: #63a35c;
|
||||
}
|
||||
|
||||
.hljs-tag {
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.hljs-title,
|
||||
.hljs-attr,
|
||||
.hljs-selector-id,
|
||||
.hljs-selector-class,
|
||||
.hljs-selector-attr,
|
||||
.hljs-selector-pseudo {
|
||||
color: #795da3;
|
||||
}
|
||||
|
||||
.hljs-addition {
|
||||
color: #55a532;
|
||||
background-color: #eaffea;
|
||||
}
|
||||
|
||||
.hljs-deletion {
|
||||
color: #bd2c00;
|
||||
background-color: #ffecec;
|
||||
}
|
||||
|
||||
.hljs-link {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* 代码高亮 */
|
||||
/* PrismJS 1.15.0
|
||||
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+javascript */
|
||||
/**
|
||||
* prism.js default theme for JavaScript, CSS and HTML
|
||||
* Based on dabblet (http://dabblet.com)
|
||||
* @author Lea Verou
|
||||
*/
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
color: black;
|
||||
background: none;
|
||||
text-shadow: 0 1px white;
|
||||
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
word-spacing: normal;
|
||||
word-break: normal;
|
||||
word-wrap: normal;
|
||||
line-height: 1.5;
|
||||
|
||||
-moz-tab-size: 4;
|
||||
-o-tab-size: 4;
|
||||
tab-size: 4;
|
||||
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
-ms-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::-moz-selection,
|
||||
pre[class*="language-"] ::-moz-selection,
|
||||
code[class*="language-"]::-moz-selection,
|
||||
code[class*="language-"] ::-moz-selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
pre[class*="language-"]::selection,
|
||||
pre[class*="language-"] ::selection,
|
||||
code[class*="language-"]::selection,
|
||||
code[class*="language-"] ::selection {
|
||||
text-shadow: none;
|
||||
background: #b3d4fc;
|
||||
}
|
||||
|
||||
@media print {
|
||||
|
||||
code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
text-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Code blocks */
|
||||
pre[class*="language-"] {
|
||||
padding: 1em;
|
||||
margin: .5em 0;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
:not(pre)>code[class*="language-"],
|
||||
pre[class*="language-"] {
|
||||
background: #f5f2f0;
|
||||
}
|
||||
|
||||
/* Inline code */
|
||||
:not(pre)>code[class*="language-"] {
|
||||
padding: .1em;
|
||||
border-radius: .3em;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.token.comment,
|
||||
.token.prolog,
|
||||
.token.doctype,
|
||||
.token.cdata {
|
||||
color: slategray;
|
||||
}
|
||||
|
||||
.token.punctuation {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.namespace {
|
||||
opacity: .7;
|
||||
}
|
||||
|
||||
.token.property,
|
||||
.token.tag,
|
||||
.token.boolean,
|
||||
.token.number,
|
||||
.token.constant,
|
||||
.token.symbol,
|
||||
.token.deleted {
|
||||
color: #905;
|
||||
}
|
||||
|
||||
.token.selector,
|
||||
.token.attr-name,
|
||||
.token.string,
|
||||
.token.char,
|
||||
.token.builtin,
|
||||
.token.inserted {
|
||||
color: #690;
|
||||
}
|
||||
|
||||
.token.operator,
|
||||
.token.entity,
|
||||
.token.url,
|
||||
.language-css .token.string,
|
||||
.style .token.string {
|
||||
color: #9a6e3a;
|
||||
background: hsla(0, 0%, 100%, .5);
|
||||
}
|
||||
|
||||
.token.atrule,
|
||||
.token.attr-value,
|
||||
.token.keyword {
|
||||
color: #07a;
|
||||
}
|
||||
|
||||
.token.function,
|
||||
.token.class-name {
|
||||
color: #DD4A68;
|
||||
}
|
||||
|
||||
.token.regex,
|
||||
.token.important,
|
||||
.token.variable {
|
||||
color: #e90;
|
||||
}
|
||||
|
||||
.token.important,
|
||||
.token.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.token.italic {
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.token.entity {
|
||||
cursor: help;
|
||||
}
|
487
public/demo/iconfont/demo_index.html
Normal file
@ -0,0 +1,487 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<title>iconfont Demo</title>
|
||||
<link rel="shortcut icon" href="//img.alicdn.com/imgextra/i2/O1CN01ZyAlrn1MwaMhqz36G_!!6000000001499-73-tps-64-64.ico" type="image/x-icon"/>
|
||||
<link rel="icon" type="image/svg+xml" href="//img.alicdn.com/imgextra/i4/O1CN01EYTRnJ297D6vehehJ_!!6000000008020-55-tps-64-64.svg"/>
|
||||
<link rel="stylesheet" href="https://g.alicdn.com/thx/cube/1.3.2/cube.min.css">
|
||||
<link rel="stylesheet" href="demo.css">
|
||||
<link rel="stylesheet" href="iconfont.css">
|
||||
<script src="iconfont.js"></script>
|
||||
<!-- jQuery -->
|
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/7bfddb60-08e8-11e9-9b04-53e73bb6408b.js"></script>
|
||||
<!-- 代码高亮 -->
|
||||
<script src="https://a1.alicdn.com/oss/uploads/2018/12/26/a3f714d0-08e6-11e9-8a15-ebf944d7534c.js"></script>
|
||||
<style>
|
||||
.main .logo {
|
||||
margin-top: 0;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
.main .logo a {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.main .logo .sub-title {
|
||||
margin-left: 0.5em;
|
||||
font-size: 22px;
|
||||
color: #fff;
|
||||
background: linear-gradient(-45deg, #3967FF, #B500FE);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="main">
|
||||
<h1 class="logo"><a href="https://www.iconfont.cn/" title="iconfont 首页" target="_blank">
|
||||
<img width="200" src="https://img.alicdn.com/imgextra/i3/O1CN01Mn65HV1FfSEzR6DKv_!!6000000000514-55-tps-228-59.svg">
|
||||
|
||||
</a></h1>
|
||||
<div class="nav-tabs">
|
||||
<ul id="tabs" class="dib-box">
|
||||
<li class="dib active"><span>Unicode</span></li>
|
||||
<li class="dib"><span>Font class</span></li>
|
||||
<li class="dib"><span>Symbol</span></li>
|
||||
</ul>
|
||||
|
||||
<a href="https://www.iconfont.cn/manage/index?manage_type=myprojects&projectId=2522399" target="_blank" class="nav-more">查看项目</a>
|
||||
|
||||
</div>
|
||||
<div class="tab-container">
|
||||
<div class="content unicode" style="display: block;">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">cutting</div>
|
||||
<div class="code-name">&#xe683;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">model & plane-overlay</div>
|
||||
<div class="code-name">&#xe6a2;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">first view-filled</div>
|
||||
<div class="code-name">&#xe6c0;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">measure-area</div>
|
||||
<div class="code-name">&#xe6c1;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">measure-filled</div>
|
||||
<div class="code-name">&#xe6c4;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">measure-angle</div>
|
||||
<div class="code-name">&#xe6c6;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">measure-distance</div>
|
||||
<div class="code-name">&#xe6ca;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">weather control-filled</div>
|
||||
<div class="code-name">&#xe6cb;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">configuration</div>
|
||||
<div class="code-name">&#xe6cc;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">cloud download-filled</div>
|
||||
<div class="code-name">&#xe71f;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">cloud upload-filled</div>
|
||||
<div class="code-name">&#xe721;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">phase-review</div>
|
||||
<div class="code-name">&#xe786;</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont"></span>
|
||||
<div class="name">data-space planning</div>
|
||||
<div class="code-name">&#xe791;</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="unicode-">Unicode 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>Unicode 是字体在网页端最原始的应用方式,特点是:</p>
|
||||
<ul>
|
||||
<li>支持按字体的方式去动态调整图标大小,颜色等等。</li>
|
||||
<li>默认情况下不支持多色,直接添加多色图标会自动去色。</li>
|
||||
</ul>
|
||||
<blockquote>
|
||||
<p>注意:新版 iconfont 支持两种方式引用多色图标:SVG symbol 引用方式和彩色字体图标模式。(使用彩色字体图标需要在「编辑项目」中开启「彩色」选项后并重新生成。)</p>
|
||||
</blockquote>
|
||||
<p>Unicode 使用步骤如下:</p>
|
||||
<h3 id="-font-face">第一步:拷贝项目下面生成的 <code>@font-face</code></h3>
|
||||
<pre><code class="language-css"
|
||||
>@font-face {
|
||||
font-family: 'iconfont';
|
||||
src: url('iconfont.woff2?t=1620285948639') format('woff2'),
|
||||
url('iconfont.woff?t=1620285948639') format('woff'),
|
||||
url('iconfont.ttf?t=1620285948639') format('truetype');
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
|
||||
<pre><code class="language-css"
|
||||
>.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
</code></pre>
|
||||
<h3 id="-">第三步:挑选相应图标并获取字体编码,应用于页面</h3>
|
||||
<pre>
|
||||
<code class="language-html"
|
||||
><span class="iconfont">&#x33;</span>
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>"iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content font-class">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-clip-plane"></span>
|
||||
<div class="name">
|
||||
cutting
|
||||
</div>
|
||||
<div class="code-name">.icon-clip-plane
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-clip-box"></span>
|
||||
<div class="name">
|
||||
model & plane-overlay
|
||||
</div>
|
||||
<div class="code-name">.icon-clip-box
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-firstview-filled"></span>
|
||||
<div class="name">
|
||||
first view-filled
|
||||
</div>
|
||||
<div class="code-name">.icon-firstview-filled
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-measure-area"></span>
|
||||
<div class="name">
|
||||
measure-area
|
||||
</div>
|
||||
<div class="code-name">.icon-measure-area
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-measure-filled"></span>
|
||||
<div class="name">
|
||||
measure-filled
|
||||
</div>
|
||||
<div class="code-name">.icon-measure-filled
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-measure-angle"></span>
|
||||
<div class="name">
|
||||
measure-angle
|
||||
</div>
|
||||
<div class="code-name">.icon-measure-angle
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-measure-distance"></span>
|
||||
<div class="name">
|
||||
measure-distance
|
||||
</div>
|
||||
<div class="code-name">.icon-measure-distance
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-weathercontrol-filled"></span>
|
||||
<div class="name">
|
||||
weather control-filled
|
||||
</div>
|
||||
<div class="code-name">.icon-weathercontrol-filled
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-configuration"></span>
|
||||
<div class="name">
|
||||
configuration
|
||||
</div>
|
||||
<div class="code-name">.icon-configuration
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-clouddownload-filled"></span>
|
||||
<div class="name">
|
||||
cloud download-filled
|
||||
</div>
|
||||
<div class="code-name">.icon-clouddownload-filled
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-cloudupload-filled"></span>
|
||||
<div class="name">
|
||||
cloud upload-filled
|
||||
</div>
|
||||
<div class="code-name">.icon-cloudupload-filled
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-phase-review"></span>
|
||||
<div class="name">
|
||||
phase-review
|
||||
</div>
|
||||
<div class="code-name">.icon-phase-review
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<span class="icon iconfont icon-data-spaceplanning"></span>
|
||||
<div class="name">
|
||||
data-space planning
|
||||
</div>
|
||||
<div class="code-name">.icon-data-spaceplanning
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="font-class-">font-class 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>font-class 是 Unicode 使用方式的一种变种,主要是解决 Unicode 书写不直观,语意不明确的问题。</p>
|
||||
<p>与 Unicode 使用方式相比,具有如下特点:</p>
|
||||
<ul>
|
||||
<li>相比于 Unicode 语意明确,书写更直观。可以很容易分辨这个 icon 是什么。</li>
|
||||
<li>因为使用 class 来定义图标,所以当要替换图标时,只需要修改 class 里面的 Unicode 引用。</li>
|
||||
</ul>
|
||||
<p>使用步骤如下:</p>
|
||||
<h3 id="-fontclass-">第一步:引入项目下面生成的 fontclass 代码:</h3>
|
||||
<pre><code class="language-html"><link rel="stylesheet" href="./iconfont.css">
|
||||
</code></pre>
|
||||
<h3 id="-">第二步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||
<pre><code class="language-html"><span class="iconfont icon-xxx"></span>
|
||||
</code></pre>
|
||||
<blockquote>
|
||||
<p>"
|
||||
iconfont" 是你项目下的 font-family。可以通过编辑项目查看,默认是 "iconfont"。</p>
|
||||
</blockquote>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content symbol">
|
||||
<ul class="icon_lists dib-box">
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-clip-plane"></use>
|
||||
</svg>
|
||||
<div class="name">cutting</div>
|
||||
<div class="code-name">#icon-clip-plane</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-clip-box"></use>
|
||||
</svg>
|
||||
<div class="name">model & plane-overlay</div>
|
||||
<div class="code-name">#icon-clip-box</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-firstview-filled"></use>
|
||||
</svg>
|
||||
<div class="name">first view-filled</div>
|
||||
<div class="code-name">#icon-firstview-filled</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-measure-area"></use>
|
||||
</svg>
|
||||
<div class="name">measure-area</div>
|
||||
<div class="code-name">#icon-measure-area</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-measure-filled"></use>
|
||||
</svg>
|
||||
<div class="name">measure-filled</div>
|
||||
<div class="code-name">#icon-measure-filled</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-measure-angle"></use>
|
||||
</svg>
|
||||
<div class="name">measure-angle</div>
|
||||
<div class="code-name">#icon-measure-angle</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-measure-distance"></use>
|
||||
</svg>
|
||||
<div class="name">measure-distance</div>
|
||||
<div class="code-name">#icon-measure-distance</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-weathercontrol-filled"></use>
|
||||
</svg>
|
||||
<div class="name">weather control-filled</div>
|
||||
<div class="code-name">#icon-weathercontrol-filled</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-configuration"></use>
|
||||
</svg>
|
||||
<div class="name">configuration</div>
|
||||
<div class="code-name">#icon-configuration</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-clouddownload-filled"></use>
|
||||
</svg>
|
||||
<div class="name">cloud download-filled</div>
|
||||
<div class="code-name">#icon-clouddownload-filled</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-cloudupload-filled"></use>
|
||||
</svg>
|
||||
<div class="name">cloud upload-filled</div>
|
||||
<div class="code-name">#icon-cloudupload-filled</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-phase-review"></use>
|
||||
</svg>
|
||||
<div class="name">phase-review</div>
|
||||
<div class="code-name">#icon-phase-review</div>
|
||||
</li>
|
||||
|
||||
<li class="dib">
|
||||
<svg class="icon svg-icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-data-spaceplanning"></use>
|
||||
</svg>
|
||||
<div class="name">data-space planning</div>
|
||||
<div class="code-name">#icon-data-spaceplanning</div>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
<div class="article markdown">
|
||||
<h2 id="symbol-">Symbol 引用</h2>
|
||||
<hr>
|
||||
|
||||
<p>这是一种全新的使用方式,应该说这才是未来的主流,也是平台目前推荐的用法。相关介绍可以参考这篇<a href="">文章</a>
|
||||
这种用法其实是做了一个 SVG 的集合,与另外两种相比具有如下特点:</p>
|
||||
<ul>
|
||||
<li>支持多色图标了,不再受单色限制。</li>
|
||||
<li>通过一些技巧,支持像字体那样,通过 <code>font-size</code>, <code>color</code> 来调整样式。</li>
|
||||
<li>兼容性较差,支持 IE9+,及现代浏览器。</li>
|
||||
<li>浏览器渲染 SVG 的性能一般,还不如 png。</li>
|
||||
</ul>
|
||||
<p>使用步骤如下:</p>
|
||||
<h3 id="-symbol-">第一步:引入项目下面生成的 symbol 代码:</h3>
|
||||
<pre><code class="language-html"><script src="./iconfont.js"></script>
|
||||
</code></pre>
|
||||
<h3 id="-css-">第二步:加入通用 CSS 代码(引入一次就行):</h3>
|
||||
<pre><code class="language-html"><style>
|
||||
.icon {
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
vertical-align: -0.15em;
|
||||
fill: currentColor;
|
||||
overflow: hidden;
|
||||
}
|
||||
</style>
|
||||
</code></pre>
|
||||
<h3 id="-">第三步:挑选相应图标并获取类名,应用于页面:</h3>
|
||||
<pre><code class="language-html"><svg class="icon" aria-hidden="true">
|
||||
<use xlink:href="#icon-xxx"></use>
|
||||
</svg>
|
||||
</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
$('.tab-container .content:first').show()
|
||||
|
||||
$('#tabs li').click(function (e) {
|
||||
var tabContent = $('.tab-container .content')
|
||||
var index = $(this).index()
|
||||
|
||||
if ($(this).hasClass('active')) {
|
||||
return
|
||||
} else {
|
||||
$('#tabs li').removeClass('active')
|
||||
$(this).addClass('active')
|
||||
|
||||
tabContent.hide().eq(index).fadeIn()
|
||||
}
|
||||
})
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
67
public/demo/iconfont/iconfont.css
Normal file
@ -0,0 +1,67 @@
|
||||
@font-face {
|
||||
font-family: "iconfont"; /* Project id 2522399 */
|
||||
src: url('iconfont.woff2?t=1620285948639') format('woff2'),
|
||||
url('iconfont.woff?t=1620285948639') format('woff'),
|
||||
url('iconfont.ttf?t=1620285948639') format('truetype');
|
||||
}
|
||||
|
||||
.iconfont {
|
||||
font-family: "iconfont" !important;
|
||||
font-size: 16px;
|
||||
font-style: normal;
|
||||
-webkit-font-smoothing: antialiased;
|
||||
-moz-osx-font-smoothing: grayscale;
|
||||
}
|
||||
|
||||
.icon-clip-plane:before {
|
||||
content: "\e683";
|
||||
}
|
||||
|
||||
.icon-clip-box:before {
|
||||
content: "\e6a2";
|
||||
}
|
||||
|
||||
.icon-firstview-filled:before {
|
||||
content: "\e6c0";
|
||||
}
|
||||
|
||||
.icon-measure-area:before {
|
||||
content: "\e6c1";
|
||||
}
|
||||
|
||||
.icon-measure-filled:before {
|
||||
content: "\e6c4";
|
||||
}
|
||||
|
||||
.icon-measure-angle:before {
|
||||
content: "\e6c6";
|
||||
}
|
||||
|
||||
.icon-measure-distance:before {
|
||||
content: "\e6ca";
|
||||
}
|
||||
|
||||
.icon-weathercontrol-filled:before {
|
||||
content: "\e6cb";
|
||||
}
|
||||
|
||||
.icon-configuration:before {
|
||||
content: "\e6cc";
|
||||
}
|
||||
|
||||
.icon-clouddownload-filled:before {
|
||||
content: "\e71f";
|
||||
}
|
||||
|
||||
.icon-cloudupload-filled:before {
|
||||
content: "\e721";
|
||||
}
|
||||
|
||||
.icon-phase-review:before {
|
||||
content: "\e786";
|
||||
}
|
||||
|
||||
.icon-data-spaceplanning:before {
|
||||
content: "\e791";
|
||||
}
|
||||
|
1
public/demo/iconfont/iconfont.js
Normal file
BIN
public/demo/iconfont/iconfont.ttf
Normal file
BIN
public/demo/iconfont/iconfont.woff
Normal file
BIN
public/demo/iconfont/iconfont.woff2
Normal file
BIN
public/demo/images/annotation.png
Normal file
After Width: | Height: | Size: 8.4 KiB |
BIN
public/demo/images/arrow.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
public/demo/images/arrow_left.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/demo/images/arrow_right.png
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
public/demo/images/default-thumbnail.jpg
Normal file
After Width: | Height: | Size: 90 KiB |
BIN
public/demo/images/envmap/city_street_256.hdr
Normal file
BIN
public/demo/images/envmap/footprint_court_2k.hdr
Normal file
BIN
public/demo/images/envmap/venice_sunset_1k.hdr
Normal file
BIN
public/demo/images/skybox/cloudy/back.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
public/demo/images/skybox/cloudy/bottom.jpg
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
public/demo/images/skybox/cloudy/front.jpg
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
public/demo/images/skybox/cloudy/left.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
public/demo/images/skybox/cloudy/right.jpg
Normal file
After Width: | Height: | Size: 42 KiB |
BIN
public/demo/images/skybox/cloudy/top.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
BIN
public/demo/images/sunflower.jpg
Normal file
After Width: | Height: | Size: 252 KiB |
BIN
public/demo/images/terrain/grass.jpg
Normal file
After Width: | Height: | Size: 2.5 MiB |
BIN
public/demo/images/vr/album_0/主卧.jpg
Normal file
After Width: | Height: | Size: 3.0 MiB |
BIN
public/demo/images/vr/album_0/主卧/back.jpg
Normal file
After Width: | Height: | Size: 2.2 MiB |
BIN
public/demo/images/vr/album_0/主卧/bottom.jpg
Normal file
After Width: | Height: | Size: 3.4 MiB |
BIN
public/demo/images/vr/album_0/主卧/front.jpg
Normal file
After Width: | Height: | Size: 2.1 MiB |
BIN
public/demo/images/vr/album_0/主卧/left.jpg
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
public/demo/images/vr/album_0/主卧/right.jpg
Normal file
After Width: | Height: | Size: 2.5 MiB |
BIN
public/demo/images/vr/album_0/主卧/top.jpg
Normal file
After Width: | Height: | Size: 771 KiB |
BIN
public/demo/images/vr/album_0/客厅.jpg
Normal file
After Width: | Height: | Size: 5.3 MiB |
BIN
public/demo/images/vr/album_0/客厅/back.jpg
Normal file
After Width: | Height: | Size: 184 KiB |
BIN
public/demo/images/vr/album_0/客厅/bottom.jpg
Normal file
After Width: | Height: | Size: 319 KiB |
BIN
public/demo/images/vr/album_0/客厅/front.jpg
Normal file
After Width: | Height: | Size: 313 KiB |
BIN
public/demo/images/vr/album_0/客厅/left.jpg
Normal file
After Width: | Height: | Size: 242 KiB |
BIN
public/demo/images/vr/album_0/客厅/right.jpg
Normal file
After Width: | Height: | Size: 251 KiB |
BIN
public/demo/images/vr/album_0/客厅/top.jpg
Normal file
After Width: | Height: | Size: 149 KiB |
BIN
public/demo/images/vr/album_0/客餐厅.jpg
Normal file
After Width: | Height: | Size: 6.1 MiB |
BIN
public/demo/images/vr/album_0/客餐厅/back.jpg
Normal file
After Width: | Height: | Size: 308 KiB |
BIN
public/demo/images/vr/album_0/客餐厅/bottom.jpg
Normal file
After Width: | Height: | Size: 445 KiB |
BIN
public/demo/images/vr/album_0/客餐厅/front.jpg
Normal file
After Width: | Height: | Size: 317 KiB |
BIN
public/demo/images/vr/album_0/客餐厅/left.jpg
Normal file
After Width: | Height: | Size: 330 KiB |
BIN
public/demo/images/vr/album_0/客餐厅/right.jpg
Normal file
After Width: | Height: | Size: 281 KiB |
BIN
public/demo/images/vr/album_0/客餐厅/top.jpg
Normal file
After Width: | Height: | Size: 166 KiB |
BIN
public/demo/images/vr/album_0/小孩房.jpg
Normal file
After Width: | Height: | Size: 3.2 MiB |
BIN
public/demo/images/vr/album_0/小孩房/back.jpg
Normal file
After Width: | Height: | Size: 186 KiB |
BIN
public/demo/images/vr/album_0/小孩房/bottom.jpg
Normal file
After Width: | Height: | Size: 200 KiB |
BIN
public/demo/images/vr/album_0/小孩房/front.jpg
Normal file
After Width: | Height: | Size: 144 KiB |
BIN
public/demo/images/vr/album_0/小孩房/left.jpg
Normal file
After Width: | Height: | Size: 263 KiB |
BIN
public/demo/images/vr/album_0/小孩房/right.jpg
Normal file
After Width: | Height: | Size: 95 KiB |
BIN
public/demo/images/vr/album_0/小孩房/top.jpg
Normal file
After Width: | Height: | Size: 117 KiB |
BIN
public/demo/images/vr/album_0/餐厅.jpg
Normal file
After Width: | Height: | Size: 5.7 MiB |
BIN
public/demo/images/vr/album_0/餐厅/back.jpg
Normal file
After Width: | Height: | Size: 309 KiB |
BIN
public/demo/images/vr/album_0/餐厅/bottom.jpg
Normal file
After Width: | Height: | Size: 406 KiB |
BIN
public/demo/images/vr/album_0/餐厅/front.jpg
Normal file
After Width: | Height: | Size: 278 KiB |
BIN
public/demo/images/vr/album_0/餐厅/left.jpg
Normal file
After Width: | Height: | Size: 258 KiB |
BIN
public/demo/images/vr/album_0/餐厅/right.jpg
Normal file
After Width: | Height: | Size: 256 KiB |
BIN
public/demo/images/vr/album_0/餐厅/top.jpg
Normal file
After Width: | Height: | Size: 129 KiB |
BIN
public/demo/images/vr/no_image.png
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
public/demo/images/vr/vr_0/thumbnail/back.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
public/demo/images/vr/vr_0/thumbnail/bottom.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/demo/images/vr/vr_0/thumbnail/front.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
public/demo/images/vr/vr_0/thumbnail/left.jpg
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
public/demo/images/vr/vr_0/thumbnail/right.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/demo/images/vr/vr_0/thumbnail/top.jpg
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
public/demo/images/vr/vr_0/vr_0.jpg
Normal file
After Width: | Height: | Size: 9.4 MiB |
BIN
public/demo/images/vr/vr_1/back.jpg
Normal file
After Width: | Height: | Size: 397 KiB |
BIN
public/demo/images/vr/vr_1/bottom.jpg
Normal file
After Width: | Height: | Size: 544 KiB |
BIN
public/demo/images/vr/vr_1/front.jpg
Normal file
After Width: | Height: | Size: 120 KiB |
BIN
public/demo/images/vr/vr_1/left.jpg
Normal file
After Width: | Height: | Size: 292 KiB |
BIN
public/demo/images/vr/vr_1/right.jpg
Normal file
After Width: | Height: | Size: 425 KiB |
BIN
public/demo/images/vr/vr_1/thumbnail/back.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
public/demo/images/vr/vr_1/thumbnail/bottom.jpg
Normal file
After Width: | Height: | Size: 7.6 KiB |
BIN
public/demo/images/vr/vr_1/thumbnail/front.jpg
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
public/demo/images/vr/vr_1/thumbnail/left.jpg
Normal file
After Width: | Height: | Size: 7.2 KiB |
BIN
public/demo/images/vr/vr_1/thumbnail/right.jpg
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
public/demo/images/vr/vr_1/thumbnail/top.jpg
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
public/demo/images/vr/vr_1/top.jpg
Normal file
After Width: | Height: | Size: 125 KiB |
BIN
public/demo/images/vr/vr_2/back.jpg
Normal file
After Width: | Height: | Size: 1.6 MiB |
BIN
public/demo/images/vr/vr_2/bottom.jpg
Normal file
After Width: | Height: | Size: 2.9 MiB |
BIN
public/demo/images/vr/vr_2/front.jpg
Normal file
After Width: | Height: | Size: 1.1 MiB |
BIN
public/demo/images/vr/vr_2/left.jpg
Normal file
After Width: | Height: | Size: 1.5 MiB |