我正在尝试为使用鼠标或 iPhone 等触摸屏设备工作的网站制作签名板。我成功地让垫子与鼠标一起工作,但在 iPhone 上使用触摸屏时遇到了一些奇怪的问题。签名板本身都是在客户端完成的,方法是在 3 个单独的数组中记录移动到、行到和新行位置,然后在用户绘图时使用 div 段中的 svg 标签构建行。
我遇到的问题是,当使用触摸屏时,您绘制的第一条线一切正常,但如果您将手指放在屏幕上并将其放回以绘制新线,系统将停止记录用户的移动手指。这是代码示例。
Javascript:
var moved;
//Load Event Listeners
function LoadList(){
document.getElementById('SigCan').addEventListener('touchstart',function(e){e.preventDefault();TrackNow();},false);
document.getElementById('SigCan').addEventListener('touchmove',function(e){e.preventDefault();touchMove(e);},false);
document.getElementById('SigCan').addEventListener('touchend',function(e){e.preventDefault();StopTrack();},false);
document.getElementById('SigCan').addEventListener('touchenter',function(e){e.preventDefault();TrackNow();},false);
}
function touchMove(e){
e.preventDefault;
//var sigobj = e.changedTouches[0];
//var length;
//length = length - 1
//alert(length);
getMouseXY(e.changedTouches[0]);
}
//Set value to isSig to true (mainly for mouse movement to track when button is pressed down
function TrackNow(){
document.getElementById('<%=isSig.ClientId%>').value = 'True';
}
//Set new line flag and reset moved flag. Reset isSig value
function StopTrack(){
if(moved == 1){
//alert('Stopped');
document.getElementById('<%=isSig.ClientId%>').value = 'False';
newline = 1;
moved = 0;
}
}
// Main function to retrieve mouse x-y pos.s, fill textboxes for server side code.
function getMouseXY(e) {
var signon;
var obj;
signon = document.getElementById('<%=isSig.ClientId%>').value;
if (signon == 'True'){
OX = tempX;
OY = tempY;
if (OX == 0){
OX = tempX;
}
if (OY == 0){
OY = tempY;
}
obj = document.getElementById('SigCan');
tempX = e.clientX - document.getElementById('SigCan').offsetLeft;
tempY = e.clientY - document.getElementById('SigCan').offsetTop;
//Remove all offsets
if(obj.offsetParent){
do{
tempX -= obj.offsetLeft;
tempY -= obj.offsetTop;
}while (obj = obj.offsetParent)
}
//Fill newline array, reset new line flag, set the old X & Y to current X & Y so line starts and new position.
if (newline == 1){
newobj[n] = OX + ',' + OY;
OX = tempX;
OY = tempY;
newline = 0;
n = n + 1;
}
//Fill moveto and lineto arrays
mtarray[i] = OX + "," + OY;
ltarray[i] = tempX + "," + tempY;
//Fill textboxes to be used in server side code
i = i + 1;
if (mtarray[1] != '') {
//document.getElementById('<%=mtAr.ClientId%>').value = tempX + "," + tempY;
document.getElementById('<%=mtAr.ClientId%>').value = mtarray.join('|');
document.getElementById('<%=ltAr.ClientId%>').value = ltarray.join('|');
document.getElementById('<%=nobj.ClientId%>').value = newobj.join('|');
}
mtarray[0] = ltarray[0];
//set moved flag to 1 so touchend code only runs after finger has been moved
moved = 1;
//Build svg and insert into inner html of the div segment
return DrawSig();
}
return true;
}
function DrawSig(){
var inhtml;
sigpath = ''
//check browser
ubrow = BrowserDetect.browser + ' ' + BrowserDetect.version;
//get path information
sigpath = BuildPath();
//if using IE 8 or 7 insert vml into inner HTML of div
if(ubrow == 'Explorer 8'||ubrow == 'Explorer 7'){
document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', "#default#VML");
inhtml = "<v:group style='position:absolute;antialias:true;height:100px;width:500px' coordsize='500,100' coordorigin='0,0'><v:shape style='postition:absolute;height:100px;width:500px' strokeweight = '3pt' ><v:stroke joinstyle='round' endcap='round'/>";
inhtml = inhtml + "<v:path v ='" + sigpath + " '/>";
inhtml = inhtml + "</v:shape></v:group>";
document.getElementById('SigCan').innerHTML = inhtml;
//document.getElementById('ctl00_mtAr').value = inhtml
}
//if using any other browser insert svg into inner HTML of div
else{
inhtml = "<svg><g fill='none' stroke='black' stroke-width='4'><path d='" + sigpath + "'/></g></svg>";
document.getElementById('SigCan').innerHTML = inhtml;
//document.getElementById('<%=mtAr.ClientId%>').value = 'Working as it should';
}
return false;
}
function BuildPath(){
var path;
//Build vml path for ie 7 & 8
if(ubrow == 'Explorer 8'||ubrow == 'Explorer 7'){
path = 'M ' + mtarray[0] + ' L ' + ltarray[0];
for(var p = 1;p < i; p++){
path = path + ' M ' + mtarray[p] +' L ' + ltarray[p];
}
}
//Build svg path for other browsers
else{
path = ' M ' + mtarray[0].replace(',',' ') + ' L ' + ltarray[0].replace(',',' ');
for(var p = 1;p < i; p++){
path = path + ' M ' + mtarray[p].replace(',',' ') + ' L ' + ltarray[p].replace(',',' ');
}
}
return path;
}
HTML:
<body>
<table>
<tr>
<td colspan=3>
<div id ="SigCan" style="width:500px;height:100px;border:1px solid #c3c3c3;background:white;cursor:crosshair" onmousemove = "return getMouseXY(event);" onmousedown = "return TrackNow();" onmouseup = "return StopTrack();">
</div>
<script>
LoadList();
</script>
<asp:image runat = "Server" id ="SigImg"/>
</td>
</tr>
<tr>
<td><asp:textbox runat="Server" id="mtAr"/></td>
<td><asp:textbox runat="Server" id="ltAr"/><asp:textbox runat="Server" id ="nobj"/></td>
<td><asp:hiddenfield runat="Server" id="isSig"/></td>
</tr>
<tr>
<td><asp:button runat="Server" id = "btnSave" text="Save Signature" autopostback = "False"/><asp:checkbox id="chkVerify" runat="Server" text="I verify the above signature is mine." visible="false"/></td>
<td><asp:button id ="btnVerify" runat="server" text="Verify" visible = "false" onclick="VerifySig" /></td>
<td align="right"><asp:button id="btnClear" runat="Server" text = "Clear Signature" OnClientClick="return ClearSig();"/></td>
<td><asp:button id="Sig" runat="Server" OnClientClick="return SigP();" text="Give Me sig Path"/></td>
</tr>
</table>
</body>
我知道画布对象可能会更容易,但我需要让它在运行 IE8 的计算机和触摸屏上通过鼠标工作。到目前为止,我还没有找到修复程序,但我已经将问题缩小到这行代码document.getElementById('SigCan').innerHTML = inhtml;
如果我注释掉这段代码一切正常,但这是将 SVG 路径放入 div 段的代码所以我需要它。
我发现的唯一另一件事是,当发生此错误时,由于某种原因,在绘制第一行后似乎 touchend 事件没有运行,我必须双击屏幕才能注册 touchend。当它停止响应时,我可以再次按下屏幕并将其记录为另一个触摸点。我对触摸屏非常陌生,并且在 Javascript 方面只是一个业余爱好者,所以我想知道是否有人可以提供帮助。
编辑 1: 我还没有找到解决方法,但我确实发现了实际发生的情况。出于某种原因,当您将手指从触摸屏上移开然后放回触摸屏上时,无论您在哪里移动手指,touchmove 事件都只会触发一次,并且永远不会再次触发。出于某种原因,如果您在发生这种情况时将手指从屏幕上移开,则 touchend 事件不会运行,但如果您在目标区域中点击屏幕,它将运行。