HTML5 Canvas 實現在線簽字功能(示例代碼)

前言
在現代互聯網應用中,有時我們需要讓用戶在網頁上進行簽字操作,比如確認文件、填寫電子表格或者簽署合同。利用 HTML5 的 canvas 畫布,我們可以輕松地實現這一功能,為用戶提供方便快捷的在線簽字體驗。
一、HTML5 Canvas 簡介
HTML5 的 canvas 元素是一種強大的圖形渲染工具,它允許開發(fā)者使用 JavaScript 在網頁上繪制各種圖形、動畫和交互式內容。通過 canvas,開發(fā)者可以創(chuàng)建豐富多彩的視覺效果,并實現復雜的用戶交互體驗。
HTML5 Canvas的關鍵特性:
圖形繪制能力:Canvas 元素提供了繪制路徑、矩形、圓形、直線、文本等基本圖形的功能,同時還支持圖像的繪制和變換操作,使得開發(fā)者能夠輕松地創(chuàng)建各種視覺效果。
動畫和交互:借助 JavaScript,開發(fā)者可以在 Canvas 上創(chuàng)建復雜的動畫效果,并添加交互式的操作。這使得 Canvas 成為開發(fā)游戲、數據可視化和其他需要動態(tài)效果的應用的理想選擇。
性能優(yōu)勢:由于 Canvas 是基于 GPU 加速的,因此它具有良好的性能表現,能夠處理大量的圖形元素和動畫效果,而不會對頁面的整體性能產生太大影響。
靈活性:Canvas 元素可以輕松地與其他 HTML 元素結合使用,使得開發(fā)者可以在頁面上創(chuàng)建復雜的混合媒體效果,同時還可以響應用戶的交互操作。
二、簽字功能的實現
效果演示
完整代碼
HTML代碼
<!DOCTYPE html> <html class="no-js"> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0,user-scalable=no,viewport-fit=cover"> <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" /> <meta http-equiv="expires" CONTENT="Wed, 26 Feb 1997 08:21:57 GMT"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Cache" content="no-cache"> <meta http-equiv="Expires" content="0"> <meta charset="utf-8"> <title>畫圖</title> <link rel="stylesheet" href="css/bootstrap.css"> <style> * { margin: 0; padding: 0; } html, body { width: 100%; height: 100%; text-align: center; } canvas { max-width: 100%; border: 2px dotted #ccc; } </style> </head> <body> <script src="./index.js"></script> <script> //初始化 var sign = new Draw( { // canvas:document.getElementById('canvas'), lineWidth: 10, // 線條寬度 width: 400, // canvas 寬 height: 400, //canvas 高 strokeStyle: '#333333' // 線條顏色 } ); window.onload = function () { // 點擊輸出圖片 document.querySelector( '.ouput' ).onclick = function () { var img = new Image(); img.style.width = '200px'; img.src = sign.ouput(); img.onload = function () { document.body.appendChild( img ); } document.querySelector( 'img' ) && document.querySelector( 'img' ).remove(); } // 點擊清除 document.querySelector( '.clear' ).onclick = function () { sign.clear(); } // 點擊撤銷 document.querySelector( '.undo' ).onclick = function () { if ( sign.state.undopath.length > 0 ) { sign.undo(); } else { console.log( '還沒有簽名' ); } } } </script> <div class="buttons"> <button type="button" class="btn btn-primary ouput">生成圖片</button> <button type="button" class="btn btn-light undo">撤銷</button> <button type="button" class="btn btn-light clear">清除畫布</button> </div> </body> </html>
js代碼
( function ( global, factory ) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define( factory ) : ( global = global || self, global.Draw = factory() ); }( this, ( function () { 'use strict'; var classCallCheck = function ( instance, Constructor ) { if ( !( instance instanceof Constructor ) ) { throw new TypeError( "Cannot call a class as a function" ); } }; var createClass = function () { function defineProperties ( target, props ) { for ( var i = 0; i < props.length; i++ ) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ( "value" in descriptor ) descriptor.writable = true; Object.defineProperty( target, descriptor.key, descriptor ); } } return function ( Constructor, protoProps, staticProps ) { if ( protoProps ) defineProperties( Constructor.prototype, protoProps ); if ( staticProps ) defineProperties( Constructor, staticProps ); return Constructor; }; }(); /** * * @description 手寫簽字版 */ var Draw = function () { function Draw () { var params = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {}; classCallCheck( this, Draw ); this.el = params.el || document.createElement( 'canvas' ); this.state = { undopath: [], index: -1, old: void 0, isStart: false, width: params.width || 400, height: params.height || 400, lineWidth: params.lineWidth || 1, isTouch: 'ontouchstart' in window, strokeStyle: params.strokeStyle || '#333333' }; var _state = this.state, width = _state.width, height = _state.height, lineWidth = _state.lineWidth; this.el.width = width * 2; this.el.height = height * 2; document.body.appendChild( this.el ); this.ctx = this.el.getContext( '2d' ); this.ctx.scale( 2, 2 ); this.ctx.lineWidth = lineWidth; this.ctx.lineJoin = 'round'; this.ctx.lineCap = 'round'; this.init(); } createClass( Draw, [{ key: 'onStart', value: function onStart () { ++this.state.index; this.state.isStart = true; } }, { key: 'onMove', value: function onMove ( e ) { e.preventDefault(); if ( !this.state.isStart ) return; var pos = this.pos( e ); var index = this.state.index; this.ctx.strokeStyle = this.state.strokeStyle; if ( this.state.old ) { this.ctx.beginPath(); this.ctx.moveTo( this.state.old.x, this.state.old.y ); this.ctx.lineTo( pos.x, pos.y ); this.ctx.stroke(); } this.state.old = pos; if ( this.state.undopath[index] ) { this.state.undopath[index].push( { x: this.state.old.x, y: this.state.old.y } ); } else { this.state.undopath[index] = [{ x: this.state.old.x, y: this.state.old.y, strokeStyle: this.ctx.strokeStyle, lineWidth: this.ctx.lineWidth }]; } } }, { key: 'onEnd', value: function onEnd () { this.state.old = void 0; this.state.isStart = false; } }, { key: 'pos', value: function pos ( e ) { var x = 0, y = 0; if ( e.touches ) { x = e.touches[0].pageX; y = e.touches[0].pageY; } else { x = e.offsetX / 2; y = e.offsetY / 2; } return { x: x, y: y }; } }, { key: 'ouput', value: function ouput () { // 輸出圖片 return this.el.toDataURL(); } }, { key: 'init', value: function init () { // 綁定事件 var isTouch = this.state.isTouch; this.el.addEventListener( isTouch ? 'touchstart' : 'mousedown', this.onStart.bind( this ), false ); this.el.addEventListener( isTouch ? 'touchmove' : 'mousemove', this.onMove.bind( this ), false ); this.el.addEventListener( isTouch ? 'touchend' : 'mouseup', this.onEnd.bind( this ), false ); this.el.addEventListener( isTouch ? 'touchcancel' : 'mouseout', this.onEnd.bind( this ), false ); } }, { key: 'destroyed', value: function destroyed () { if ( this.el ) { var isTouch = this.state.isTouch; this.el.removeEventListener( isTouch ? 'touchstart' : 'mousedown', this.onStart.bind( this ) ); this.el.removeEventListener( isTouch ? 'touchmove' : 'mousemove', this.onMove.bind( this ) ); this.el.removeEventListener( isTouch ? 'touchend' : 'mouseup', this.onEnd.bind( this ) ); this.el.removeEventListener( isTouch ? 'touchcancel' : 'mouseout', this.onEnd.bind( this ) ); } } }, { key: 'clear', value: function clear () { // 清除畫布 this.state.index = -1; this.state.undopath = []; this.ctx.clearRect( 0, 0, this.el.width, this.el.height ); } }, { key: 'undo', value: function undo () { // 撤銷 this.state.index >= 0 && --this.state.index; var undopath = this.state.undopath; this.state.undopath.pop(); this.ctx.clearRect( 0, 0, this.el.width, this.el.height ); if ( undopath ) { this.ctx.beginPath(); for ( var z = 0; z < undopath.length; ++z ) { this.ctx.moveTo( undopath[z][0].x, undopath[z][0].y ); this.ctx.lineWidth = undopath[z][0].lineWidth; this.ctx.strokeStyle = undopath[z][0].strokeStyle; for ( var i = 0; i < undopath[z].length; ++i ) { this.ctx.lineTo( undopath[z][i].x, undopath[z][i].y ); } } this.ctx.stroke(); this.ctx.closePath(); } else { this.state.undopath = []; } } }] ); return Draw; }(); return Draw; } ) ) );
到此這篇關于HTML5 Canvas 實現在線簽字功能的文章就介紹到這了,更多相關HTML5 Canvas在線簽字內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持腳本之家!
相關文章
- 這篇文章主要介紹了HTML5 Canvas 實現K線圖的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學2019-12-23
- 這篇文章主要介紹了HTML5模擬齒輪動畫的示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學2019-09-24
- 這篇文章主要介紹了Html5 Canvas 實現一個“刮刮樂”游戲,本文通過實例代碼給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-05
- 這篇文章主要介紹了html5 canvas繪制網絡字體的常用方法,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-26
- 這篇文章主要介紹了html5 canvas實現給圖片添加平鋪水印,代碼簡單易懂,非常不錯,具有一定的參考借鑒價值,需要的朋友可以參考下2019-08-20
- 這篇文章主要介紹了導出HTML5 Canvas圖片并上傳服務器功能,文中通過實例代碼給大家介紹了HTML5 Canvas轉化成圖片后上傳服務器,代碼簡單易懂非常不錯,具有一定的參考借鑒2019-08-16
基于Html5 canvas實現裁剪圖片和馬賽克功能及又拍云上傳圖片 功能
這篇文章主要介紹了基于Html5 canvas實現裁剪圖片和馬賽克功能及又拍云上傳圖片 功能,需要的朋友可以參考下2019-07-09