在画布上绘制六边形,测试鼠标单击事件与六边形
Drawing Hexagon on Canvas, testing mouseclick event vs Hexagon
>我在画布上绘制一个基于六边形的网格。
每个六边形都是一个对象,用于保存 x/y 坐标中的 6 个点。每个六边形对象还保存其 X/Y 列/行索引。
var canvas = document.getElementById("can");
canvas.width = 200;
canvas.height = 200;
var ctx = canvas.getContext("2d");
var grid = []; // array that holds the Hex
var globalOffset = 30 // not important, just for smoother display atm
function Point(x, y) {
this.x = x;
this.y = y;
}
function Hex(x, y, size) {
this.size = 20;
this.x = x;
this.y = y;
this.points = [];
this.id = [];
this.create = function(x, y) {
var offSetX = (size / 2 * x) * -1
var offSetY = 0;
if (x % 2 == 1) {
offSetY = Math.sqrt(3) / 2 * this.size;
}
var center = new Point(
x * this.size * 2 + offSetX + globalOffset,
y * Math.sqrt(3) / 2 * this.size * 2 + offSetY + globalOffset
)
this.midPoint = center;
this.id[0] = x;
this.id[1] = y;
for (var i = 0; i < 6; i++) {
var degree = 60 * i;
var radian = Math.PI / 180 * degree;
var point = new Point(
center.x + size * Math.cos(radian),
center.y + size * Math.sin(radian)
)
this.points.push(point);
}
}
this.create(x, y);
}
}
//Determine where was clicked
canvas.addEventListener("click", function(e) {
var rect = canvas.getBoundingClientRect();
var pos = {
x: e.clientX - rect.left,
y: e.clientY - rect.top
}
document.getElementById("pos").innerHTML = "click on: " + pos.x + " " + pos.y;
});
// Creating Hexagons, setting up their center point, pushing them into Grid.
function init() {
for (var i = 0; i < 5; i++) {
for (var j = 0; j < 4; j++) {
var hex = new Hex(i, j, 20);
grid.push(hex)
}
}
//for each Hex in Grid, draw the Hex
for (var hex in grid) {
var item = grid[hex];
ctx.beginPath();
ctx.moveTo(item.points[0].x, item.points[0].y);
for (var k = 1; k < item.points.length; k++) {
ctx.lineTo(item.points[k].x, item.points[k].y);
}
ctx.closePath();
ctx.stroke();
var text = item.id;
ctx.fillStyle = "black";
ctx.fillText(text, item.midPoint.x - 7, item.midPoint.y - item.size / 2.2);
}
单击画布时,我想确定我是否单击了十六进制,如果单击了十六进制,则单击了哪个十六进制(按列/行)。它的数学问题。
我该怎么做?
这里的完整工作示例:http://codepen.io/anon/pen/RrMzKy?editors=1111
如果将
六边形中心视为圆心,则单击的六边形是中心最接近单击的六边形。 (应该可以在不测试到每个可能单元的距离的情况下对其进行优化)。
为了解释不完全覆盖,假设在可见六边形周围的附加环中有更多的(不可见)六边形。
如果选择了其中一个,或者距离大于圆半径,则单击不是在可见的六边形上。
在某种程度上基于对你自己提出的代码的重构,并避免两个循环,因为唯一的收获是消除了单个sqrt
函数:
Grid.prototype.getHexAt = function(pos) {
var closest = null;
var min = Infinity;
grid.hexes.forEach(function(hex) {
var dx = hex.center.x - pos.x;
var dy = hex.center.y - pos.y;
var distance = Math.sqrt(v.x * v.x + v.y * v.y);
if (distance < hex.size && distance < min) {
min = distance;
closest = hex;
}
});
return closest; // may return null
}
有趣的是,Alnitak的建议相当不错,因为六边形确实是一个圆。这是我的职能。比较鼠标通风口位置 x/y 与每个六边形圆和六边形固有尺寸(宽度/高度)。鼠标位置 x/y + 六边形大小是否接近六边形中心,您可能单击了这个六边形。仍然针对所有六边形进行测试。如果您"接近"多个,请获取鼠标路线 x/y 与所有有效六边形圆的矢量距离。矢量最短的六边形是您单击的六边形。
Grid.prototype.getHexAt = function(pos){
var inRange = [];
var closest = null;
for (var hex in grid.hexes) {
var item = grid.hexes[hex];
var center = item.center;
if (center.x + item.size > pos.x && center.x - item.size < pos.x) {
if (center.y + item.size > pos.y && center.y - item.size < pos.y) {
inRange.push(item);
}
}
}
if (inRange.length > 1) {
var pick = null;
var dist = null;
for (var i = 0; i < inRange.length; i++) {
var vector = {
x: inRange[i].center.x - pos.x,
y: inRange[i].center.y - pos.y
};
if (vector.x < 0) {
vector.x *= -1;
}
if (vector.y < 0) {
vector.y *= -1;
}
if (pick == null || vector.x + vector.y < dist) {
pick = inRange[i];
dist = vector.x + vector.y;
}
}
closest = pick;
}
else {
closest = inRange[0];
}
return closest;
};
相关文章:
- EaseJS拖放;放下(动画CC)电影剪辑的鼠标坐标
- 当鼠标悬停在文本中的单词上时显示警报
- JsFiddle上的鼠标事件不起作用
- 每当您在选择器内移动鼠标时,悬停功能就会重复
- 如何在鼠标悬停时在另一个图像上滑动图像.
- 鼠标悬停事件影响列表中所有行中的按钮,而不仅仅是特定按钮
- 将鼠标旋转限制为特定的度数
- 跟踪jqplot垂直折线图的鼠标位置
- node-webkit-从父窗口捕获iframe鼠标事件
- 悬停下拉菜单即使在鼠标移出后也保持活动状态
- Javascript-在视频中跟踪鼠标位置
- JQuery UI可拖动潜水与滚动棒到鼠标
- 如何在jquery中找到鼠标滚轮/触摸移动事件的走向
- 在鼠标悬停时展开列表
- jQuery悬停在没有鼠标悬停的情况下启动
- 鼠标输入在 YUI 的 chrome 中不起作用
- 鼠标悬停时如何居中放大背景图像
- 鼠标光标-用于wordpress网站
- 当我在节点上拖动鼠标时,我如何防止使用d3.ehavior.zoom().on(“缩放”,重绘)
- 在画布上绘制六边形,测试鼠标单击事件与六边形