整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JQ利用canvas,實現移動端手寫板 「筆記」

          JQ利用canvas,實現移動端手寫板 「筆記」

          近公司項目需求,客戶可以直接在textarea可以輸入簽名,經過研究,采用Canvas解決,廢話少說,直接上代碼,樣式可根據設計圖自行修改。

          僅此個人筆記,分享學習 。有不足之處,望大佬指點學習,共勉!!!


          <!DOCTYPE html>
          <html>
          <head>
          	<meta charset="UTF-8">
              <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
          	<title></title>
          </head>
          <style type="text/css">
          	*{
          		margin: 0;
          		padding: 0;
          	}
          	.from_list{
          		width: 96%;
          		margin: 0 2%;
          		color: #353535;
          		line-height: 2rem;
          		background: #FFFFFF;
          		border-top: 1px solid #EEEEEE;
          		border-bottom: 1px solid #EEEEEE;
          		display: -webkit-box;
          		display: -ms-flexbox;
          		display: flex;
          		display: -webkit-flex;
          		align-items: center;
          		-webkit-align-items: center;
          		justify-content: space-between;
          		-webkit-justify-content: space-between;
          	}
          	#reset_btn {
          	    width: 4rem;
          	    color: #ffffff;
          	    font-size: 0.7rem;
          	    text-align: center;
          	    line-height: 1.5rem;
          	    background: #2F7DCD;
          	    border-radius: 0.15rem;
          	    -webkit-border-radius: 0.15rem;
          	}
          	.sign_box {
          		margin-top: 1rem;
          	    padding: 0 0.75rem 0.5rem 1rem;
          	    background: #ffffff;
          	}
          	.sign_content {
          	    border: 1px solid #CCCCCC;
          	}
          	#canvas_box {
          	    width: 100%;
          	    height: 10rem;
          	}
          	canvas {
             		 height: 10rem !important;
          	}
          	.submit_box {
          		width: 92%;
          		margin: 0 4%;
          	    height: 2.4rem;
          	    line-height: 2.4rem;
          	    background: #2F7DCD;
          	   	border-radius: 0.2rem;
          	    color: white;
          	    text-align: center;
          </style>
          <body>
          	<div class="from_list _bor_bottom0"><div>商戶手動簽字 <var>*</var></div><div id="reset_btn">重寫</div></div>
              <div class="sign_box">
                  <div class="sign_content">
                      <div id="canvas_box"></div>
                  </div>
              </div>
               <div class="submit_box" id="submit_btn">提交</div>
          </body>
          <script type="text/javascript" src="./js/jquery.js"></script>
          <script type="text/javascript" src="./js/jSignature.min.js"></script>
          <script type="text/javascript" src="./js/flashcanvas.js"></script>
          <script type="text/javascript">
          	 // *********電子簽名功能*********
              let canvas_box=$("#canvas_box");    // 獲取canvas標簽
              canvas_box.jSignature(); // 初始化簽名畫板,初始化之后就可以進行操作
              let signImgSrc="";   // 提交后臺的圖片路徑
              // 監聽手動簽名滑動開始、移動、釋放時,執行輸入框失去焦點的功能,解決簽名時觸發軟鍵盤的問題
              $("#canvas_box").on("touchstart mousemove touchend",function () {
                  // console.log("走簽名-mousemove事件");
                  $("input,textarea").blur();
              });
               // 重置按鈕,生成圖片之后,可重置畫板,并清空圖片
              $("#reset_btn").on("click",function (e) {
                  canvas_box.jSignature("reset");
                  signImgSrc="";
                  e.preventDefault();
              });
              //提交簽名
              $("#submit_btn").on("click",function (e) {
              	// 獲取簽名長度
              	let signLen=canvas_box.jSignature("getData","native").length; 
            		//簽名判斷,長度為0,提示客戶簽名
              	if(signLen==0){	
              		alert("請輸入簽名");
              	}else{
              		//當有商戶簽字時,賦值簽字的base64碼
              		 let datapair=canvas_box.jSignature("getData","image");    // 獲取簽名的“base64”數據
                        console.log("datapair",datapair);
                      // 拼接完整的base64轉碼,根絕接口說明,傳遞。
                      signImgSrc='data:' + datapair[0] + "," + datapair[1];
                       console.log('確認后的base64路徑=',signImgSrc);
              	}
              })
          </script>
          </html>
          yy

          源碼地址:https://github.com/Skingsking/signature

          在中國互聯網行業崛起的大背景下,大家普遍對互聯網行業發展持樂觀態度。據今年第二季度招聘信息顯示,目前web前端工程師日均崗位缺口已經超過50000,隨著互聯網+的深入發展,html5作為前端展示技術,市場人才需求量將呈直線上漲。一個好的Web前端工程師在知識體系上既要有廣度,又要有深度,所以很多大公司即使出高薪也很難招聘到理想的前端開發工程師。那么如何系統的學習企業實用的web前端技術呢

          第一階段 :html+div+css+ps切圖+ftp網站上傳(網站上線)阿里圖標+html5標簽+css3動畫+手機網站開發+swiper.js+iscroll.js

          前端開發:制作網頁 ,HTML是內容,CSS是格式,JavaScript是動作

          HTML即超文本標記語言,是 WWW 的描述語言,由 Tim Berners-lee提出。設計 HTML 語言的目的是為了能把存放在一臺電腦中的文本或圖形與另一臺電腦中的文本或圖形方便地聯系在一起,形成有機的整體。

          CSS層疊樣式表是一種用來表現HTML或XML等文件樣式的計算機語言。CSS不僅可以靜態地修飾網頁,還可以配合各種腳本語言動態地對網頁各元素進行格式化。CSS 能夠對網頁中元素位置的排版進行像素級精確控制,支持幾乎所有的字體字號樣式,擁有對網頁對象和模型樣式編輯的能力。

          第二個階段:JavaScript+jQuery+Ajax+正則表達式+面向對象+js插件+代碼性能優化+github+sea.js+require.js+gulp

          JavaScript一種直譯式腳本語言,是一種動態類型、弱類型、基于原型的語言,內置支持類型。它的解釋器被稱為JavaScript引擎,為瀏覽器的一部分,廣泛用于客戶端的腳本語言,最早是在HTML網頁上使用,用來給HTML網頁增加動態功能。

          jQuery是一個快速、簡潔的JavaScript框架,是繼Prototype之后又一個優秀的JavaScript代碼庫它封裝JavaScript常用的功能代碼,提供一種簡便的JavaScript設計模式,優化HTML文檔操作、事件處理、動畫設計和Ajax交互。

          AJAX 是一種用于創建快速動態網頁的技術。通過在后臺與服務器進行少量數據交換,AJAX 可以使網頁實現異步更新。這意味著可以在不重新加載整個網頁的情況下,對網頁的某部分進行更新。

          第三個階段:2D+3D應用+移動觸屏事件touch+Canvas+Svg+多媒體技術+地理信息+本地存儲+H5拖拽api+跨域操作+多線程+highcharts圖表+bootstrap

          移動端觸屏事件touch滑動的效果其實就是圖片輪播,在PC的頁面上很好實現,綁定click和mouseover等事件來完成。但是在移動設備上,要實現這種輪播的效果,就需要用到核心的touch事件。處理touch事件能跟蹤到屏幕滑動的每根手指。

          Canvas是HTML5新增的組件,它就像一塊幕布,可以用JavaScript在上面繪制各種圖表、動畫等。沒有Canvas的年代,繪圖只能借助Flash插件實現,頁面不得不用JavaScript和Flash進行交互。有了Canvas,我們就再也不需要Flash了,直接使用JavaScript完成繪制。

          以上這些是全部的知識體系。如果你想成為一名合格的程序猿,你除了知道這些知識之外,我覺得還需要以下幾點:

          • 要了解敏捷軟件開發流程和項目管理知識這也屬于一種知識吧。
          • 要學會在網上和別人交流,交流能讓自己看到自己的不足。
          • 要學會自我反省和自我學習,隨時反省隨時進步。

          動驗證碼的識別介紹

          本節目標:

          用程序識別極驗滑動驗證碼的驗證,包括分析識別思路、識別缺口位置、生成滑塊拖動路徑、模擬實現滑塊拼合通過驗證等步驟。

          準備工作:

          本次案例我們使用Python庫是Selenium,瀏覽器為Chrome。請確保已安裝Selenium庫和ChromeDriver瀏覽器驅動。

          了解極驗滑動驗證碼:

          極驗滑動驗證碼官網為:http://www.geetest.com/

          驗證方式為拖動滑塊拼合圖像,若圖像完全拼合,則驗證成功,否則需要重新驗證,如圖所示:

          接下來我們鏈接地址:https://account.geetest.com/login,打開極驗的管理后臺登錄頁面,完成自動化登錄操作。

          實現步驟:

          ① 初始化

          初始化鏈接地址、創建模擬瀏覽器對象、設置登錄賬戶和密碼等信息。

          EMAIL='登錄賬戶'
          PASSWORD='登錄密碼'
          ?
          class CrackGeetest():
           def __init__(self):
           self.url='https://account.geetest.com/login'
           self.browser=webdriver.Chrome()
           #設置顯示等待時間
           self.wait=WebDriverWait(self.browser, 20)
           self.email=EMAIL
           self.password=PASSWORD
          ?
           def crack():
           pass
          ?
          # 程序主入口
          if __name__=='__main__':
           crack=CrackGeetest()
           crack.crack()
          

          ② 模擬登錄填寫,點開滑塊驗證

          • 在實例化CrackGeetest對象后調用crack()方法開始模擬登錄驗證...
          • 調用open()方法,打開登錄界面,獲取賬戶和密碼輸入框節點,完成賬戶和密碼的輸入。
          • 調用get_geetest_button()方法獲取滑動驗證按鈕,并點擊。
          class CrackGeetest():
           #...
          ?
           def get_geetest_button(self):
           ''' 獲取初始驗證按鈕,return:按鈕對象 '''
           button=self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_radar_tip')))
           return button
          ?
           def open(self):
           ''' 打開網頁輸入用戶名密碼, return: None '''
           self.browser.get(self.url)
           email=self.wait.until(EC.presence_of_element_located((By.ID, 'email')))
           password=self.wait.until(EC.presence_of_element_located((By.ID, 'password')))
           email.send_keys(self.email)
           password.send_keys(self.password)
          ?
           def crack(self):
           # 輸入用戶名密碼
           self.open()
           # 點擊驗證按鈕
           button=self.get_geetest_button()
           button.click()
           #...
           #...
          

          ③ 獲取并儲存有無缺口的兩張圖片

          • 首先獲取無缺口的驗證圖片,并保存到本地
          • 獲取滑塊對象,并執行點擊,讓瀏覽器中顯示有缺口圖片
          • 獲取有缺口的驗證圖片,并保存到本地
           def get_position(self):
           ''' 獲取驗證碼位置, return: 驗證碼位置(元組) '''
           img=self.wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_canvas_img')))
           time.sleep(2)
           location=img.location
           size=img.size
           top,bottom,left,right=location['y'],location['y']+size['height'],location['x'],location['x']+size['width']
           return (top, bottom, left, right)
          ?
           def get_screenshot(self):
           ''' 獲取網頁截圖, return: 截圖對象 '''
           #瀏覽器截屏
           screenshot=self.browser.get_screenshot_as_png()
           screenshot=Image.open(BytesIO(screenshot))
           return screenshot
          ?
           def get_geetest_image(self, name='captcha.png'):
           ''' 獲取驗證碼圖片, return: 圖片對象 '''
           top, bottom, left, right=self.get_position()
           print('驗證碼位置', top, bottom, left, right)
           screenshot=self.get_screenshot()
           #從網頁截屏圖片中裁剪處理驗證圖片
           captcha=screenshot.crop((left, top, right, bottom))
           captcha.save(name)
           return captcha
          ?
           def get_slider(self):
           ''' 獲取滑塊, return: 滑塊對象 '''
           slider=self.wait.until(EC.element_to_be_clickable((By.CLASS_NAME, 'geetest_slider_button')))
           return slider
          ?
           def crack(self):
           #...
          ?
           # 獲取驗證碼圖片
           image1=self.get_geetest_image('captcha1.png')
           # 點按呼出缺口
           slider=self.get_slider()
           slider.click()
           # 獲取帶缺口的驗證碼圖片
           image2=self.get_geetest_image('captcha2.png')
          ?
           #...
          

          ④ 獲取缺口位置

          • 對比兩張圖片的所有RBG像素點,得到不一樣像素點的x值,即要移動的距離
          BORDER=6
          INIT_LEFT=60
          ?
          class CrackGeetest(): 
           def get_gap(self, image1, image2):
           ''' 獲取缺口偏移量, 參數:image1不帶缺口圖片、image2帶缺口圖片。返回偏移量 '''
           left=65
           for i in range(left, image1.size[0]):
           for j in range(image1.size[1]):
           if not self.is_pixel_equal(image1, image2, i, j):
           left=i
           return left
           return left
          ?
           def is_pixel_equal(self, image1, image2, x, y):
           '''
           判斷兩個像素是否相同
           :param image1: 圖片1
           :param image2: 圖片2
           :param x: 位置x
           :param y: 位置y
           :return: 像素是否相同
           '''
           # 取兩個圖片的像素點(R、G、B)
           pixel1=image1.load()[x, y]
           pixel2=image2.load()[x, y]
           threshold=60
           if abs(pixel1[0]-pixel2[0])<threshold and abs(pixel1[1]-pixel2[1])<threshold and abs(pixel1[2]-pixel2[2])<threshold:
           return True
           else:
           return False
          ?
           def crack(self):
           #...
          ?
           # 獲取缺口位置
           gap=self.get_gap(image1, image2)
           print('缺口位置', gap)
           # 減去缺口位移
           gap -=BORDER
          

          ⑤ 獲取移動軌跡

          模擬人的行為習慣(先勻加速拖動后勻減速拖動),把需要拖動的總距離分成一段一段小的軌跡

           def get_track(self, distance):
           '''
           根據偏移量獲取移動軌跡
           :param distance: 偏移量
           :return: 移動軌跡
           '''
           # 移動軌跡
           track=[]
           # 當前位移
           current=0
           # 減速閾值
           mid=distance * 4 / 5
           # 計算間隔
           t=0.2
           # 初速度
           v=0
          ?
           while current < distance:
           if current < mid:
           # 加速度為正2
           a=2
           else:
           # 加速度為負3
           a=-3
           # 初速度v0
           v0=v
           # 當前速度v=v0 + at
           v=v0 + a * t
           # 移動距離x=v0t + 1/2 * a * t^2
           move=v0 * t + 1 / 2 * a * t * t
           # 當前位移
           current +=move
           # 加入軌跡
           track.append(round(move))
           return track
          ?
           def crack(self):
           #...
          ?
           # 獲取移動軌跡
           track=self.get_track(gap)
           print('滑動軌跡', track)
          

          ⑥ 按照軌跡拖動,完全驗證

           def move_to_gap(self, slider, track):
           '''
           拖動滑塊到缺口處
           :param slider: 滑塊
           :param track: 軌跡
           :return:
           '''
           ActionChains(self.browser).click_and_hold(slider).perform()
           for x in track:
           ActionChains(self.browser).move_by_offset(xoffset=x, yoffset=0).perform()
           time.sleep(0.5)
           ActionChains(self.browser).release().perform()
          ?
           def crack(self):
           #...
          ?
           # 拖動滑塊
           self.move_to_gap(slider, track)
          ?
           success=self.wait.until(
           EC.text_to_be_present_in_element((By.CLASS_NAME, 'geetest_success_radar_tip_content'), '驗證成功'))
           print(success)
          

          ⑦ 完成登錄


          主站蜘蛛池模板: 一区二区三区亚洲| 日韩av片无码一区二区三区不卡 | 无码国产精品一区二区免费vr| 午夜影视日本亚洲欧洲精品一区 | 色一情一乱一伦一区二区三欧美| 亚洲AV无码一区东京热久久| 国产无码一区二区在线| 一区二区免费国产在线观看| 日韩电影在线观看第一区| 视频一区在线播放| 一区二区三区在线观看视频| 国产激情无码一区二区三区| 精品理论片一区二区三区| 亚洲国产成人久久综合一区77| 国产激情一区二区三区成人91| 国产在线aaa片一区二区99| 无码少妇一区二区性色AV| 亚洲av乱码一区二区三区香蕉 | 国产福利一区二区三区在线视频| 精品一区精品二区制服| 国精产品一区一区三区有限公司| 精品成人一区二区三区免费视频| 精品国产AⅤ一区二区三区4区 | 亚洲老妈激情一区二区三区| 亚洲成av人片一区二区三区| 99精品国产一区二区三区| 国产一区二区在线观看app| 亚洲综合色自拍一区| 亚洲一区中文字幕| 精品免费国产一区二区三区 | 国产激情一区二区三区| 精品一区二区三区免费| 亚洲码一区二区三区| 国产伦精品一区二区三区免费迷| 久久国产精品一区| 亚洲一区在线免费观看| 国产三级一区二区三区| 熟女性饥渴一区二区三区| 午夜影院一区二区| 亚洲一区精品伊人久久伊人| 性色av一区二区三区夜夜嗨|