Search code examples
javascriptcsshtmltwo.js

How do I create circular hotspots with two.js?


I am trying to make a solar system model. I made it all so far using two.js. I want to make it so when the mouse is over a planet's orbit path, it'll highlight that planet's orbit, and be a link to information about that planet. I'm having trouble finding a way to do this, though.

If you don't have it, here's Two.js.

My file structure looks like this:

css
   main.css
js
   main.js
   two.js
index.html

PS. This will not render with the "Run code snippet" feature. If you wish to see it, you must save this code and put it in the same file structure I have.

//This work was created by the minds of Sam Steele and Devin Fowler of Cryptocosm Developers.
//Cryptocosm ©2014
//cryptocosm.x10.bz

//Initiate the render context
var elem = document.getElementById('canvas');
var two = new Two({
    fullscreen: true
}).appendTo(elem);

//Define our planets and their colors
var sun = two.makeCircle(0, 0, 70);
var mercury = two.makeCircle(95, 0, 7);
var venus = two.makeCircle(125, 0, 8.5);
var earth = two.makeCircle(160, 0, 11.4);
var mars = two.makeCircle(200, 0, 9.5);
var jupiter = two.makeCircle(260, 0, 28);
//      For Saturn we're going to do something special in order to get the rings
var saturnBody = two.makeCircle(320, 0, 24);
var saturnRings = two.makeCurve(296, 0, 290, 10, 322, 10, 350, -8, 342, -10, true);
saturnRings.rotation = 4.5;
var saturn = two.makeGroup(saturnBody, saturnRings);
var uranus = two.makeCircle(460, 0, 18);
var neptune = two.makeCircle(540, 0, 16);
var asteroid = two.makeCircle(0, 320, 3);

//Try to make some stars
var width = window.innerWidth;
var height = window.innerHeight;
var star;
for (i = 0; i < 200; i++) {
    var randX = Math.round(Math.random() * width);
    var randY = Math.round(Math.random() * height);
    star = two.makeCircle(randX, randY, 2);
}

//Set the color of the planets
sun.fill = '#F7CA18';
mercury.fill = '#9E9E9E';
venus.fill = '#795548';
earth.fill = '#2196F3';
mars.fill = '#FF7043';
jupiter.fill = '#E67E22';
saturnBody.fill = '#A1887F';
saturnRings.stroke = "#F5F5F5";
saturnRings.linewidth = 7;
saturnRings.noFill();
saturn.translation.set(20, 0);
uranus.fill = '#4DB6AC';
neptune.fill = '#3F51B5';
star.fill = '#FAFAFA';
asteroid.fill = '#FAFAFA';

//Group the planets
var Mercury = two.makeGroup(mercury);
var Venus = two.makeGroup(venus);
var Earth = two.makeGroup(earth);
var Mars = two.makeGroup(mars);
var Jupiter = two.makeGroup(jupiter);
var Saturn = two.makeGroup(saturn);
var Uranus = two.makeGroup(uranus);
var Neptune = two.makeGroup(neptune);
var planets = two.makeGroup(sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune);

//Center everything in the center of the element
planets.translation.set(two.width / 2, two.height / 2);
Mercury.rotation = 4;
Venus.rotation = 2.5;
Earth.rotation = 5.5;
Mars.rotation = 1;
Jupiter.rotation = 4.2;
Saturn.rotation = 2.5;
Uranus.rotation = 5.75;
Neptune.rotation = .5;

var counter = document.getElementById('counter');
var count = 0;
var yearsPassed = 0;


// Bind a function to scale and rotate the group to the animation loop.
two.bind('update', function (frameCount) {
    //Set the "ZOOM" of the system
    planets.scale = .8;

    //Rotate all the planets
    Mercury.rotation += .01607;
    Venus.rotation += .01174;
    Earth.rotation += .01;
    /* //Earth year counter (not currently accurate at all)
	count++;
    if (count % 550 == 0) {
        yearsPassed++;
        counter.innerHTML = "An estimated " + yearsPassed + " Earth years passed";
    }; */
    Mars.rotation += .00802;
    Jupiter.rotation += .00434;
    Saturn.rotation += .00323;
    Uranus.rotation += .00228;
    Neptune.rotation += .00182;

    //Rotate Saturn's rings so that it doesn't look dumb
    saturnRings.rotation -= .00323;
}).play(); // Finally, start the animation loop
@font-face {
    font-family: Roboto-Thin;
    font-style: normal;
    src: url(Roboto/Roboto-Thin.ttf);
}
html {
    background-color: #212121;
}
body {
    color: white;
    font-family: Roboto-Thin;
}
#counter {
    background-color: rgba(0, 0, 0, .4);
    width: auto;
    height: auto;
    font-size: 34px;
    float: left;
    position: fixed;
    padding: 10px;
}
#canvas {}
<html>

<head>
    <title>The Solar System</title>
    <link href="css/main.css" type="text/css" rel="stylesheet">
    <script src="js/two.js"></script>
</head>

<body>
    <div id="counter"></div>
    <div id="canvas">
    </div>
    <script src="js/main.js"></script>
</body>

</html>


Solution

  • This is one way to achieve that effect:

    This will only work for the svg renderer, but you can add event listeners on mouseover and mouseout as well as touchmove events like so:

    // ... After you've created all the planets ...
    
    // This command will create all the dom elements
    // which you can bind events to.
    two.update();
    
    var highlight = function() { sun.fill = 'red'; };
    var ignore = function() { sun.fill = 'yellow'; };
    
    sun._renderer.elem.addEventListener('mousemove', highlight, false);
    sun._renderer.elem.addEventListener('mouseout', ignore, false);
    

    There is also an example of how to achieve this here.