應(yīng)用場景
我們最近開發(fā)了一款筆跡測試功能的程序(測試版),用戶在手寫板上手寫簽名,提交后即可測試出被測試者的心理素質(zhì)評價分析。類似功能的場景還比如,在銀行柜臺辦理業(yè)務(wù),期間可能需要您使用手寫設(shè)備進(jìn)行簽名并確認(rèn);保險續(xù)期小程序,到期后需要你在確認(rèn)續(xù)期條款后,在手機(jī)上提供的簽名區(qū)域進(jìn)行簽名并提交確認(rèn)。
實現(xiàn)效果
筆跡測試顯示界面如下:
可選擇畫筆顏色(默認(rèn)為黑色筆) ,在虛線框內(nèi)可隨便寫一段文字,點擊提交即可。當(dāng)然程序還提供拍照上傳功能,這里不再詳述。下面我們開始介紹,C#如何結(jié)合JavaScript實現(xiàn)手寫板寫字并上傳到服務(wù)器進(jìn)行處理。
開發(fā)運(yùn)行環(huán)境
操作系統(tǒng): Windows Server 2019 DataCenter
手寫觸屏設(shè)備:Microsoft Surface Pro 9
.net版本:?.netFramework4.0 或以上
開發(fā)工具:VS2019 ?C#
設(shè)計實現(xiàn)
手寫功能
設(shè)計采用了 iframe 嵌入式的方式實現(xiàn) JavaScript 前端,假設(shè)頁面為?hw.aspx ,該頁面實現(xiàn)了手寫功能、重寫功能、畫筆選擇功能和提交功能,其完整示例代碼如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=yes"/>
<title>手寫板</title>
<style type="text/css">
html,body{
margin: 0;
padding: 0;
}
.saveimg{
text-align: center;
}
.saveimgs span{
display: inline-block;
margin-top:5px;
}
</style>
</head>
<body>
<script src="jquery-3.3.1.min.js"></script>
<div align="center">
<canvas id="myCanvas" width="500" height="300" style="border:1px dotted #6699cc"></canvas>
<div class="control-ops control">
<button type="button" class="btn btn-primary" onclick="javascript:clearArea();return false;">重寫</button>
<select style="display:none" id="selWidth" onchange="aaa()">
<option value="1">1</option>
<option value="3" selected="selected">3</option>
<option value="5">5</option>
<option value="7">7</option>
<option value="9">9</option>
<option value="11">11</option>
</select>
<select id="selColor" onchange="aaa2()">
<option value="black" selected="selected">黑色筆</option>
<option value="blue">藍(lán)色筆</option>
<option value="red">紅色筆</option>
<option value="green">綠色筆</option>
<option value="yellow">黃色筆</option>
<option value="gray">深灰筆</option>
</select>
<button type="button" class="saveimg" onclick="javascript:saveImageInfo();return false;">提交</button>
</div>
<div class="saveimgs"></div>
</div>
</body>
<script type="text/javascript">
var mousePressed = false;
var lastX, lastY;
var ctx = document.getElementById('myCanvas').getContext("2d");
var c = document.getElementById("myCanvas");
var control = document.getElementsByClassName("control")[0];
var saveimgs = document.getElementsByClassName("saveimgs")[0];
window.onload = function () {
document.getElementById('myCanvas').setAttribute("width", $(window).width()-5);
InitThis();
}
function saveImageInfo(){
var image = c.toDataURL("image/png");
window.parent.document.getElementById('pbase64').value = image;
window.parent.document.getElementById('phw').click();
return;
var ctximg = document.createElement("span");
ctximg.innerHTML = "<img src='"+image+"' alt='from canvas'/>";
if(saveimgs.getElementsByTagName('span').length >= 1){
var span_old = saveimgs.getElementsByTagName("span")[0];
saveimgs.replaceChild(ctximg,span_old)
}
else{
saveimgs.appendChild(ctximg);
}
}
var selected1,selected2;
function aaa(){
var sel = document.getElementById('selWidth');
var value = sel.selectedIndex;
return selected1 = sel[value].value;
}
function aaa2(){
var sel2 = document.getElementById('selColor');
var value = sel2.selectedIndex;
return selected2 = sel2[value].value;
}
function InitThis() {
// 觸摸屏
c.addEventListener('touchstart', function (event) {
console.log(1)
if (event.targetTouches.length == 1) {
event.preventDefault();// 阻止瀏覽器默認(rèn)事件,重要
var touch = event.targetTouches[0];
mousePressed = true;
Draw(touch.pageX - this.offsetLeft, touch.pageY - this.offsetTop, false);
}
},false);
c.addEventListener('touchmove', function (event) {
console.log(2)
if (event.targetTouches.length == 1) {
event.preventDefault();// 阻止瀏覽器默認(rèn)事件,重要
var touch = event.targetTouches[0];
if (mousePressed) {
Draw(touch.pageX - this.offsetLeft, touch.pageY - this.offsetTop, true);
}
}
},false);
c.addEventListener('touchend', function (event) {
console.log(3)
if (event.targetTouches.length == 1) {
event.preventDefault();// 阻止瀏覽器默認(rèn)事件,防止手寫的時候拖動屏幕,重要
mousePressed = false;
}
},false);
/*c.addEventListener('touchcancel', function (event) {
console.log(4)
mousePressed = false;
},false);*/
// 鼠標(biāo)
c.onmousedown = function (event) {
mousePressed = true;
Draw(event.pageX - this.offsetLeft, event.pageY - this.offsetTop, false);
};
c.onmousemove = function (event) {
if (mousePressed) {
Draw(event.pageX - this.offsetLeft, event.pageY - this.offsetTop, true);
}
};
c.onmouseup = function (event) {
mousePressed = false;
};
}
function Draw(x, y, isDown) {
if (isDown) {
ctx.beginPath();
ctx.strokeStyle = selected2;
ctx.lineWidth = selected1;
ctx.lineJoin = "round";
ctx.moveTo(lastX, lastY);
ctx.lineTo(x, y);
ctx.closePath();
ctx.stroke();
}
lastX = x; lastY = y;
}
function clearArea() {
ctx.setTransform(1, 0, 0, 1, 0, 0);
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
// 清除簽名圖片
if(saveimgs.getElementsByTagName('span').length >= 1){
var clearImg = saveimgs.getElementsByTagName('span')[0];
saveimgs.removeChild(clearImg);
}
}
</script>
</html>
該頁面需要引用?jquery-3.3.1.min.js ,可下載我的鏈接資源:
https://download.csdn.net/download/michaelline/89226046
前端引用
前端頁面除嵌入手寫功能頁面外,iframe的父窗口需要放置兩個元素,一個用于存儲手寫提交后的Base64數(shù)據(jù)的 Asp.net 服務(wù)器按鈕文本框元素,另一個是用于模擬調(diào)用服務(wù)器事件的 Asp.net 服務(wù)器按鈕元素。
引用代碼如下:
<div style=" text-align:center">
<iframe width="520" height="350" id="hw" runat="server" scrolling="no" frameborder="0" src="/cc/module/hw/hw.aspx" ></iframe>
<asp:TextBox ID="pbase64" TextMode="MultiLine" style="display:none" runat="server" ></asp:TextBox>
<asp:button ID="phw" OnClientClick="waittip()" text="后臺處理" runat="server" style="display:none" onclick="phw_Click" />
</div>
后端處理
手寫功能中的提交執(zhí)行代碼將調(diào)用如下:
window.parent.document.getElementById('pbase64').value = image;
window.parent.document.getElementById('phw').click();
其中 pbase64 和 phw 控件為服務(wù)器控件,可直接模擬調(diào)用 phw 按鈕的服務(wù)器 click,在這之前其還可以自動處理 OnClientClick事件以顯示等待界面。請注意 waittip() 執(zhí)行了一段 javascript 腳本,如下:
function waittip() {
layer.open({ type: 2, shadeClose: false, content: '正在分析,請稍候...' });
}
?這其中引入了 Layer 彈出層技術(shù),關(guān)于 Layer 彈層組件請參照我的文章《改造 layer 彈層移動版組件》,下載JS請訪問如下鏈接:
https://download.csdn.net/download/michaelline/88406984
這是調(diào)用服務(wù)器Click的事件處理代碼,將上傳的Base64圖片轉(zhuǎn)為兩種格式的圖片文件(PNG和JPEG)。代碼如下:
protected void phw_Click(object sender, EventArgs e)
{
string mtfilename = "d:\\hw_" + System.Guid.NewGuid().ToString() + ".png";
string mtfilename2 = "d:\\hw_" + System.Guid.NewGuid().ToString() + ".jpg";
string dummyData = pbase64.Text.Trim().Replace("data:image/png;base64,", "");
Base64StringToImage(dummyData, mtfilename);
if (File.Exists(mtfilename)==false)
{
base64.ImageUrl = dummyData;
layer.open("保存手寫圖片失敗,請重試并提交。" , "'確定'", "error");
return;
}
System.Drawing.Image img = System.Drawing.Image.FromFile(mtfilename);
using (var b = new System.Drawing.Bitmap(img.Width, img.Height))
{
b.SetResolution(img.HorizontalResolution, img.VerticalResolution);
using (var g = System.Drawing.Graphics.FromImage(b))
{
g.Clear(System.Drawing.Color.White);
g.DrawImageUnscaled(img, 0, 0);
}
b.Save(mtfilename2, System.Drawing.Imaging.ImageFormat.Jpeg);
}
}
小結(jié)
本示例中的前后端代碼僅為展示參考,手寫功能在支持觸屏的設(shè)備可以支持手寫,也可以用鼠標(biāo)進(jìn)行模擬。
服務(wù)器調(diào)用示例中需要使用 Base64StringToImage(dummyData, mtfilename); 方法由Base64數(shù)據(jù)轉(zhuǎn)化為圖片文件,代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-861791.html
public bool Base64StringToImage(string strbase64, string outputFilename)
{
byte[] arr = Convert.FromBase64String(strbase64);
MemoryStream ms = new MemoryStream(arr);
System.Drawing.Image img = System.Drawing.Image.FromStream(ms);
img.Save(outputFilename);
img.Dispose();
if (File.Exists(outputFilename))
{
return true;
}
return false;
}
感謝您的閱讀,希望本文能夠?qū)δ兴鶐椭?span toymoban-style="hidden">文章來源地址http://www.zghlxwxcb.cn/news/detail-861791.html
到了這里,關(guān)于C# 結(jié)合JavaScript實現(xiàn)手寫板簽名并上傳到服務(wù)器的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!