说明
在Canvas中绘制了多个矩形(位置互不重叠),点击矩形在矩形右侧弹出操作框,操作框内含有多个状态操作按钮,点击状态操作按钮后修改对应的矩形的背景色为与状态对应的颜色。
思路
1、使用数组存储多个矩形的信息,矩形信息中包含ID、位置、宽高、状态、文本,遍历数组绘制多个矩形;
2、给整个Canvas元素绑定单击事件,获取鼠标单击的位置信息;
3、遍历矩形数组,获取鼠标点中的矩形;如果有点中矩形,则在矩形右侧显示状态操作框,并将点中的矩形赋值给全局变量target;如果没有点中矩形且状态操作框处于显示状态则隐藏状态操作框;
4、点击状态操作按钮,遍历矩形数组修改与全局变量target的ID相同的矩形的状态;
5、遍历矩形数组重新绘制所有矩形。
实现步骤
1、创建文件骨架,引入 jquery;
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Canvas</title>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
// ...
</script>
</body>
</html>
2、全局变量
// 获取 Canvas 对象
var canvas = document.getElementById("canvas");
// 获取上下文环境对象
var ctx = canvas.getContext("2d");
// 状态与矩形背景色映射关系
var statusStyleMap = {
0: "#fffbf0",
1: "#45C552",
2: "#F45454",
3: "#FFE960",
4: "#5EB1FF",
};
// 需要绘制的矩形信息列表,含ID、坐标位置、宽度、高度、状态
var rectList = [
{
id: 1,
x: 50,
y: 50,
width: 200,
height: 30,
status: 0,
},
{
id: 2,
x: 200,
y: 100,
width: 200,
height: 30,
status: 0,
},
];
// 当前点中的矩形
var targetRect = null;
全局变量中我们定义了Canvas对象、上下文环境对象、状态与矩形背景色映射关系、需要绘制的矩形信息列表、当前点中的矩形。
3、定义绘制矩形的方法
// 绘制矩形
function drawRect(rect) {
ctx.strokeStyle = "#FDCC6B";
ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
var fileStyle = statusStyleMap[rect.status];
ctx.fillStyle = fileStyle;
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
// 绘制文本
ctx.textAlign = "left";
ctx.fillStyle = "#333333";
ctx.font = "18px 'Microsoft YaHei'";
//
ctx.fillText("Click Me.", rect.x + 10, rect.y + 18 + 4);
ctx.stroke();
}
页面加载完成后初始绘制所有矩形。
$(function () {
// 初始绘制矩形
for (var i = 0; i < rectList.length; i++) {
drawRect(rectList[i]);
}
});
所有矩形成功渲染后的效果图如下:
4、Canvas元素单击事件处理
// 画布点击事件绑定、处理
canvas.onclick = function (e) {
console.log("## canvas click ##");
// 控制台打印点击位置坐标信息
console.log("x: " + e.offsetX + ", y: " + e.offsetY);
// 获取点击的矩形
var target = rectList.find((item, index) => {
return (
e.offsetX >= item.x &&
e.offsetX <= item.x + item.width &&
e.offsetY >= item.y &&
e.offsetY <= item.y + item.height
);
});
// 如果获取到了矩形信息
if (target) {
targetRect = target;
// 设置状态操作区位置
$(".item-operations").css({
position: "absolute",
top: targetRect.y + $("#canvas").offset().top + "px",
left:
targetRect.x +
targetRect.width +
$("#canvas").offset().left +
"px",
});
// 显示状态操作区
$(".item-operations").show();
} else {
// 如果点击的是画布其它位置(非矩形上)则清空选中的矩形、隐藏状态操作区
targetRect = null;
$(".item-operations").hide();
}
};
Canvas中的矩形点击之后的效果图如下:
5、状态操作按钮单击事件处理
// 状态操作按钮单击事件绑定、处理
$(".item-operations li").click(function () {
console.log("## operation click ##");
var targetStatus = $(this).attr("data-status");
targetRect.status = targetStatus;
for (var i = 0; i < rectList.length; i++) {
if (rectList[i].id === targetRect.id) {
rectList[i].status = targetRect.status;
}
console.log("id: " + targetRect.id);
console.log(rectList[i]);
drawRect(rectList[i]);
}
$(".item-operations").hide();
});
选择状态后的效果图如下:
完整代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Canvas - 处理单击事件</title>
</head>
<body>
<canvas id="canvas" width="500" height="500"></canvas>
<ul class="item-operations" style="display: none">
<li data-status="1">通过</li>
<li data-status="2">不通过</li>
<li data-status="3">拒绝</li>
<li data-status="4">无条件</li>
<li data-status="0">未选择</li>
</ul>
<script type="text/javascript" src="jquery.min.js"></script>
<script type="text/javascript">
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
// 状态与fillStyle对应关系
var statusStyleMap = {
0: "#fffbf0",
1: "#45C552",
2: "#F45454",
3: "#FFE960",
4: "#5EB1FF",
};
// 需要绘制的矩形信息列表,含ID、坐标位置、宽度、高度、状态
var rectList = [
{
id: 1,
x: 50,
y: 50,
width: 200,
height: 30,
status: 0,
},
{
id: 2,
x: 200,
y: 100,
width: 200,
height: 30,
status: 0,
},
];
// 选择(点击)的矩形
var targetRect = null;
$(function () {
// 初始绘制矩形
for (var i = 0; i < rectList.length; i++) {
drawRect(rectList[i]);
}
// 状态操作按钮单击事件绑定、处理
$(".item-operations li").click(function () {
console.log("## operation click ##");
var targetStatus = $(this).attr("data-status");
targetRect.status = targetStatus;
for (var i = 0; i < rectList.length; i++) {
if (rectList[i].id === targetRect.id) {
rectList[i].status = targetRect.status;
}
console.log("id: " + targetRect.id);
console.log(rectList[i]);
drawRect(rectList[i]);
}
$(".item-operations").hide();
});
});
// 画布点击事件绑定、处理
canvas.onclick = function (e) {
console.log("## canvas click ##");
// 控制台打印点击位置坐标信息
console.log("x: " + e.offsetX + ", y: " + e.offsetY);
// 获取点击的矩形
var target = rectList.find((item, index) => {
return (
e.offsetX >= item.x &&
e.offsetX <= item.x + item.width &&
e.offsetY >= item.y &&
e.offsetY <= item.y + item.height
);
});
// 如果获取到了矩形信息
if (target) {
targetRect = target;
// 设置状态操作区位置
$(".item-operations").css({
position: "absolute",
top: targetRect.y + $("#canvas").offset().top + "px",
left:
targetRect.x +
targetRect.width +
$("#canvas").offset().left + "px",
});
// 显示状态操作区
$(".item-operations").show();
} else {
// 如果点击的是画布其它位置(非矩形上)则清空选中的矩形、隐藏状态操作区
targetRect = null;
$(".item-operations").hide();
}
};
// 绘制矩形
function drawRect(rect) {
ctx.strokeStyle = "#FDCC6B";
ctx.strokeRect(rect.x, rect.y, rect.width, rect.height);
var fileStyle = statusStyleMap[rect.status];
ctx.fillStyle = fileStyle;
ctx.fillRect(rect.x, rect.y, rect.width, rect.height);
// 绘制文本
ctx.textAlign = "left";
ctx.fillStyle = "#333333";
ctx.font = "18px 'Microsoft YaHei'";
//
ctx.fillText("Click Me.", rect.x + 10, rect.y + 18 + 4);
ctx.stroke();
}
</script>
<style>
.item-operations {
list-style: none;
margin: 0;
padding: 0;
width: 100px;
height: 124px;
background: #ffffff;
box-shadow: 0px 4px 10px 0px rgba(51, 51, 51, 0.1);
border-radius: 0px 0px 0px 0px;
border: 1px solid #fdcd6c;
}
.item-operations li {
height: 24px;
line-height: 24px;
text-align: center;
border-radius: 0px 0px 0px 0px;
cursor: pointer;
}
.item-operations li:hover {
background-color: #fdcd6c;
}
/* #FDCD6C */
</style>
</body>
</html>