2

我正在尝试为使用鼠标或 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 事件不会运行,但如果您在目标区域中点击屏幕,它将运行。

4

1 回答 1

1

好的,找到问题了。显然,当将 DIV 的 innerHTML 设置为 SVG 时,触摸事件的目标第二次变成了没有触摸事件的 SVG 本身。在多次尝试修复它之后,最好的方法是在包含 SVG 的当前 DIV 上放置另一个 DIV,然后在新的 DIV 元素上触发所有触摸事件。我必须将两个 div 的位置都更改为绝对位置,以便新的 div 可以放在旧的 div 上。这会导致设计问题,但这些问题很容易解决。现在一切似乎都正常了。

于 2013-10-03T20:43:48.143 回答