使用JavaScript和HTML5绘制橡皮筋线
除了绘制橡皮筋线条,你还可以了解自定义光标和数组存储。
引言
我的主要目标是解决在画布上绘制橡皮筋线条的问题。我使用了位于原始画布之上(z-index!)的透明副本画布。副本画布仅在输入过程中“可见”,否则 <display:"none">。
我的程序是一个类似于 CAD 的 2D 绘图解决方案,具有重力(吸附)功能。你可以绘制线条、多线、圆形和弧线。智能(自定义)光标反映了几何元素和光标位置之间的关系。
元素数据存储在 sessionStorage 中。如何存储和检索对象数组并不显而易见:我使用了 JSON 函数来实现。
所使用的工具提示解决方案并非我创建的。
你可以在 此页面 上试用此应用程序。
使用代码
我附上了一个 htm 文件,js 文件夹中的三个 js 文件,以及光标文件夹中的自定义光标图像文件。
现在我分享一些代码文件中的重要细节
如何创建副本画布?
htm 文件中的原始画布
<div id = "canvasId">
<canvas id="myCanvas" width=...; z-index: 1;">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
副本 JavaScript 函数
function SetCanvasLayer (p_canvas, p_divId, p_moveFunc, p_cancelFunc) {
var rubberDiv = document.getElementById(p_divId);
var layer = document.getElementById(canvasRubber);
if (layer == null) {
canvasRubber = document.createElement('canvas');
rubberDiv.appendChild(canvasRubber);
ctxRubber = canvasRubber.getContext("2d");
canvasRubber.width = p_canvas.width;
canvasRubber.height = p_canvas.height;
canvasRubber.setAttribute("style", p_canvas.getAttribute("style"));
canvasRubber.style.backgroundColor = "transparent";
canvasRubber.style.zIndex = parseInt(p_canvas.style.zIndex) + 1;
canvasRubber.style.cursor = "url(Cursors/pencil.png) 6 28, crosshair";
canvasRubber.style.display = "none";
canvasRubber.innerHTML = "Your browser does not support the HTML5 canvas tag.";
canvasRubber.onclick = LayerClick;
canvasRubber.onmousemove = LayerMouseMove;
window.addEventListener("keydown", LayerKeyDown, false);
moveFunction = p_moveFunc;
cancelFunction = p_cancelFunc;
}
}
第一次点击事件由原始画布处理。根据单选按钮,它的函数必须调用 StartRubberLine
函数,例如。之后,副本画布变得“可见”,并接收鼠标事件。
LayerMouseMove
函数在 mousemove 事件时被调用。此函数调用 - 除其他外 - DrawRubberLine
函数
function DrawRubberLine(pos, clear) {
if (clear == true) {
ClearCanvas();
}
ctxRubber.strokeStyle = colorRubber;
ctxRubber.beginPath();
ctxRubber.moveTo(startx, starty);
ctxRubber.lineTo(pos.x, pos.y);
ctxRubber.stroke();
}
通常,我们必须在绘制之前清除画布
function ClearCanvas() {
ctxRubber.clearRect(0, 0, canvasRubber.width, canvasRubber.height);
var w = canvasRubber.width;
canvasRubber.width = 1;
canvasRubber.width = w;
}
StoreGeomElemObj
函数将数据存储到 sessionStorage
中。存储的数据是一个数组。数组中的一个项目是一个包含数字、字符串和坐标数组的对象。
function StoreGeomElemObj(p_elem, p_storageId) {
var store = sessionStorage.getItem(p_storageId);
if (store == null) {
store = new Array(0);
}
else {
store = JSON.parse(store);
}
store.push(p_elem);
sessionStorage.setItem(p_storageId, JSON.stringify(store));
}
要检索原始对象项,请使用以下函数
function GetGeomElemObj(p_index, p_storageId) {
var store = sessionStorage.getItem(p_storageId)
if (store == null) {
return null;
}
else {
store = JSON.parse(store);
return store[p_index];
}
}
要获取对象数组中的元素数量,请使用以下函数
function GetArrayLength (obj) {
var i = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
i++;
}
}
return i;
};
重力系统是一个包含几何计算的复杂代码。例如,如果光标靠近一条线段的端点,光标会改变其形状:在输入过程中显示管道或条纹铅笔。
var CursorPencilStriped = "url(cursors/pencilstriped.png) 6 28, crosshair";
canvasRubber.style.cursor = CursorPencilStriped ;
重力系统还可以帮助你绘制垂直线。弧线的重力是你的任务 :) 我可以做到:请参阅 此页面。
最后,这里有一个提示:你可以通过返回弧线的起始点来改变弧线的方向。