Canvas如何实现拾取矩形?

拾取矩形的实现

判断规则:

在判断点与矩形是否相交的问题上,存在一个明确的规则。当点的X坐标落在矩形起点X坐标与起点X坐标加上矩形宽度之间(包括两者),并且点的Y坐标也落在矩形起点Y坐标与起点Y坐标加上矩形高度之间(包括两者)时,我们可以确定该点位于矩形内部。反之,如果点的X坐标或Y坐标超出这一范围,则可以判断点不在矩形内。

这个规则基于几何形状的基本属性,为点与矩形的位置关系提供了明确的判断依据。在实际应用中,我们可以根据这一规则进行点与矩形相交性的判断,从而进行相应的空间分析或计算。

示例效果与源代码:

运行效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
<!DOCTYPE html>
<html>

<head>
<title>点图查询-几何法</title>
<meta charset="UTF-8">
<!-- frame所需脚本和样式 -->
<script type="text/javascript" src="/examples/script/lib/jquery-1.11.2.min.js"></script>
<link type="text/css" rel="stylesheet" href="/examples/script/bootstrap-3.3.5/css/bootstrap.min.css">
<script src="/examples/graph/js/helper.js"></script>
</head>

<body style="overflow: hidden; margin:10px;">
<div id="graphWrapper" style="width:850px; height:500px; border:solid 1px #CCC;"></div>
<div style="margin:10px; text-align: left;">
<div class="checkbox" style="font-size: 16px;">
<label style="margin-right:20px"><input id="chkPoint" type="checkbox"></label>
<label style="margin-right:20px"><input id="chkRect" type="checkbox">矩形</label>
<label style="margin-right:20px"><input id="chkPolyline" type="checkbox">线</label>
<label style="margin-right:20px"><input id="chkPolygon" type="checkbox">多边形</label>
<label style="margin-right:20px"><input id="chkCircle" type="checkbox">圆形</label>
<label style="margin-right:20px"><input id="chkEllipse" type="checkbox">椭圆</label>
<label style="margin-right:20px"><input id="chkText" type="checkbox">文字</label>
</div>
</div>
</body>
<script type="module">
import {
Graph, Layer, VectorSource, debug, Color, MathUtil, Collide, circle2LineRing, getStarLineRing,
GGeometryType, Rect, Point, Circle, Ellipse, Text, Polyline, Polygon,
} from "/examples/src/index.js";

// graph对象
let graph = new Graph({
"target": "graphWrapper"
});

// 网格水印层
let debugLayer = debug.generateGrid(Object.assign({ "interval": 10, "graph": graph }, graph.getSize()));
debugLayer.getSource().add(new Text({
"text": "按点拾取(几何法)Demo",
"x": graph.getSize().width / 2,
"y": graph.getSize().height / 2,
"vectorSize": false,
"style": { "lineWidth": 4, "fillStyle": 0, "fillColor": "#D0D0D0", "fontSize": 30, "fontName": "黑体", "textAlign": "center", "textBaseline": "middle" }
}));

// 新建绘图图层
let layer = graph.addLayer();
// 浮动层
let overLayer = graph.addOverLayer();

// pageload
$(document).ready(function () {

$("#hitGraph").append(graph.getRenderer().getHitImage());

graph.getRenderObject().on('mousemove', function (e) {
let point = [e.offsetX, e.offsetY];
let coord = graph.getCoordinateFromPixel(point, true);

// 清空浮动层数据
overLayer.getSource().clearData();

// 碰撞检测
_collideCheck(coord);

// 鼠标位置点
overLayer.getSource().add(new Point({
"x": coord[0],
"y": coord[1],
"size": -5,
"style": { "fillColor": "blue", "fillStyle": 1, "color": "none" }
}));

// 图形重绘
graph.renderLayer(overLayer);
});

// 逐一与数据层中的对象进行碰撞检测
function _collideCheck(coord) {
let datas = layer.getSource().getData();
for (let i = 0, len = datas.length; i < len; i++) {
if (datas[i].contain([coord[0], coord[1]])) {
let clone = datas[i].clone();
clone.setStyle({ "fillColor": "#FF2020", "color": "#FF2020", "lineWidth":4 });
overLayer.getSource().add(clone);
return true;
}
}
return false;
}

// 复选框状态事件:清空或随机生成对象
$("#chkPoint").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(6, 10); i++) {
layer.getSource().add(new Point({
"x": MathUtil.getRandomNum(50, 800),
"y": MathUtil.getRandomNum(50, 450),
"size": MathUtil.getRandomNum(10, 20),
"style": { "fillColor": "#FFDFDF", "fillStyle": 1, "lineWidth": 1, "color": "#FFA5E8" }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.POINT);
}
graph.render();
});

$("#chkRect").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(6, 10); i++) {
layer.getSource().add(new Rect({
"x": MathUtil.getRandomNum(50, 800),
"y": MathUtil.getRandomNum(50, 450),
"width": MathUtil.getRandomNum(40, 70),
"height": MathUtil.getRandomNum(20, 40),
"style": { "fillColor": "#FFDFDF", "fillStyle": 1, "lineWidth": 1, "color": "#FFA5E8" }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.RECT);
}
graph.render();
});

$("#chkCircle").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(6, 10); i++) {
layer.getSource().add(new Circle({
"x": MathUtil.getRandomNum(50, 800),
"y": MathUtil.getRandomNum(50, 450),
"radius": MathUtil.getRandomNum(20, 40),
"style": { "fillColor": "#DFFFBF", "fillStyle": 1, "lineWidth": 1, "color": "#FFA5E8" }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.CIRCLE);
}
graph.render();
});

$("#chkText").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(6, 10); i++) {
layer.getSource().add(new Text({
"x": MathUtil.getRandomNum(50, 800),
"y": MathUtil.getRandomNum(50, 450),
"text": "碰撞检测文本",
"style": { "fontSize": 24, "fontName": "黑体", "fillColor": "#0000FF", }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.TEXT);
}
graph.render();
});

$("#chkEllipse").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(6, 10); i++) {
layer.getSource().add(new Ellipse({
"x": MathUtil.getRandomNum(50, 800),
"y": MathUtil.getRandomNum(50, 450),
"radiusX": MathUtil.getRandomNum(20, 40),
"radiusY": MathUtil.getRandomNum(20, 20),
"style": { "fillColor": "#9FFFFF", "fillStyle": 1, "lineWidth": 1, "color": "#FFA5E8" }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.ELLIPSE);
}
graph.render();
});

$("#chkPolyline").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(6, 10); i++) {
let [x, y] = [MathUtil.getRandomNum(50, 620), MathUtil.getRandomNum(50, 400)];
layer.getSource().add(new Polyline({
"coords": [[x, y], [x + MathUtil.getRandomNum(10, 300), y + MathUtil.getRandomNum(-100, 100)]],
"style": { "lineWidth": 4, "color": "#00957D" }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.POLYLINE);
}
graph.render();
});

$("#chkPolygon").on("change", function () {
if ($(this).prop("checked")) {
for (let i = 0; i < MathUtil.getRandomNum(3, 5); i++) {
let center = [MathUtil.getRandomNum(150, 620), MathUtil.getRandomNum(50, 400)];
let sideNum = MathUtil.getRandomNum(3, 8);
let radius = MathUtil.getRandomNum(20, 40);
layer.getSource().add(new Polygon({
"coords": circle2LineRing(center, radius, sideNum),
"style": { "fillColor": "#E5FFF5", "fillStyle": 1, "lineWidth": 1, "color": "#FF9F9F" }
}));

center = [MathUtil.getRandomNum(150, 620), MathUtil.getRandomNum(50, 400)];
layer.getSource().add(new Polygon({
"coords": getStarLineRing(center, radius, null, sideNum >= 6 ? sideNum - 3 : sideNum),
"style": { "fillColor": "#E5FFF5", "fillStyle": 1, "lineWidth": 1, "color": "#FF9F9F" }
}));
}
} else {
layer.getSource().clearTypeData(GGeometryType.POLYGON);
}
graph.render();
});
})

</script>

</html>

尝试一下 »