我需要做以下工作:拥有一个普通的网页,能够使用鼠标、手写笔或手指(如果是平板电脑或智能手机)在文本上“绘制形状”,然后使用形状信息确定某些“动作”。
让我举个例子。想象一下stackoverflow上的这个问题,我在ipad上围绕这一段“画”了一个圆圈。圆圈(或者圆圈的尝试,手工绘制总是非常不完美的),“捕捉”段落,所以我知道我会对段落做出一个动作,就像,例如,选择所有内部文本。
我的问题是:这是否可行?有这样的图书馆吗?如果没有,哪些技术可以进行调查?
我一直在做自己的研究,但没有什么能给我所需要的。例如,画布完全按照我的需要绘制,但是画布不能在html页面上使用。它是页面上的另一个元素,而不是一个“包裹”另一个。
那么要回答最初的问题:这可行吗?
对
首先,你需要在纸上画画的能力。的HTML5
其次,您需要能够识别页面上的哪些元素被圈起来。javascript函数。getBoundingClientRect()对此很有用,因为它告诉我们x和y位置以及宽度和高度。因为这些值是基于它们相对于文档边界框的位置(而不是父元素),我们可以将其与绘制的圆的坐标进行比较。
因此,有了这两个组件,我们可以把这样的东西组合在一起。。。(我承认这有点笨重,但可以根据您的特定用例进行优化):
var canvas, ctx, flag, coords, cntnr, dot_flag;
function _InitDraw() {
flag = false;
coords = {
pX: 0,
cX: 0,
pY: 0,
cY: 0
};
cntnr = {
minX: document.body.offsetWidth,
minY: document.body.offsetHeight,
maxX: 0,
maxY: 0
};
dot_flag = false;
canvas = document.createElement('canvas');
canvas.id = "cnvTest";
canvas.style.position = "fixed";
canvas.style.top = 0;
canvas.style.left = 0;
document.body.appendChild(canvas);
canvas.style.width = "100%";
canvas.style.height = "100%";
canvas.style.zIndex = 9001;
ctx = canvas.getContext("2d");
ctx.canvas.width = window.innerWidth;
ctx.canvas.height = window.innerHeight;
canvas.addEventListener("mousemove", function (e) { _Draw('move', e); }, false);
canvas.addEventListener("mousedown", function (e) { _Draw('down', e); }, false);
canvas.addEventListener("mouseup", function (e) { _Draw('up', e); }, false);
//canvas.addEventListener("mouseout", function (e) { _Draw('out', e); }, false);
}
function _Draw(action, e) {
if(action == 'down') {
coords.pX = coords.cX;
coords.pY = coords.cY;
coords.cX = e.pageX;
coords.cY = e.pageY;
if(coords.cX < cntnr.minX) cntnr.minX = coords.cX;
if(coords.cY < cntnr.minY) cntnr.minY = coords.cY;
if(coords.cX > cntnr.maxX) cntnr.maxX = coords.cX;
if(coords.cY > cntnr.maxY) cntnr.maxY = coords.cY;
flag = true;
dot_flag = true;
if(dot_flag) {
ctx.beginPath();
ctx.fillStyle = "black";
ctx.lineCap = 'round';
ctx.fillRect(coords.cX, coords.cY, 2, 2);
ctx.closePath();
dot_flag = false;
}
}
if(action == 'up' || action == "out") {
flag = false;
_GetText();
}
if(action == 'move') {
if(flag) {
coords.pX = coords.cX;
coords.pY = coords.cY;
coords.cX = e.pageX;
coords.cY = e.pageY;
if(coords.cX < cntnr.minX) cntnr.minX = coords.cX;
if(coords.cY < cntnr.minY) cntnr.minY = coords.cY;
if(coords.cX > cntnr.maxX) cntnr.maxX = coords.cX;
if(coords.cY > cntnr.maxY) cntnr.maxY = coords.cY;
ctx.beginPath();
ctx.moveTo(coords.pX, coords.pY);
ctx.lineTo(coords.cX, coords.cY);
ctx.strokeStyle = "black";
ctx.lineCap = 'round';
ctx.lineWidth = 4;
ctx.stroke();
ctx.closePath();
}
}
}
function _GetText() {
// Find position and get closest element
document.body.removeChild(canvas);
var allEls = document.body.getElementsByTagName("*");
for(var i = 0; i < allEls.length; i++) {
var elBox = allEls[i].getBoundingClientRect();
if(elBox.x > cntnr.minX && elBox.x+elBox.width < cntnr.maxX && elBox.y > cntnr.minY && elBox.y+elBox.height < cntnr.maxY) {
// Do whatever you want with the element here.
// I am adding an outline for confirmation of the circled elements.
allEls[i].style.outline = "2px solid rgba(255, 255, 0, 0.8)";
if(allEls[i].innerText !== null && allEls[i].innerText !== "undefined") {
// Do something with the innerText here if you need the text from the element.
console.log(allEls[i].innerText);
}
}
}
}