我几个小时以来一直在查看我的代码,但我仍然无法弄清楚它的错误。
我创建了一个非常简单的六边形网格系统版本。我想在网格中选择任何六边形的地方。所有的六边形都正确显示,只是当我点击网格时,会选择一个不正确的六边形。它的行为,就像鼠标位置不正确一样,或者 也许它可能是六边形有不正确的位置数据(?)。 但他们为什么如此正确定位呢?
////////// [ Hexagon ] ////////////////////
function Hexagon( options ){
if( options !== "undefined" ){
this.attributes = {
type : options.type || 0, //// 0 is cell , 1 player /// Default : 0 ////
id: options.id,
color : this.getColor(),
coords: [], //// [ r, q ] /// row / col ///
points: [],
pos: options.pos,
size: options.size
};
this.states = {
selected: false
};
//// make short-cuts to frequently used attributes ////
this.pos = this.attributes.pos;
this.coords = this.attributes.coords;
this.size = this.attributes.size;
this.points = this.attributes.points;
///// caclulate top_left, bottom and center points ////
this.TopLeftPoint = [ this.pos[0], this.pos[1] ];
this.BottomRightPoint = [ this.pos[0] + this.size.w, this.pos[1] + this.size.h ];
this.MidPoint = [ this.pos[0] + (this.size.w / 2), this.pos[1] + (this.size.h / 2) ];
///////// generate points ///////
this.generate();
}
}
Hexagon.prototype = {
constructor : Hexagon,
changeState: function( st_name, st_value ){
if( this.checkState( st_name ) ) {
this.states[st_name] = st_value;
}
},
checkState: function( st_name ){
if( typeof this.states[st_name] !== "undefined" ) {
return this.states[st_name];
}
return false;
},
isInHexBounds : function( p ){ /*Point*/
if(this.TopLeftPoint[0] < p[0] && this.TopLeftPoint[1] < p[1] && p[0] < this.BottomRightPoint[0] && p[1] < this.BottomRightPoint[0]){
return true;
}
return false;
},
contains: function( p ) {
var isIn = false;
if( this.isInHexBounds( p ) ){
var i, j = 0;
for (i = 0, j = this.points.length - 1; i < this.points.length; j = i++){
var iP = this.points[i];
var jP = this.points[j];
if (
( ((iP[1] <= p[1]) && (p[1] < jP[1])) || ((jP[1] <= p[1]) && (p[1] < iP[1]))) && (p[0] < (jP[0] - iP[0]) * (p[1] - iP[1]) / (jP[1] - iP[1]) + iP[0])
){
isIn = !isIn;
}
}
}
return isIn;
},
getColor: function( ){
switch( this.type ){
case 0:
return "blue";
case 1:
return "red";
default:
return "yellow";
}
},
trigger: function( e_name ){
this.events[ e_name ].call(this);
},
events: {
"select" : function(){
if( ! this.checkState( "selected" ) ){
this.changeState("selected", true);
//console.log( this.coords )
this.type = 1;
}
}
},
setType: function( type ){
this.attributes.type = type;
},
generate: function(){///// generate hexagon points //////
var x1 = (this.size.w - this.size.s)/2;
var y1 = (this.size.h / 2);
this.points.push(
[ x1 + this.pos[0], this.pos[1] ],
[ x1 + this.size.s + this.pos[0], this.pos[1] ],
[ this.size.w + this.pos[0], y1 + this.pos[1] ],
[ x1 + this.size.s + this.pos[0], this.size.h + this.pos[1] ],
[ x1 + this.pos[0], this.size.h + this.pos[1] ],
[ this.pos[0], y1 + this.pos[1] ]
);
},
draw : function( ctx ){
if( this.type > 0 ){
ctx.globalAlpha = 0.5;
ctx.fillStyle = this.color;
ctx.fill();
ctx.globalAlpha = 1.0;
}else{
ctx.strokeStyle = "grey";
}
//ctx.rect( this.BottomRightPoint[0],this.BottomRightPoint[1],4,4);
//ctx.stroke();
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo( this.points[0][0], this.points[0][1] );
for( var c=1; c < this.points.length; c++ ){
ctx.lineTo( this.points[c][0], this.points[c][1] );
}
ctx.closePath();
ctx.stroke();
this.draw_coords( ctx );
},
draw_coords: function( ctx ){
ctx.font="10px Georgia";
ctx.textAlign = "center";
ctx.textBaseline = 'middle';
ctx.fillStyle = "blue";
ctx.fillText(this.coords[0]+" , "+this.coords[1], this.MidPoint[0], this.MidPoint[1]);
}
}
///////// [ Grid ] /////////////////////
function Grid( options ){
if(typeof options !== "undefined"){
this.size = {
width: options.size[0],
height: options.size[1]
};
//this.mouse_pos = [];
this.pos = options.pos; //// position within the canvas /// [ x , y ] ////
this.ctx = options.ctx;
this.ctx_pos = options.ctx_pos; //// position of canvas element /// [ left, top] ///
this.hex_size = this.calculate_hex_size( options.hex_def );
this.hexagons = []; //// [ row, col ] ///// just a temporary array ////
this.grid2D = []; ///// includes all hexagons to be drawn ///
}
this.generate();
this.animate();
this.enable_mouse_events();
}
Grid.prototype = {
constructor : Grid,
generate : function(){
var hex_pos_x = 0.0, hex_pos_y = 0.0, row = 0, col = 0, offset = 0.0, h = null, h_id = 0;
while( (hex_pos_y + this.hex_size.h) <= this.size.height ){
col = 0; //// reset col
offset = 0.0; //// reset offset
if( (row % 2) == 1){
offset = ( ( this.hex_size.w - this.hex_size.s ) /2 ) + this.hex_size.s ;
col = 1;
}
hex_pos_x = offset;
while( (hex_pos_x + this.hex_size.w) <= this.size.width ){
h = new Hexagon( { pos : [ hex_pos_x, hex_pos_y ], size: this.hex_size , id: row+""+col, type: 0 });
h.coords[0] = col; //// set coord X ///
this.grid2D.push( h );
if( ! this.hexagons[col] ){
this.hexagons[col] = [];
}
this.hexagons[col].push( h );
col += 2;
hex_pos_x += (this.hex_size.w + this.hex_size.s);
}
row++;
hex_pos_y += (this.hex_size.h / 2);
}
////finally go through our list of hexagons by their x co-ordinate to assign the y co-ordinate
var coordX = 0, coordY = 0, h_l = this.hexagons.length, hex_arr = [];
for( ; coordX < h_l; coordX++ ){
hex_arr = this.hexagons[ coordX ];
coordY = Math.floor( (coordX / 2 ) + (coordX % 2) );
for( var h = 0, size = hex_arr.length; h < size; h++ ){
hex_arr[h].coords[1] = coordY++;
}
}
},
getHexAt: function( p ){ //// point [ x, y ]
for ( var h = 0, h_l = this.grid2D.length; h < h_l; h++ ){
if ( this.grid2D[h].contains( p ) ){
return this.grid2D[h];
}
}
return null;
},
animate: function(){
var self = this;
window.requestAnimationFrame( function(){
self.animate();
});
self.draw();
},
draw : function( ){
this.ctx.clearRect(0, 0, this.size.width, this.size.height);
for( var h = 0, h_l = this.grid2D.length; h < h_l; h++ ){
this.grid2D[h].draw( this.ctx );
}
},
calculate_hex_size : function( hex_def ){
return {
w: hex_def.radius * 2,
m: hex_def.margin,
h: (Math.sqrt(3) / 2) * ( hex_def.radius * 2),
r: hex_def.radius,
s: hex_def.radius
}
},
enable_mouse_events: function(){
var self = this;
var mouse_pos = [];
var cur_hex = null;
window.addEventListener( 'mousemove', function(e){
mouse_pos = [ ( e.clientX - self.ctx_pos[0] ), ( e.clientY - self.ctx_pos[1] )];
//self.mouse_pos = mouse_pos;
});
window.addEventListener( 'mousedown', function(e){
if( mouse_pos.length > 0 ){
cur_hex = self.getHexAt( mouse_pos );
if( cur_hex != null ){
cur_hex.trigger("select");
}
}
});
}
}
var c_el = document.getElementById("myCanvas");
var ctx = c_el.getContext("2d");
var nGrid = new Grid({
/// size : [ c_el.width, c_el.height ], /// [rows / cols ] //// 20 px x 10 px///
size : [ 70 , 70 ],
pos: [ 20, 20 ], /// [X, Y] ////
hex_def: {
radius: 20,
margin: 0
},
ctx : ctx,
ctx_pos: [ c_el.getBoundingClientRect().left, c_el.getBoundingClientRect().top ]
});
&#13;
<body stye="width: 100%; height: 100%" >
<canvas id="myCanvas" width="750px" height="405px" style="margin:0; padding:0; border:1px solid #d3d3d3;"></canvas>
</body>
&#13;
答案 0 :(得分:0)
ctx.fill()
之前调用ctx.begonPath()/ctx.closePath()
。这是错误的,所以任何先前绘制的六边形都被填充为这个错误的副作用
在ctx.fill()
之后我添加了ctx.begonPath()/ctx.closePath()
一切都完美无缺。
请参阅下面的结果。
////////// [ Hexagon ] ////////////////////
function Hexagon( options ){
if( options !== "undefined" ){
this.attributes = {
type : options.type || 0, //// 0 is cell , 1 player /// Default : 0 ////
id: options.id,
color : this.getColor(),
coords: [], //// [ r, q ] /// row / col ///
points: [],
pos: options.pos,
size: options.size
};
this.states = {
selected: false
};
//// make short-cuts to frequently used attributes ////
this.pos = this.attributes.pos;
this.coords = this.attributes.coords;
this.size = this.attributes.size;
this.points = this.attributes.points;
///// caclulate top_left, bottom and center points ////
this.TopLeftPoint = [ this.pos[0], this.pos[1] ];
this.BottomRightPoint = [ this.pos[0] + this.size.w, this.pos[1] + this.size.h ];
this.MidPoint = [ this.pos[0] + (this.size.w / 2), this.pos[1] + (this.size.h / 2) ];
///////// generate points ///////
this.generate();
}
}
Hexagon.prototype = {
constructor : Hexagon,
changeState: function( st_name, st_value ){
if( this.checkState( st_name ) ) {
this.states[st_name] = st_value;
}
},
checkState: function( st_name ){
if( typeof this.states[st_name] !== "undefined" ) {
return this.states[st_name];
}
return false;
},
isInHexBounds : function( p ){ /*Point*/
if(this.TopLeftPoint[0] < p[0] && this.TopLeftPoint[1] < p[1] && p[0] < this.BottomRightPoint[0] && p[1] < this.BottomRightPoint[1]){
return true;
}
return false;
},
contains: function( p ) {
var isIn = false;
if( this.isInHexBounds( p ) ){
var i, j = 0;
for (i = 0, j = this.points.length - 1; i < this.points.length; j = i++){
var iP = this.points[i];
var jP = this.points[j];
if (
( ((iP[1] <= p[1]) && (p[1] < jP[1])) || ((jP[1] <= p[1]) && (p[1] < iP[1])) ) && (p[0] < (jP[0] - iP[0]) * (p[1] - iP[1]) / (jP[1] - iP[1]) + iP[0])
){
isIn = !isIn;
}
}
}
return isIn;
},
getColor: function( ){
switch( this.type ){
case 0:
return "blue";
case 1:
return "red";
default:
return "yellow";
}
},
trigger: function( e_name ){
this.events[ e_name ].call(this);
},
events: {
"select" : function(){
if( ! this.checkState( "selected" ) ){
this.changeState("selected", true);
//console.log( this.coords )
this.type = 1;
}
}
},
setType: function( type ){
this.attributes.type = type;
},
generate: function(){///// generate hexagon points //////
var x1 = (this.size.w - this.size.s)/2;
var y1 = (this.size.h / 2);
this.points.push(
[ x1 + this.pos[0], this.pos[1] ],
[ x1 + this.size.s + this.pos[0], this.pos[1] ],
[ this.size.w + this.pos[0], y1 + this.pos[1] ],
[ x1 + this.size.s + this.pos[0], this.size.h + this.pos[1] ],
[ x1 + this.pos[0], this.size.h + this.pos[1] ],
[ this.pos[0], y1 + this.pos[1] ]
);
},
draw : function( ctx ){
ctx.lineWidth = 1;
ctx.beginPath();
ctx.moveTo( this.points[0][0], this.points[0][1] );
for( var c=1; c < this.points.length; c++ ){
ctx.lineTo( this.points[c][0], this.points[c][1] );
}
ctx.closePath();
ctx.stroke();
if( this.type > 0 ){
ctx.globalAlpha = 0.5;
ctx.fillStyle = this.color;
ctx.fill();
ctx.globalAlpha = 1.0;
}else{
ctx.strokeStyle = "grey";
}
this.draw_coords( ctx );
},
draw_coords: function( ctx ){
ctx.font="10px Georgia";
ctx.textAlign = "center";
ctx.textBaseline = 'middle';
ctx.fillStyle = "blue";
ctx.fillText(this.coords[0]+" , "+this.coords[1], this.MidPoint[0], this.MidPoint[1]);
}
}
///////// [ Grid ] /////////////////////
function Grid( options ){
if(typeof options !== "undefined"){
this.size = {
width: options.size[0],
height: options.size[1]
};
//this.mouse_pos = [];
this.pos = options.pos; //// position within the canvas /// [ x , y ] ////
this.ctx = options.ctx;
this.ctx_pos = options.ctx_pos; //// position of canvas element /// [ left, top] ///
this.hex_size = this.calculate_hex_size( options.hex_def );
this.hexagons = []; //// [ row, col ] ///// just a temporary array ////
this.grid2D = []; ///// includes all hexagons to be drawn ///
}
this.generate();
this.animate();
this.enable_mouse_events();
}
Grid.prototype = {
constructor : Grid,
generate : function(){
var hex_pos_x = 0.0, hex_pos_y = 0.0, row = 0, col = 0, offset = 0.0, h = null, h_id = 0;
while( (hex_pos_y + this.hex_size.h) <= this.size.height ){
col = 0; //// reset col
offset = 0.0; //// reset offset
if( (row % 2) == 1){
offset = ( ( this.hex_size.w - this.hex_size.s ) /2 ) + this.hex_size.s ;
col = 1;
}
hex_pos_x = offset;
while( (hex_pos_x + this.hex_size.w) <= this.size.width ){
h = new Hexagon( { pos : [ hex_pos_x, hex_pos_y ], size: this.hex_size , id: row+""+col, type: 0 });
h.coords[0] = col; //// set coord X ///
this.grid2D.push( h );
if( ! this.hexagons[col] ){
this.hexagons[col] = [];
}
this.hexagons[col].push( h );
col += 2;
hex_pos_x += (this.hex_size.w + this.hex_size.s);
}
row++;
hex_pos_y += (this.hex_size.h / 2);
}
////finally go through our list of hexagons by their x co-ordinate to assign the y co-ordinate
var coordX = 0, coordY = 0, h_l = this.hexagons.length, hex_arr = [];
for( ; coordX < h_l; coordX++ ){
hex_arr = this.hexagons[ coordX ];
coordY = Math.floor( (coordX / 2 ) + (coordX % 2) );
for( var h = 0, size = hex_arr.length; h < size; h++ ){
hex_arr[h].coords[1] = coordY++;
}
}
},
getHexAt: function( p ){ //// point [ x, y ]
for ( var h = 0, h_l = this.grid2D.length; h < h_l; h++ ){
if ( this.grid2D[h].contains( p ) ){
return this.grid2D[h];
}
}
return null;
},
animate: function(){
var self = this;
window.requestAnimationFrame( function(){
self.animate();
});
self.draw();
},
draw : function( ){
this.ctx.clearRect(0, 0, this.size.width, this.size.height);
for( var h = 0, h_l = this.grid2D.length; h < h_l; h++ ){
this.grid2D[h].draw( this.ctx );
}
},
calculate_hex_size : function( hex_def ){
return {
w: hex_def.radius * 2,
m: hex_def.margin,
h: (Math.sqrt(3) / 2) * ( hex_def.radius * 2),
r: hex_def.radius,
s: hex_def.radius
}
},
enable_mouse_events: function(){
var self = this;
var mouse_pos = [];
var cur_hex = null;
window.addEventListener( 'mousemove', function(e){
mouse_pos = [ ( e.clientX - self.ctx_pos[0] ), ( e.clientY - self.ctx_pos[1] )];
//self.mouse_pos = mouse_pos;
});
window.addEventListener( 'mousedown', function(e){
if( mouse_pos.length > 0 ){
cur_hex = self.getHexAt( mouse_pos );
if( cur_hex != null ){
cur_hex.trigger("select");
}
}
});
}
}
var c_el = document.getElementById("myCanvas");
var ctx = c_el.getContext("2d");
var nGrid = new Grid({
/// size : [ c_el.width, c_el.height ], /// [rows / cols ] //// 20 px x 10 px///
size : [ 70 , 70 ],
pos: [ 20, 20 ], /// [X, Y] ////
hex_def: {
radius: 20,
margin: 0
},
ctx : ctx,
ctx_pos: [ c_el.getBoundingClientRect().left, c_el.getBoundingClientRect().top ]
});
&#13;
<body stye="width: 100%; height: 100%" >
<canvas id="myCanvas" width="750px" height="405px" style="margin:0; padding:0; border:1px solid #d3d3d3;"></canvas>
</body>
&#13;