I am trying to integrate the code in this answer (run snippet in question's answer to see an example) with the rest of the script below to allow the user to scroll down the sideButtons
selection menu by hovering in the bottom or top areas of the selection menu. However, I'm not sure how to write the requestAnimationFrame
function for it to work with the rest of the object structure or where to place it.
Attached to the sideButtons
' mouseMove
eventListener
function are two hitTest
's: 'lowerHoverBoxHitTest(x, y)
' and 'upperHoverBoxHitTest(x, y)
'. These detect if the top or bottom half of the selection menu is being hovered over. If so, hoverAmount
should be incremented accordingly such that sideButtons
is pushed up or down depending on which hoverBox
is selected. However, this part - which must (I think) occur within the requestAnimationFrame
function - is not working in the code above.
If it is still not clear how the animation should work please see the attached link above. It should be clear that it is not currently working properly... Any help will be much appreciated.
var buttonTypeSelection = document.getElementById('languageSelection');
var initialButtonType;
var buttonRanges = {'1-10': [1,2,3,4,5,6,7,8,9,10],
'One to Ten': ['One','Two','Three','Four','Five',
'Six','Seven','Eight','Nine','Ten'],
'0000-1010': ['0001','0010','0011','0100','0101',
'0110','0111','1000','1001','1010']};
var buttonTypeIndex = {'1-10': 1, 'One to Ten': 2, '0000-1010': 3};
Object.keys(buttonRanges).forEach(function(buttonType) {
buttonTypeSelection.options[buttonTypeSelection.options.length] = new Option(buttonType, buttonTypeIndex[buttonType]);
}, buttonRanges);
buttonTypeSelection.options.selectedIndex = 1; // set to page source language's code
initialButtonType=buttonRanges[Object.keys(buttonRanges)[buttonTypeSelection.options.selectedIndex]];
function Game (elementID,width,height){
this.elementID = elementID;
this.element = document.getElementById(elementID);
this.width = width;
this.height = height;
this.palette = {
color1:'#fff',
color2:'#000',
color3:'#9F3A9B',
color4:'#a84ea5',
color5:'#b56ab2',
color6:'#bf7dbd',
color7:'#d5a8d2'
};
this.element.style.width = width + 'px';
this.element.style.height= height + 'px';
this.element.style.border='solid thin ' + this.palette.color2;
this.element.style.display= 'block';
//this.element.style.margin='1em auto';
this.element.style.background=this.palette.color3;
this.buttonType=buttonRanges[buttonTypeSelection.options[buttonTypeSelection.selectedIndex].text];
this.hoverAmount = 0;
this.overTypes = {none:0, lower:1, raise:2}
this.overBox = 0;
this.overDist = 0;
this.initialGame();
}
Game.prototype.initialGame = function(){
this.canvas = document.createElement("canvas");
this.canvas.width = this.width;
this.canvas.height = this.height;
this.element.appendChild(this.canvas);
this.initialSideButtons();
this.initialTitle();
this.initialBoard();
this.initialFooter();
// initial selection
this.sideButtons.select(this.sideButtons.buttons[0]);
this.resize(this.width,this.height);
this.render();
this.attachEvents();
}
Game.prototype.attachEvents = function(){
var element = this.element;
var getX = function(evt){return evt.offsetX || evt.layerX || (evt.clientX - element.offsetLeft);};
var getY = function(evt){return evt.offsetY || evt.layerY || (evt.clientY - element.offsetTop);};
var game = this;
this.element.addEventListener('mousemove',function(evt){
game.hover(getX(evt),getY(evt));
if (game.sideButtons.lowerHoverBoxHitTest(game.hoverX, game.hoverY)) {
game.overBox=game.overTypes.raise;
} else if (game.sideButtons.upperHoverBoxHitTest(game.hoverX, game.hoverY)) {
game.overBox=game.overTypes.lower;
} else {
game.overBox=game.overTypes.none;
}
game.render();
});
this.element.addEventListener('click',function(evt){
game.sideButtons.click();
game.render();
});
}
Game.prototype.onSelect = function(button){
this.selected = button;
};
Game.prototype.hover=function(x,y){
this.hoverX = x;
this.hoverY = y;
};
Game.prototype.initialBoard = function(){
var game = this;
var Board = function(){
this.left = 0;
this.top = 0;
this.width = 0;
this.height = 0;
};
Board.prototype.render = function(ctx){
if(game.selected){
var shapeWidth = this.width/3;
ctx.fillStyle = game.palette.color1;
ctx.strokeStyle = game.palette.color1;
var fontSize = 14;
ctx.font = 'bold '+ fontSize +'px Noto Sans';
ctx.textAlign='center';
ctx.lineWidth=8;
ctx.lineJoin = 'round';
ctx.strokeRect(this.left + this.width/2 - (shapeWidth/2),this.height/2-(shapeWidth/2) + this.top,shapeWidth,shapeWidth);
ctx.fillText(game.selected.text,this.left + this.width/2,this.height/2 + this.top );
}
};
this.board = new Board();
};
Game.prototype.initialSideButtons = function(){
var game = this;
var ButtonBar =function(text){
this.text = text;
this.left = 0;
this.top = 0;
this.width = 1;
this.height= 1;
this.selected=false;
};
ButtonBar.prototype.hitTest=function(x,y){
return (this.left < x) && (x < (this.left + this.width)) &&
(this.top <y) && (y < (this.top + this.height));
};
ButtonBar.prototype.getColor=function(){
var hovered = this.hitTest(game.hoverX,game.hoverY);
if(this.selected){
if(hovered)
{
return game.palette.color7;
}
return game.palette.color6;
}
if(hovered){
return game.palette.color5;
}
return game.palette.color4;
};
ButtonBar.prototype.render = function(ctx){
var fontSize = 14;
ctx.fillStyle = this.getColor();
ctx.fillRect(this.left, this.top, this.width, this.height);
ctx.fillStyle = game.palette.color1;
ctx.textAlign = 'left';
ctx.font ='bold '+ fontSize +'px Noto Sans';
ctx.fillText(this.text,this.left + 10,this.top+ this.height/2);
};
var SideButtons = function(){
this.buttons = [];
this.width = 1;
this.height= 1;
this.left=1;
this.top=1;
};
SideButtons.prototype.lowerHoverBoxHitTest = function(x, y) {
game.overDist = y - (game.title.height + game.footer.top) - game.hoverScrollSize;
return (x >= this.width) && (x <= game.width) &&
(y >= ((game.title.height + game.footer.top) - game.hoverScrollSize)) && (y <= (game.title.height + game.footer.top));
}
SideButtons.prototype.upperHoverBoxHitTest = function(x, y) {
game.overDist = game.hoverScrollSize - y;
return (x>=this.width) && (x <= game.width) &&
(y >= game.title.height) && (y <= (game.title.height+game.hoverScrollSize));
}
SideButtons.prototype.render = function(ctx){
if(!this.buttons.length){
return;
}
var height = (this.height / this.buttons.length)/0.45;
for(var i=0;i<this.buttons.length;i++){
var btn = this.buttons[i];
btn.left = this.left;
btn.top = i * height + this.top;
btn.width = this.width;
btn.height = height;
this.buttons[i].render(ctx);
}
};
SideButtons.prototype.click = function() {
var current = null;
for(var i=0;i<this.buttons.length;i++){
var btn = this.buttons[i];
if(btn.hitTest(game.hoverX,game.hoverY)) {
this.select(btn);
break;
}
}
};
SideButtons.prototype.select = function(btn) {
for(var i=0; i<this.buttons.length; i++) {
this.buttons[i].selected = false;
}
btn.selected=true;
game.onSelect(btn);
};
SideButtons.prototype.refreshShapes = function() {
this.buttons = [];
for (var buttonIndex=1; buttonIndex<=10; buttonIndex++) {
this.buttons.push(new ButtonBar('Button ' + game.buttonType[buttonIndex]));
}
}
this.sideButtons = new SideButtons();
for (var buttonIndex=1; buttonIndex<=10; buttonIndex++) {
this.sideButtons.buttons.push(new ButtonBar('Button ' + game.buttonType[buttonIndex]));
}
};
Game.prototype.initialTitle = function(){
var Title = function(value,width,height){
this.value=value;
this.width = width;
this.height= height;
};
var game = this;
Title.prototype.render=function(ctx){
var k = 2;
var fontSize = this.height / k;
ctx.fillStyle=game.palette.color1;
ctx.fillRect(0,0,this.width,this.height);
ctx.font='bold '+ fontSize +'px Noto Sans'; // check
ctx.fillStyle=game.palette.color3;
ctx.textAlign='center';
ctx.fillText(this.value,this.width/2,this.height - fontSize/2);
};
this.title = new Title('Test',this.width,this.height / 10);
}
Game.prototype.initialFooter = function(){
var Footer = function(){
this.width = 1;
this.height= 1;
this.left=0;
this.top=0;
}
var game = this;
Footer.prototype.render = function(ctx){
ctx.fillStyle = game.palette.color5;
ctx.fillRect(this.left,this.top,this.width,this.height);
};
this.footer = new Footer();
};
Game.prototype.resetCanvas = function() {
this.canvas.width = this.width;
this.canvas.height = this.height;
};
Game.prototype.render = function () {
var that = this;
that._render();
}
Game.prototype._render = function() {
this.resetCanvas();
var context = this.canvas.getContext('2d');
this.sideButtons.render(context);
this.title.render(context);
this.board.render(context);
this.footer.render(context);
};
Game.prototype.resize = function (width,height){
this.width = width;
this.height= height;
this.element.style.width = width + 'px';
this.element.style.height= height+ 'px';
this.title.height = this.height / 14;
this.title.width = this.width;
this.footer.height = this.title.height;
this.footer.width = this.width;
this.footer.top = this.height - this.footer.height;
this.footer.left = 0;
this.board.top = this.title.height;
this.board.left = 0;
this.board.width = this.width / 2;
this.board.height= this.height - this.title.height - this.footer.height;
this.sideButtons.left= this.board.width;
this.sideButtons.top = this.board.top + this.hoverAmount;
this.sideButtons.width = this.width - this.board.width;
this.sideButtons.height = this.board.height;
this.maxSpeed = this.height*(5/500);
this.shapeSize = this.height*(30/500);
this.hoverScrollSize = this.height*(100/500);
this.render();
};
var game = new Game('game',window.innerWidth -50,window.innerWidth * 2/3);
window.addEventListener('resize', function(){
game.resize(window.innerWidth -50,window.innerWidth * 2/3);
});
buttonTypeSelection.addEventListener('change', function() {
game.buttonType=buttonRanges[buttonTypeSelection.options[buttonTypeSelection.selectedIndex].text];
var selectedIndex = game.sideButtons.buttons.indexOf(game.selected);
game.sideButtons.refreshShapes();
game.selected = game.sideButtons.buttons[selectedIndex];
game.render();
});
requestAnimationFrame(() => {
game.resize(window.innerWidth - 50, window.innerWidth * 2/3);
requestAnimationFrame(mainLoop); // start main loop
});
function mainLoop() {
if (game.overBox !== game.overTypes.none) {
game.hoverAmount += game.overDist/game.hoverScrollSize * (game.overBox === game.overTypes.lower ? game.maxSpeed : -game.maxSpeed);
var bottom = (game.height - (game.title.height + game.footer.height) + (game.sideButtons.buttons.length * game.shapeSize));
// game.hoverAmount = (game.hoverAmount > 0) ? 0 : (game.hoverAmount < bottom) ? bottom : game.hoverAmount;
game.resize(window.innerWidth - 50, window.innerWidth * 2/3);
}
requestAnimationFrame(mainLoop);
}
<!doctype html>
<html lang="en">
<body>
<div id='game'></div>
<div class="styled-select">
<select id="languageSelection"></select>
</div>
<script type='text/javascript' src='scaleStack.js'></script>
</body>
</html>