Skip to content

Instantly share code, notes, and snippets.

@YeYongFen
Created February 1, 2023 09:04
Show Gist options
  • Select an option

  • Save YeYongFen/245931993c3dbd5fd0084d6c634430d5 to your computer and use it in GitHub Desktop.

Select an option

Save YeYongFen/245931993c3dbd5fd0084d6c634430d5 to your computer and use it in GitHub Desktop.

Revisions

  1. YeYongFen created this gist Feb 1, 2023.
    5 changes: 5 additions & 0 deletions index.html
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,5 @@
    <div class="annotation">
    <p><strong>Cube</strong></p>
    <p>In geometry, a cube is a three-dimensional solid object bounded by six square faces, facets or sides, with three meeting at each vertex.</p>
    </div>
    <canvas id="number" width="64" height="64"></canvas>
    175 changes: 175 additions & 0 deletions script.babel
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,175 @@
    // Number

    const canvas = document.getElementById("number");
    const ctx = canvas.getContext("2d");
    const x = 32;
    const y = 32;
    const radius = 30;
    const startAngle = 0;
    const endAngle = Math.PI * 2;

    ctx.fillStyle = "rgb(0, 0, 0)";
    ctx.beginPath();
    ctx.arc(x, y, radius, startAngle, endAngle);
    ctx.fill();

    ctx.strokeStyle = "rgb(255, 255, 255)";
    ctx.lineWidth = 3;
    ctx.beginPath();
    ctx.arc(x, y, radius, startAngle, endAngle);
    ctx.stroke();

    ctx.fillStyle = "rgb(255, 255, 255)";
    ctx.font = "32px sans-serif";
    ctx.textAlign = "center";
    ctx.textBaseline = "middle";
    ctx.fillText("1", x, y);

    // three.js

    let camera;
    let controls;
    let scene;
    let renderer;
    let sprite;
    let mesh;
    let spriteBehindObject;
    const annotation = document.querySelector(".annotation");

    init();
    animate();

    function init() {

    // Camera

    camera = new THREE.PerspectiveCamera(55, window.innerWidth / window.innerHeight, 2, 2000);
    camera.position.x = 750;
    camera.position.y = 500;
    camera.position.z = 1250;

    // Scene

    scene = new THREE.Scene();

    // Lights

    const lights = [];
    lights[0] = new THREE.PointLight(0xffffff, 1, 0);
    lights[1] = new THREE.PointLight(0xffffff, 1, 0);
    lights[2] = new THREE.PointLight(0xffffff, 1, 0);

    lights[0].position.set(0, 2000, 0);
    lights[1].position.set(1000, 2000, 1000);
    lights[2].position.set(-1000, -2000, -1000);

    scene.add(lights[0]);
    scene.add(lights[1]);
    scene.add(lights[2]);

    // Mesh

    const cubeGeometry = new THREE.BoxGeometry(500, 500, 500);

    mesh = new THREE.Mesh(
    cubeGeometry,
    new THREE.MeshPhongMaterial({
    color: 0x156289,
    emissive: 0x072534,
    side: THREE.DoubleSide,
    shading: THREE.FlatShading
    })
    );

    const line = new THREE.LineSegments(
    new THREE.WireframeGeometry(cubeGeometry),
    new THREE.LineBasicMaterial({
    color: 0xffffff,
    linewidth: 1,
    opacity: 0.25,
    transparent: true
    })
    );

    scene.add(mesh);
    scene.add(line);

    // Sprite

    const numberTexture = new THREE.CanvasTexture(
    document.querySelector("#number")
    );

    const spriteMaterial = new THREE.SpriteMaterial({
    map: numberTexture,
    alphaTest: 0.5,
    transparent: true,
    depthTest: false,
    depthWrite: false
    });

    sprite = new THREE.Sprite(spriteMaterial);
    sprite.position.set(250, 250, 250);
    sprite.scale.set(60, 60, 1);

    scene.add(sprite);

    // Renderer

    renderer = new THREE.WebGLRenderer({ antialias: true });
    renderer.setPixelRatio(window.devicePixelRatio);
    renderer.setSize(window.innerWidth, window.innerHeight);
    renderer.setClearColor(0x333333, 1);
    document.body.appendChild(renderer.domElement);

    // Controls

    controls = new THREE.OrbitControls(camera, renderer.domElement);
    controls.enableZoom = false;

    window.addEventListener("resize", onWindowResize, false);
    }

    function onWindowResize() {
    camera.aspect = window.innerWidth / window.innerHeight;
    camera.updateProjectionMatrix();

    renderer.setSize(window.innerWidth, window.innerHeight);
    }

    function animate() {
    requestAnimationFrame(animate);
    controls.update();
    render();
    }

    function render() {
    renderer.render(scene, camera);
    updateAnnotationOpacity();
    updateScreenPosition();
    }

    function updateAnnotationOpacity() {
    const meshDistance = camera.position.distanceTo(mesh.position);
    const spriteDistance = camera.position.distanceTo(sprite.position);
    spriteBehindObject = spriteDistance > meshDistance;
    sprite.material.opacity = spriteBehindObject ? 0.25 : 1;

    // Do you want a number that changes size according to its position?
    // Comment out the following line and the `::before` pseudo-element.
    sprite.material.opacity = 0;
    }

    function updateScreenPosition() {
    const vector = new THREE.Vector3(250, 250, 250);
    const canvas = renderer.domElement;

    vector.project(camera);

    vector.x = Math.round((0.5 + vector.x / 2) * (canvas.width / window.devicePixelRatio));
    vector.y = Math.round((0.5 - vector.y / 2) * (canvas.height / window.devicePixelRatio));

    annotation.style.top = `${vector.y}px`;
    annotation.style.left = `${vector.x}px`;
    annotation.style.opacity = spriteBehindObject ? 0.25 : 1;
    }
    2 changes: 2 additions & 0 deletions scripts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2 @@
    <script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/85/three.min.js"></script>
    <script src="https://codepen.io/Lorti/pen/mNzxjE.js"></script>
    41 changes: 41 additions & 0 deletions style.scss
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,41 @@
    canvas {
    width: 100%;
    height: 100px;
    display: block;
    }

    .annotation {
    position: absolute;
    top: 0;
    left: 0;
    z-index: 1;
    margin-left: 15px;
    margin-top: 15px;
    padding: 1em;
    width: 200px;
    color: #fff;
    background: rgba(0, 0, 0, 0.8);
    border-radius: .5em;
    font-size: 12px;
    line-height: 1.2;
    transition: opacity .5s;
    &::before {
    content: '1';
    position: absolute;
    top: -30px;
    left: -30px;
    width: 30px;
    height: 30px;
    border: 2px solid #fff;
    border-radius: 50%;
    font-size: 16px;
    line-height: 30px;
    text-align: center;
    background: rgba(0, 0, 0, 0.8);
    }
    }

    #number {
    position: absolute;
    z-index: -1;
    }
    7 changes: 7 additions & 0 deletions webgl-annotations-three-js.markdown
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,7 @@
    WebGL Annotations (three.js)
    ----------------------------


    A [Pen](https://codepen.io/Lorti/pen/Vbppap) by [Manuel Wieser](https://codepen.io/Lorti) on [CodePen](https://codepen.io).

    [License](https://codepen.io/license/pen/Vbppap).