This commit is contained in:
parent
c966b1c617
commit
c40aeb1dfb
@ -9,3 +9,10 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pseudo-3d-layer {
|
||||||
|
position: fixed;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
<canvas id="three-viewport"></canvas>
|
<canvas id="three-viewport"></canvas>
|
||||||
|
|
||||||
|
<div id="pseudo-3d-layer"></div>
|
||||||
|
|
||||||
<script src="assets/javascripts/main.js"></script>
|
<script src="assets/javascripts/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
27
src/index.js
27
src/index.js
@ -1,8 +1,31 @@
|
|||||||
import ThreeViewport from "./three.js";
|
import WorldViewport from "./world-viewport.js";
|
||||||
import WebGL from "three/examples/jsm/capabilities/WebGL.js";
|
import WebGL from "three/examples/jsm/capabilities/WebGL.js";
|
||||||
|
import Pseudo3DLayer from "./pseudo-3d-layer.js";
|
||||||
|
|
||||||
if (WebGL.isWebGL2Available()) {
|
if (WebGL.isWebGL2Available()) {
|
||||||
new ThreeViewport(document.getElementById('three-viewport')).setup();
|
const canvas = document.getElementById('three-viewport');
|
||||||
|
const world = new WorldViewport(canvas);
|
||||||
|
world.setup();
|
||||||
|
console.log(world);
|
||||||
|
|
||||||
|
const container = document.getElementById('pseudo-3d-layer');
|
||||||
|
const layer = new Pseudo3DLayer(container);
|
||||||
|
layer.bind(world);
|
||||||
|
console.log(layer);
|
||||||
|
|
||||||
|
const test1 = document.createElement('div');
|
||||||
|
test1.style.width = '10%';
|
||||||
|
test1.style.height = '10%';
|
||||||
|
test1.style.background = 'red';
|
||||||
|
test1.style.pointerEvents = 'fill';
|
||||||
|
layer.add(test1, { x: 0, y: 0, z: 0 });
|
||||||
|
|
||||||
|
const test2 = document.createElement('div');
|
||||||
|
test2.style.width = '5%';
|
||||||
|
test2.style.height = '5%';
|
||||||
|
test2.style.background = 'green';
|
||||||
|
test2.style.pointerEvents = 'fill';
|
||||||
|
layer.add(test2, { x: 0, y: 0, z: 1 });
|
||||||
} else {
|
} else {
|
||||||
document.body.appendChild(WebGL.getWebGL2ErrorMessage());
|
document.body.appendChild(WebGL.getWebGL2ErrorMessage());
|
||||||
}
|
}
|
||||||
|
56
src/pseudo-3d-layer.js
Normal file
56
src/pseudo-3d-layer.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
export default class Pseudo3DLayer {
|
||||||
|
/** @param {HTMLDivElement} container */
|
||||||
|
constructor(container) {
|
||||||
|
this.container = container;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @param {WorldViewport} world */
|
||||||
|
bind(world) {
|
||||||
|
this.world = world;
|
||||||
|
this.originX = world.camera.position.z;
|
||||||
|
world.renderPseudo = this.render.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @type {[ { wrapper: HTMLDivElement, element: HTMLElement, x: (layer: Pseudo3DLayer) => number, y: (layer: Pseudo3DLayer) => number, z: (layer: Pseudo3DLayer) => number } ]} */
|
||||||
|
items = [];
|
||||||
|
/**
|
||||||
|
* @param {HTMLElement} element
|
||||||
|
* @param {{ x: number | (() => number), y?: number | (() => number), z?: number | (() => number) }} options
|
||||||
|
*/
|
||||||
|
add(element, options) {
|
||||||
|
const wrapper = document.createElement('div');
|
||||||
|
wrapper.style.position = 'absolute';
|
||||||
|
wrapper.style.width = '100%';
|
||||||
|
wrapper.style.height = '100%';
|
||||||
|
wrapper.appendChild(element);
|
||||||
|
this.container.appendChild(wrapper);
|
||||||
|
// const
|
||||||
|
const value = x => typeof x === 'function' ? x : () => (x || 0);
|
||||||
|
this.items.push({
|
||||||
|
wrapper,
|
||||||
|
element,
|
||||||
|
x: value(options.x),
|
||||||
|
y: value(options.y),
|
||||||
|
z: value(options.z),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static PixelToBlockMultiple = 40;
|
||||||
|
render(item) {
|
||||||
|
if (!item) return this.items.forEach(item => this.render(item));
|
||||||
|
|
||||||
|
const { innerWidth: windowWidth, innerHeight: windowHeight } = window;
|
||||||
|
const { clientWidth: width, clientHeight: height } = item.element;
|
||||||
|
const [ x, y, z ] = [ item.x(this), item.y(this), item.z(this) ];
|
||||||
|
const cameraZ = this.world.camera.position.z;
|
||||||
|
|
||||||
|
const top = windowHeight / 2 - height / 2 + y;
|
||||||
|
const left = windowWidth / 2 - width / 2
|
||||||
|
+ x
|
||||||
|
+ (this.originX - cameraZ) * Pseudo3DLayer.PixelToBlockMultiple
|
||||||
|
* (1 + z);
|
||||||
|
|
||||||
|
item.wrapper.style.top = `${top}px`;
|
||||||
|
item.wrapper.style.left = `${left}px`;
|
||||||
|
}
|
||||||
|
}
|
@ -34,7 +34,7 @@ const motionBlurShader = {
|
|||||||
`,
|
`,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default class ThreeViewport {
|
export default class WorldViewport {
|
||||||
/** @param {HTMLCanvasElement} canvas */
|
/** @param {HTMLCanvasElement} canvas */
|
||||||
constructor(canvas) {
|
constructor(canvas) {
|
||||||
this.canvas = canvas;
|
this.canvas = canvas;
|
||||||
@ -229,8 +229,6 @@ export default class ThreeViewport {
|
|||||||
this.camera.position.set(-34, -12, -0.1);
|
this.camera.position.set(-34, -12, -0.1);
|
||||||
this.camera.rotation.set(0, THREE.MathUtils.degToRad(270), 0);
|
this.camera.rotation.set(0, THREE.MathUtils.degToRad(270), 0);
|
||||||
|
|
||||||
// this.camera.position.z += -3;
|
|
||||||
|
|
||||||
this.controller();
|
this.controller();
|
||||||
this.animate();
|
this.animate();
|
||||||
}
|
}
|
||||||
@ -249,12 +247,13 @@ export default class ThreeViewport {
|
|||||||
this.canvas.addEventListener('touchstart', event => this.previousX = event.touches[0].clientX);
|
this.canvas.addEventListener('touchstart', event => this.previousX = event.touches[0].clientX);
|
||||||
this.canvas.addEventListener('touchmove', event => {
|
this.canvas.addEventListener('touchmove', event => {
|
||||||
const currentX = event.touches[0].clientX;
|
const currentX = event.touches[0].clientX;
|
||||||
if (this.previousX) this.targetZ += (this.previousX - currentX) * 0.02;
|
if (this.previousX) this.targetZ += (this.previousX - currentX) * 0.025;
|
||||||
this.previousX = currentX;
|
this.previousX = currentX;
|
||||||
});
|
});
|
||||||
window.addEventListener('touchend', () => this.previousX = null);
|
window.addEventListener('touchend', () => this.previousX = null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderPseudo;
|
||||||
animate() {
|
animate() {
|
||||||
requestAnimationFrame(this.animate.bind(this));
|
requestAnimationFrame(this.animate.bind(this));
|
||||||
|
|
||||||
@ -275,6 +274,8 @@ export default class ThreeViewport {
|
|||||||
|
|
||||||
this.animatePetals();
|
this.animatePetals();
|
||||||
|
|
||||||
|
if (this.renderPseudo) this.renderPseudo();
|
||||||
|
|
||||||
this.composer.render();
|
this.composer.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user