Published
Edited
Sep 25, 2021
Fork of Puzzle
3 forks
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
rotateInterface = {
let div = html`<div>
<style>
table.interface tr { margin:2px; border:0px;}
table.interface td.button {
cursor:pointer;
background:white;
border-radius:5px;
border:1px solid gray;
text-align:center;
}
button.interface {
cursor:pointer;
width:14em;
}
table.interface {
border-collapse:separate;
width:14em;
}
</style>
</div>`;
let reset = html`<button class=interface> Reset`;
reset.onclick = () => {
if (mutable rotInfo) return;
mutable rotInfo = { type: "reset" };
};
div.append(reset);
let table = html`<table class=interface>`;
div.append(table);
let buttonClick = rot => {
return () => {
if (mutable rotInfo) return;
mutable rotInfo = rot;
};
};

for (let i = -1; i <= 6; i++) {
let tr = html`<tr>`;
table.append(tr);
if (i == -1) {
tr.append(html`<td>`);
tr.append(html`<td>`);
let td = html`<td colspan=4 class=button>↓</td>`;
td.onclick = buttonClick({ type: "allcol", angle: 90 });
tr.append(td);
tr.append(html`<td>`);
tr.append(html`<td>`);
continue;
}
if (i == 6) {
tr.append(html`<td>`);
tr.append(html`<td>`);

let td = html`<td colspan=4 class=button>↑</td>`;
td.onclick = buttonClick({ type: "allcol", angle: -90 });
tr.append(td);
tr.append(html`<td>`);
tr.append(html`<td>`);
continue;
}

if (i == 1) {
let td = html`<td rowspan=4 class=button>→</td>`;
td.onclick = buttonClick({ type: "allrow", angle: 90 });
tr.append(td);
} else if (i == 0 || i == 5) {
tr.append(html`<td>`);
}
for (let j = 0; j <= 5; j++) {
if (i == j || i + j == 5) {
tr.append(html`<td>`);
continue;
}
let rot, sym;
if (i == 0)
[rot, sym] = [{ type: "col", row: 0, col: j - 1, angle: 90 }, "↓"];
else if (i == 5)
[rot, sym] = [{ type: "col", row: 0, col: j - 1, angle: -90 }, "↑"];
else if (j == 0)
[rot, sym] = [{ type: "row", row: 4 - i, col: 0, angle: 90 }, "→"];
else if (j == 5)
[rot, sym] = [{ type: "row", row: 4 - i, col: 0, angle: -90 }, "←"];
if (rot) {
let td = html`<td class=button>`;
tr.append(td);
td.onclick = buttonClick(rot);
td.append(sym);
} else tr.append(html`<td>`);
}
if (i == 1) {
let td = html`<td rowspan=4 class=button>←</td>`;
td.onclick = buttonClick({ type: "allrow", row: 0, col: 0, angle: -90 });
tr.append(td);
} else if (i == 0 || i == 5) {
tr.append(html`<td>`);
}
}
return div;
}
Insert cell
Insert cell
mutable rotInfo = null;
Insert cell
Insert cell
Insert cell
animation = {
if (rotInfo) {
let { type, row, col, angle } = rotInfo; // Currently ignored
let anims = [];
for (let i = 0; i < 4; i++) {
for (let j = 0; j < 4; j++) {
let c = cubes[i][j];
let [rx, ry, rz] = [0, 1, 2].map(
() => (Math.floor(Math.random() * 2) * Math.PI) / 2
);
let rot = new THREE.Quaternion().setFromEuler(
new THREE.Euler(rx, ry, rz)
);
anims.push({
q: c.quaternion,
oldq: c.quaternion.clone(),
newq: c.quaternion.clone().premultiply(rot)
});
}
}
for (let i = 0; i < 120; i++) {
for (let { q, oldq, newq } of anims) {
q.slerpQuaternions(oldq, newq, i / 119);
}
render();
yield i;
}
mutable rotInfo = null;
}
}
Insert cell
Insert cell
THREE = {
const THREE = (window.THREE = await require('three@0.128'));
await require('three@0.128/examples/js/controls/OrbitControls.js').catch(
() => {}
);
return THREE;
}
Insert cell
Insert cell
renderer = new THREE.WebGLRenderer({
canvas: html`<canvas width=${width} height=${(width / 16) * 9}>`,
antialias: true
})
Insert cell
camera = {
let camera = new THREE.PerspectiveCamera(70, 16 / 9, 0.1, 100);
camera.position.set(0, 0, 8);
return camera;
}
Insert cell
light = {
let group = new THREE.Group();
const dirLight = new THREE.DirectionalLight({ color: 0x777777 }); //new THREE.HemisphereLight();
dirLight.position.set(10, 10, 100);
const ambLight = new THREE.AmbientLight(0x777777);
group.add(dirLight, ambLight);
return group;
}
Insert cell
Insert cell
function createCube(x = 0, y = 0, z = 0, l = 1) {
let geometry = new THREE.BoxGeometry(l, l, l);
let material = new THREE.MeshStandardMaterial({ color: 0xCC0000 });
let mesh = new THREE.Mesh(geometry, material);
mesh.position.set(x, y, z);
return mesh;
}
Insert cell
Insert cell
Insert cell
function createCubeTex(x = 0, y = 0, z = 0, l = 1) {
return createCube(x, y, z, l);
}
Insert cell
import { texCubeGeometry, textureImage } from "@esperanc/textured-box"
Insert cell
Insert cell
Insert cell
images = [
await FileAttachment("img1.jpg").image(),
await FileAttachment("img2.jpg").image(),
await FileAttachment("img3.jpg").image(),
await FileAttachment("img4.jpg").image(),
await FileAttachment("img5.jpg").image(),
await FileAttachment("img6.jpg").image()
]
Insert cell
function createCubeTile(x = 0, y = 0, z = 0, l = 1, i = 0, j = 0) {
return createCube(x, y, z, l);
}
Insert cell
Insert cell
cubes = {
const m = 4;
const n = 4;
const w = 5;
const h = 5;
let cubes = [];
for (let i = 0; i < m; i++) {
cubes.push([]);
let x = w * (i / (m - 1) - 0.5);
for (let j = 0; j < n; j++) {
let y = h * (j / (n - 1) - 0.5);
cubes[i].push(
variant === "textured"
? createCubeTex(x, y, 0, w / (m - 1) - 0.04)
: variant === "plain"
? createCube(x, y, 0, w / (m - 1) - 0.04)
: createCubeTile(x, y, 0, w / (m - 1) - 0.04, i, j)
);
cubes[i].ij = [i, j];
}
}
return cubes;
}
Insert cell
cubeGroup = {
let cubeGroup = new THREE.Group();
for (let i = 0; i < cubes.length; i++)
for (let j = 0; j < cubes[0].length; j++) cubeGroup.add(cubes[i][j]);
return cubeGroup;
}
Insert cell
Insert cell
scene = {
let scene = new THREE.Scene();
scene.background = new THREE.Color(0xCCCCCC);
scene.add(cubeGroup)
scene.add(light)
return scene
}
Insert cell
Insert cell
controls = new THREE.OrbitControls(camera, renderer.domElement)
Insert cell
Insert cell
function render () {
controls.update();
renderer.render(scene, camera);
}
Insert cell
Insert cell
{
for (;;) {
render();
yield;
}
}
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more