Hexagon Button


#1

Hi,

mit meinen beschränkten HTML/JS Kenntnissen versuche folgendes Layout hinzukriegen:

Jedes Hexagon soll zu einer anderen Seite führen.
Ich habe überlegt das Bild in mehrere Rechtecke aufzuteilen, aber geht es nicht auch einfacher?


#2

Eine Möglichkeit wäre z.B. SVG als Grafikformat.

Dort kann man dann für jedes Hexagon einen Link hinzufügen. Beispiel mit Quadraten.

http://svg.tutorial.aptico.de/start3.php?knr=6&kname=Hyperlinks&uknr=6.1&ukname=Besonderheiten%20des%20a-Elements

http://svg.tutorial.aptico.de/grafik_svg/kap5_1.svg

Und das ganze könnte man z.B. mit Inkscape Zeichnen.


Eine andere Möglichkeit ist das Image so zu lassen wie es ist und sich die Koordinaten geben zu lassen und daraus dann das Hexagon zu bestimmen.

Dazu das image als Input mit dem type image versehen, dann werden beim Klick, Absenden des Forms die Koordinaten mitgeschickt als x und y Wert. Daraus kann man dann wiederum bestimmen welches Hexagon geclickt wurde und entsprechend weiterleiten.


#3

Ich habe mal die zweite Variante ausprobiert, funktioniert ganz gut. Um von den Koordinaten auf das entsprechende Hexagon zu kommen benutze ich zwar wieder Rechtecke, weshalb die Ecken nicht unbedingt anklickbar sind, aber falls das nicht reicht versuche ich es mal mit Dreiecken, damit sollte es präziser gehen.

Danke erstmal :wink:


#5

Was ist den genau die Frage? Wie man Hexagons repräsentiert, oder wie man das in JS konkret implementiert?

Wie auch immer, für beides könnte http://www.redblobgames.com/grids/hexagons/ hilfreich sein.


#6

Hab selbst noch ein wenig rumprobiert und hänge mal mein Snippet ran, dass ich soweit als beste Lösung empfand, falls ich es mal selbst bräuchte.

function getClickPosition(e) {
    var xPosition = e.offsetX;
    var yPosition = e.offsetY;
    // Ergebnis anzeigen
    document.getElementById("x").innerHTML= xPosition;
    document.getElementById("y").innerHTML= yPosition;
    if(200 < xPosition && xPosition < 320
      && 200 < yPosition && yPosition < 320) {
        alert("Gelbes Hexagon getroffen");
      }
}
function init() {
  document.getElementById("hexagon").addEventListener("click", getClickPosition);
}

Zur Berechnung könnte man auch die Mitte der jeweiligen Hexagone nehmen und die Entfernung zum Click berechnen und dann das nächste als Treffer heranziehen.


#7

@ionutbaiu so ungefähr habe ich es auch gemacht. Wenn ich die Mitte habe kann ich relativ einfach auf die Eckpunkte kommen, das könnte der einfachste Weg sein um es perfekt zu machen.

@Marco13 Die Frage war eher auf die Implementation bezogen.Mir war nicht klar wie ich an die Koordinaten komme und daraus das richtige Hexagon berechne.

Danke nochmal :slight_smile:


#8

Unter <HTML4 gab es Mal den Tag “map” oder ähnlich. Im Zusammenhang mit Image konnte man damit Shapes (in deinem Fall Hexagonal) auf dem Image mit passenden Links versehen. Kein Ahnung ob es das unter HTML4++ noch gibt.

Gibts: https://www.w3schools.com/tags/tag_map.asp


#9

@mogel Hört sich auch gut an, versuche ich mal die Tage :wink:

Ich habe die Berechnung noch ein bisschen verbessert, und es funktioniert jetzt alles wie gewollt.
Hier meine Lösung für den den es interessiert:

/**
Hexagon Tile coordinates
*/
var organigrammCoords = [
    {x: 395, y: 134, containerID: ''},  
    {x: 155, y: 274, containerID: ''},   
    {x: 634, y: 274, containerID: ''}, 
    {x: 395, y: 410, containerID: ''}, 
    {x: 155, y: 550, containerID: ''},
    {x: 395, y: 686, containerID: ''}
    {x: 634, y: 550, containerID: ''}
];

var cornerOffsets = [
    [-75, -144],
    [75, -144],
    [155, 0],
    [75, 144],
    [-75, 144],
    [-155, 0]
];

$(document).ready(function () {
    $('#organigramm').click(function(e) {
        var offset = $(this).offset();
        var x = e.pageX - offset.left;
        var y = e.pageY - offset.top;

        var polygon = [cornerOffsets.length];
        for(var i = 0; i < organigrammCoords.length; i++) {
            var bounds = organigrammCoords**;
            for(var j = 0; j < cornerOffsets.length; j++) {
                polygon[j] = [bounds.x + cornerOffsets[j][0], bounds.y + cornerOffsets[j][1]];
            }

            if(isInPolygon(x, y, polygon)) {
                showContent(bounds.containerID);
                break;
            }
        }
    });
});

function isInPolygon(x, y, polygon) {
    var b = false;
    for (var i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
        if ((polygon**[1] > y) != (polygon[j][1] > y) && (x < (polygon[j][0] - polygon**[0]) * (y - polygon**[1]) / (polygon[j][1] - polygon**[1]) + polygon**[0])) {
            b = !b;
        }
    }
    return b;
}

Aus dem Mittelpunkt berrechne ich mit den Offsets die Eckpunkte und prüfe dann mit der Even-Odd Rule ob innerhalb des Polygons geklickt wurde. Kann denke ich noch optimiert werden, funktioniert aber ziemlich gut.

Danke für eure Hilfe :wink: