307 lines
8.5 KiB
HTML
307 lines
8.5 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<!-- # (C) buildingSMART International -->
|
|
<!-- # published under MIT license -->
|
|
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<title>IFC5 View</title>
|
|
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD@24,200,0,0" />
|
|
<style>
|
|
* {
|
|
margin: 0;
|
|
padding: 0;
|
|
box-sizing: border-box;
|
|
font-family: "Roboto", "Helvetica", "Arial", sans-serif;
|
|
}
|
|
|
|
html,
|
|
body {
|
|
height: 100%;
|
|
}
|
|
|
|
body>div>div {
|
|
background: #eee;
|
|
overflow-y: scroll;
|
|
}
|
|
|
|
.container {
|
|
display: grid;
|
|
grid-template-rows: 2em 1fr 1fr 1fr 2em;
|
|
grid-template-columns: 1fr 2fr;
|
|
height: 100vh;
|
|
width: 100vw;
|
|
}
|
|
|
|
.layers {
|
|
grid-row: 2;
|
|
grid-column: 1;
|
|
}
|
|
|
|
.layers form {
|
|
margin: 0.5em;
|
|
}
|
|
|
|
.layers div div {
|
|
padding: 0.2em 0.5em;
|
|
border: solid 1px #ccc;
|
|
border-radius: 2px;
|
|
margin: 4px;
|
|
}
|
|
|
|
.layers div div span {
|
|
border-radius: 2px;
|
|
border: solid 1px #ddd;
|
|
display: block;
|
|
width: 20px;
|
|
height: 20px;
|
|
text-align: center;
|
|
float: right;
|
|
margin-left: 0.3em;
|
|
cursor: pointer;
|
|
}
|
|
|
|
.layers div div span:hover {
|
|
border-color: #aaa;
|
|
background-color: #ddd;
|
|
}
|
|
|
|
.tree-container {
|
|
grid-row: 3;
|
|
grid-column: 1;
|
|
}
|
|
|
|
.tree {
|
|
padding: 0.5em;
|
|
font-size: 0.8em;
|
|
}
|
|
|
|
.tree div div {
|
|
cursor: pointer;
|
|
padding: 0.2em 0 0 1em;
|
|
border-top: solid 1px #ddd;
|
|
line-height: 24px;
|
|
}
|
|
|
|
.tree div.selected {
|
|
background-color: rgba(255, 255, 0, 0.3);
|
|
}
|
|
|
|
.tree .material-symbols-outlined {
|
|
vertical-align: -6px;
|
|
margin-left: 0.5em;
|
|
}
|
|
|
|
.viewport {
|
|
grid-row: 2 / 4;
|
|
grid-column: 2;
|
|
background: linear-gradient(#80a1c2, #eee);
|
|
}
|
|
|
|
.attributes {
|
|
grid-row: 4;
|
|
grid-column: 1 / 3;
|
|
}
|
|
|
|
.attributes {
|
|
grid-row: 4;
|
|
grid-column: 1 / 3;
|
|
}
|
|
|
|
.attributes a {
|
|
text-decoration: none;
|
|
color: black;
|
|
border-bottom: dotted 1px gray;
|
|
}
|
|
|
|
.attributes a::before {
|
|
content: "\01F517";
|
|
}
|
|
|
|
.table {
|
|
font-size: 0.8em;
|
|
}
|
|
|
|
.header {
|
|
grid-row: 1;
|
|
grid-column: 1 / 3;
|
|
background: #666;
|
|
line-height: 2em;
|
|
border-bottom: solid 1px #555;
|
|
}
|
|
|
|
.header h1 {
|
|
font-size: 1em;
|
|
font-weight: 100;
|
|
padding-left: 0.5em;
|
|
}
|
|
|
|
.header h1 span {
|
|
font-size: 50%;
|
|
opacity: 0.5;
|
|
}
|
|
|
|
.footer {
|
|
grid-row: 5;
|
|
grid-column: 1 / 3;
|
|
background: white;
|
|
text-align: center;
|
|
font-size: 0.8em;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
table {
|
|
border: none;
|
|
border-collapse: collapse;
|
|
}
|
|
|
|
tr>td:first-child {
|
|
font-weight: bold;
|
|
}
|
|
|
|
td {
|
|
border-bottom: solid 1px #ddd;
|
|
vertical-align: top;
|
|
padding: 0.5em;
|
|
}
|
|
|
|
h2 {
|
|
background: #aaa;
|
|
color: white;
|
|
border: solid 1px #888;
|
|
font-size: 0.8em;
|
|
font-weight: 100;
|
|
padding: 0.2em 0.5em;
|
|
}
|
|
|
|
input,button {
|
|
padding: 0.5em !important;
|
|
border: solid 1px gray;
|
|
background: #eee;
|
|
display: inline-block;
|
|
vertical-align: middle;
|
|
height: 40px;
|
|
}
|
|
button {
|
|
padding: 10px !important;
|
|
border-radius: 0 5px 5px 0;
|
|
background-color: #ddd;
|
|
}
|
|
input {
|
|
width: 70%;
|
|
border-radius: 5px 0 0 5px;
|
|
border-width: 1px 0 1px 1px;
|
|
}
|
|
input[type=text] {
|
|
padding: 9px 0.5em !important;
|
|
}
|
|
|
|
.error-modal {
|
|
display: none;
|
|
position: absolute;
|
|
left: 15vw;
|
|
right: 15vw;
|
|
top: 15vw;
|
|
bottom: 15vw;
|
|
border: solid 2px red;
|
|
background-color: #fee;
|
|
cursor: pointer;
|
|
font-size: 150%;
|
|
}
|
|
|
|
.error-modal .message {
|
|
padding: 5vw;
|
|
display: inline-block;
|
|
}
|
|
|
|
.error-modal .message::before {
|
|
content: '\26A0 \A0 \A0';
|
|
}
|
|
</style>
|
|
</head>
|
|
|
|
<body>
|
|
<div class="container">
|
|
<div class="header"><h1>IFC5 view <span>BETA - IFC 5 is still heavily under development. Software tools (including this viewer), the IFC 5 datamodel, schema and examples are under constant change.</span></h1></div>
|
|
<div class='layers'>
|
|
<h2>Layer browser (lower takes priority)</h2>
|
|
<div></div>
|
|
<form id="fileForm">
|
|
<input type="file" id="fileInput" multiple="true" required><button class="file-upload-submit" type="submit">view ></button>
|
|
</form>
|
|
<form id="urlForm">
|
|
<input type="text" placeholder="url" id="urlInput" name="urlInput" required><button class="url-submit" type="submit">view ></button>
|
|
</form>
|
|
</div>
|
|
<div class='tree-container'>
|
|
<h2>Model tree</h2>
|
|
<div class='tree'>
|
|
|
|
</div>
|
|
</div>
|
|
<div class="viewport"></div>
|
|
<div class="attributes">
|
|
<h2>Selection attributes</h2>
|
|
<div class="table"></div>
|
|
</div>
|
|
<div class="footer">
|
|
This software is freely available for use, modification, and distribution under the MIT License, provided the original copyright notice and license terms are included.
|
|
<a href="https://github.com/buildingSMART/IFC5-development/">https://github.com/buildingSMART/IFC5-development/</a>
|
|
</div>
|
|
<div class="error-modal" onclick="document.querySelector('.error-modal').style.display = 'none';">
|
|
<span class="message"></span>
|
|
</div>
|
|
</div>
|
|
<script type="importmap">
|
|
{
|
|
"imports": {
|
|
"three": "https://cdn.jsdelivr.net/npm/three@0.177.0/build/three.module.js",
|
|
"three/addons/": "https://cdn.jsdelivr.net/npm/three@0.177.0/examples/jsm/"
|
|
}
|
|
}
|
|
</script>
|
|
<script type="module">
|
|
import addModel from './render.mjs';
|
|
|
|
document.querySelector('#fileForm').addEventListener('submit', function(event) {
|
|
event.preventDefault();
|
|
|
|
const fileInput = document.getElementById('fileInput');
|
|
for (const file of fileInput.files) {
|
|
const reader = new FileReader();
|
|
reader.onload = function(e) {
|
|
let json = null;
|
|
try {
|
|
json = JSON.parse(e.target.result);
|
|
} catch(e) {
|
|
document.querySelector('.error-modal .message').innerHTML = e.message;
|
|
document.querySelector('.error-modal').style.display = 'block';
|
|
}
|
|
if (json) {
|
|
addModel(file.name, json).catch(e => {
|
|
document.querySelector('.error-modal .message').innerHTML = e.message;
|
|
document.querySelector('.error-modal').style.display = 'block';
|
|
});
|
|
}
|
|
};
|
|
reader.readAsText(file);
|
|
}
|
|
});
|
|
|
|
document.querySelector('#urlForm').addEventListener('submit', function(event) {
|
|
event.preventDefault();
|
|
fetch(event.target.urlInput.value)
|
|
.then(r => r.json())
|
|
.then((j) => {
|
|
const name = event.target.urlInput.value.split('/').reverse()[0];
|
|
addModel(name, j);
|
|
})
|
|
.catch(e => {
|
|
document.querySelector('.error-modal .message').innerHTML = e.message;
|
|
document.querySelector('.error-modal').style.display = 'block';
|
|
});
|
|
});
|
|
</script>
|
|
</body>
|
|
|
|
</html>
|