1

I have n+1 hexshapes in a honeycomb grid. The objects are stacked close together. With this code:

// Get intersected objects, a.k.a objects "hit" by mouse, a.k.a objects that are mouse-overed
const intersects = raycaster.intersectObjects(hexObjects);

// If there is one (or more) intersections
let scaleTween = null;
if (intersects.length > 0) {
  // If mouse is not currently over an object

  // Set cursor to pointer so that the user can see that the object is clickable
  document.body.style.cursor = 'pointer';

  // Get the last intersected object, it's most likely that object we are currently hovering
  const is = intersects.length > 0 ? intersects.length - 1 : 0;

  // Is the object hovered over for the first time?
  if (INTERSECTED === null) {
    // Save current hovered object
    INTERSECTED = intersects[is].object;
    // HIGHLIGHT
    // Save current color
    INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
    // Set highlight color
    INTERSECTED.material.color.setHex(COLOR_HIGHLIGHT);

    // SCALE UP
    // Try to stop the current tween, if any, in progress, so we can proceed with the next, if any, tween
    try {
      scaleTween.stop();
    } catch (e) {}

    // Create tween, save it so we can try to stop it, if needed
    scaleTween = scale_tween(
      INTERSECTED,
      INTERSECTED.scale.clone(),
      {
        x: 1.5,
        y: 1.5
      },
      100
    );
    scaleTween.start();

    // SET Z-INDEX
    INTERSECTED.position.z = 10;
  } else {
    // If the mouse is over an object

    // Do we have a previous hovered item?
    if (INTERSECTED !== null) {
      // Revert color
      INTERSECTED.material.color.setHex(INTERSECTED.currentHex);
      // SCALE DOWN
      // Try to stop the current tween, if any, in progress, so we can proceed with the next, if any, tween
      try {
        scaleTween.stop();
      } catch (e) {}

      // Create tween, save it so we can try to stop it, if needed
      scaleTween = scale_tween(
        INTERSECTED,
        INTERSECTED.scale.clone(),
        {
          x: 1,
          y: 1
        },
        100
      );
      scaleTween.start();

      // REVERT Z-INDEX
      INTERSECTED.position.z = 1;
    }

    // Save current intersected object
    INTERSECTED = intersects[is].object;

    // HIGHLIGHT
    // Save current color
    INTERSECTED.currentHex = INTERSECTED.material.color.getHex();
    // Set highlight color
    INTERSECTED.material.color.setHex(COLOR_HIGHLIGHT);

    // SCALE UP
    // Try to stop the current tween, if any, in progress, so we can proceed with the next, if any, tween
    try {
      scaleTween.stop();
    } catch (e) {}

    // Create tween, save it so we can try to stop it, if needed
    scaleTween = scale_tween(
      INTERSECTED,
      INTERSECTED.scale.clone(),
      {
        x: 1.5,
        y: 1.5
      },
      100
    );
    scaleTween.start();

    // SET Z-INDEX
    INTERSECTED.position.z = 10;
  }
} else {
  // If there are no intersections

  // Reset cursor
  document.body.style.cursor = 'default';

  // Restore previous intersection object (if it exists) to its original color
  if (INTERSECTED !== null) {
    // REVERT COLOR
    INTERSECTED.material.color.setHex(INTERSECTED.currentHex);

    // SCALE DOWN
    // Try to stop the current tween, if any, in progress, so we can proceed with the next, if any, tween
    try {
      scaleTween.stop();
    } catch (e) {}

    // Create tween, save it so we can try to stop it, if needed
    scaleTween = scale_tween(
      INTERSECTED,
      INTERSECTED.scale.clone(),
      {
        x: 1,
        y: 1
      },
      100
    );
    scaleTween.start();

    // REVERT "Z-INDEX"
    INTERSECTED.position.z = 1;
  }

  // Remove previous intersection object reference  by setting current intersection object to "nothing"
  INTERSECTED = null;
}

I've managed to highlight the object and scale it up with a tween quite nicely, but when I move the mouse out of the object onto the next object (the scaled object is scaled over the next object a bit), the highlight is gone, but the scale persists. How do I manage to scale the object down? And preferably with a tween?

A pen for this code can be found here: https://codepen.io/phun-ky/pen/erBZZy, the relevant part is at about line 1284 or search for INTERSECTED.

2
  • Is it possible to create a live code example? Commented May 6, 2018 at 19:53
  • @prisoner849 updated question now with link to a pen with this issue. Commented May 7, 2018 at 6:44

1 Answer 1

2

I wrote my own one. It's hell imperfect, but, at least, it scales up and down the hexagons:

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer({
  antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x101010);
document.body.appendChild(renderer.domElement);

var hexes = [];

var colCount = 5;
var rowCount = 4;
var hexDiameter = 3;

var xStart = -(colCount) * hexDiameter * 0.5;
var rowSpace = Math.sqrt(3) * hexDiameter * 0.5;
var yStart = (rowCount - 1) * rowSpace * 0.5;
var hexGeom = new THREE.CylinderGeometry(hexDiameter * 0.5, hexDiameter * 0.5, 0.0625, 6, 1);
hexGeom.rotateX(Math.PI * 0.5);
for (let j = 0; j < rowCount; j++) {
  for (let i = 0; i < colCount + (j % 2 === 0 ? 0 : 1); i++) {
    let hex = new THREE.Mesh(hexGeom, new THREE.MeshBasicMaterial({
      color: Math.random() * 0x7e7e7e + 0x7e7e7e,
      wireframe: false
    }));
    hex.position.set(xStart + i * hexDiameter + (j % 2 === 0 ? 0.5 * hexDiameter : 0), yStart - j * rowSpace, 0);
    hex.userData.scaleUp = function(h) {
      if (h.userData.scaleDownTween) h.userData.scaleDownTween.stop();
      let initScale = h.scale.clone();
      let finalScale = new THREE.Vector3().setScalar(2);
      h.userData.scaleUpTween = new TWEEN.Tween(initScale).to(finalScale, 500).onUpdate(function(obj) {
        h.scale.copy(obj)
      }).start();
    }
    hex.userData.scaleDown = function(h) {
      if (h.userData.scaleUpTween) h.userData.scaleUpTween.stop();
      let initScale = h.scale.clone();
      let finalScale = new THREE.Vector3().setScalar(1);
      h.userData.scaleUpTween = new TWEEN.Tween(initScale).to(finalScale, 500).onUpdate(function(obj) {
        h.scale.copy(obj)
      }).start();
    }
    scene.add(hex);
    hexes.push(hex);
  }
}

window.addEventListener("mousemove", onMouseMove, false);

var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var intersects = [];
var intersected;

function onMouseMove(event) {
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
  raycaster.setFromCamera(mouse, camera);
  intersects = raycaster.intersectObjects(hexes);
  if (intersects.length > 0) {
    if (intersected != intersects[0].object) {
      if (intersected) intersected.userData.scaleDown(intersected);
      intersected = intersects[0].object;
      intersected.userData.scaleUp(intersected);
    }
  } else {
    if (intersected) intersected.userData.scaleDown(intersected);
    intersected = null;
  }
}

render();

function render() {
  requestAnimationFrame(render);
  TWEEN.update();
  renderer.render(scene, camera);
}
body {
  overflow: hidden;
  margin: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/92/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tween.js/17.2.0/Tween.min.js"></script>

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a million @prisoner849! This helped me not just with the OT, but with the grid generation! Bonus x2! Have a nice summer!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.