JSFiddle - React, Tailwind, and code Playground
HTML
<canvas id="canvasId" width=500 height=300></canvas>
<div id="triangle_container">
<span class="triangle"></span>
<span class="triangle base1"></span>
<span class="triangle base2"></span>
</div>
CSS
#triangle_container {
width: 500px;
}
.triangle {
height: 105px;
width: 0px;
background-color: #FFC821;
position: relative;
margin: 0px 75px;
display: block;
margin: 0px auto;
}
.triangle:before, .triangle:after {
content: "";
width: 0;
height: 0;
border-bottom: 105px solid #FFC821;
position: absolute;
top: 0px;
}
.triangle:before {
border-left: 75px solid transparent;
left: -75px;
}
.triangle:after {
border-right: 75px solid transparent;
right: -75px;
}
.triangle:hover {
background-color: #0000FF;
}
.triangle:hover:before {
border-bottom-color: #0000FF;
}
.triangle:hover:after {
border-bottom-color: #0000FF;
}
.base1 {
width: 150px;
}
.base2 {
width: 300px;
}
JavaScript
var Triangle = function (color, width, height, segments) {
var context = document.getElementById("canvasId").getContext("2d");
var slope = height / (width/2);
this.withinTriangle = function (x, y) {
// vector 1 (the line)
var a = [(width/2), -1*height];
// vector 2 (the point-ish)
var b = [(width/2) - x, 0 - y];
// Cross Product
var inleft = a[0]*b[1]-a[1]*b[0]<=0;
var inbot = y < height;
// recalculate a
a = [(width/2), height];
var inright = a[0]*b[1]-a[1]*b[0]<=0;
// Return either segment contained within or false
return inleft && inbot && inright ? Math.floor(y/(height/segments)) : false;
};
// 0 count for segments, use withinTriangle return value
this.highlightSegment = function (seg, clr) {
// if we're not highlighting a valid segment, don't
if (seg === false || seg> segments || seg < 0) return;
// height of segments. Dynamic so that number of segments can be changed on the fly
var segheight = height / segments;
// Redraw triangle
this.refill();
// Clear needed space
context.clearRect(0,seg*segheight,width,segheight);
// Y val for top pieces
var topy = (seg)*segheight;
// Y val for bottom pieces
var boty = (seg+1)*segheight;
// X val for top pieces (use width - x for right side)
var topin = (segments-seg)*segheight/slope;
// X val for bottom pieces (use width - x for right side)
var botin = (segments-seg-1)*segheight/slope;
context.beginPath();
context.moveTo(botin,boty);
context.lineTo(topin,topy);
context.lineTo(width-topin,topy);
context.lineTo(width-botin,boty);
context.closePath();
context.fillStyle = clr;
context.fill();
};
// Redraw Triangle
this.refill = function (clrOvr) {
...