-
移动端手写签名 手写签名
2019-06-27 17:08:02移动端手写签名,通过canvas绘制, 最后生成base64图片。移动端手写签名,通过canvas绘制, 最后生成base64图片 -
手写签名
2016-09-06 15:44:56新建一个接口public interface DialogListener { public void refreshActivity(Object object); }主Activitypublic class HandwritingActivity extends Activity { /** Called when the activity is first crea新建一个接口
public interface DialogListener { public void refreshActivity(Object object); }
主Activity
public class HandwritingActivity extends Activity { /** Called when the activity is first created. */ private Bitmap mSignBitmap; private String signPath; private ImageView ivSign; private TextView tvSign; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); setTitle("欢迎使用手写签名"); ivSign = (ImageView) findViewById(R.id.iv_sign); tvSign = (TextView) findViewById(R.id.tv_sign); ivSign.setOnClickListener(signListener); tvSign.setOnClickListener(signListener); } private OnClickListener signListener = new OnClickListener() { @Override public void onClick(View v) { WritePadDialog writeTabletDialog = new WritePadDialog( HandwritingActivity.this,R.style.SignBoardDialog, new DialogListener() { public void refreshActivity(Object object) { mSignBitmap = (Bitmap) object; signPath = createFile(); //对图片进行压缩 /*BitmapFactory.Options options = new BitmapFactory.Options(); options.inSampleSize = 15; options.inTempStorage = new byte[5 * 1024]; Bitmap zoombm = BitmapFactory.decodeFile(signPath, options); */ Bitmap zoombm = getCompressBitmap(signPath); //ivSign.setImageBitmap(mSignBitmap); ivSign.setImageBitmap(zoombm); tvSign.setVisibility(View.GONE); } }); writeTabletDialog.show(); } }; /** * 创建手写签名文件 * * @return */ private String createFile() { ByteArrayOutputStream baos = null; String _path = null; try { String sign_dir = Environment.getExternalStorageDirectory() + File.separator; _path = sign_dir + System.currentTimeMillis() + ".png"; baos = new ByteArrayOutputStream(); mSignBitmap.compress(Bitmap.CompressFormat.PNG, 100, baos); byte[] photoBytes = baos.toByteArray(); if (photoBytes != null) { new FileOutputStream(new File(_path)).write(photoBytes); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (baos != null) baos.close(); } catch (IOException e) { e.printStackTrace(); } } return _path; } /** * 根据图片路径获取图片的压缩图 * @param filePath * @return */ public Bitmap getCompressBitmap(String filePath){ BitmapFactory.Options options = new BitmapFactory.Options(); options.inJustDecodeBounds = true; // 获取这个图片的宽和高 Bitmap bitmap = BitmapFactory.decodeFile(filePath, options); //此时返回bm为空 if(bitmap == null){ } //计算缩放比 int simpleSize = (int)(options.outHeight / (float)200); if (simpleSize <= 0) simpleSize = 1; options.inSampleSize = simpleSize; options.inJustDecodeBounds = false; //重新读入图片,注意这次要把options.inJustDecodeBounds 设为 false哦 bitmap=BitmapFactory.decodeFile(filePath,options); int w = bitmap.getWidth(); int h = bitmap.getHeight(); System.out.println(w+" "+h); return bitmap; } }
工具类
public class WritePadDialog extends Dialog { Context context; LayoutParams p; DialogListener dialogListener; public WritePadDialog(Context context) { super(context); this.context = context; } public WritePadDialog(Context context, int themeResId) { super(context, themeResId); this.context = context; } public WritePadDialog(Context context,DialogListener dialogListener) { super(context); this.context = context; this.dialogListener = dialogListener; } public WritePadDialog(Context context, int themeResId, DialogListener dialogListener) { super(context,themeResId); this.context = context; this.dialogListener = dialogListener; } static final int BACKGROUND_COLOR = Color.WHITE; static final int BRUSH_COLOR = Color.BLACK; PaintView mView; /** The index of the current color to use. */ int mColorIndex; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); requestWindowFeature(Window.FEATURE_PROGRESS); setContentView(R.layout.write_pad); WindowManager wm = (WindowManager) getContext() .getSystemService(Context.WINDOW_SERVICE); int width = wm.getDefaultDisplay().getWidth(); int height = wm.getDefaultDisplay().getHeight(); p = getWindow().getAttributes(); // 获取对话框当前的参数值 // p.height = (int)(height* 0.4); //高度设置为屏幕的0.4 // p.width = (int) (width * 0.6); //宽度设置为屏幕的0.6 int statusBarHeight = getStatusBarHeight(context); p.height = (int)(height - statusBarHeight + 0.5); //减去系统的宽高 p.width = (int)(width + 0.5); getWindow().setAttributes(p); // 设置生效,全屏填充 mView = new PaintView(context); FrameLayout frameLayout = (FrameLayout) findViewById(R.id.tablet_view); frameLayout.addView(mView); mView.requestFocus(); Button btnClear = (Button) findViewById(R.id.tablet_clear); btnClear.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mView.clear(); } }); Button btnOk = (Button) findViewById(R.id.tablet_ok); btnOk.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { try { dialogListener.refreshActivity(mView.getCachebBitmap()); WritePadDialog.this.dismiss(); } catch (Exception e) { e.printStackTrace(); } } }); Button btnCancel = (Button) findViewById(R.id.tablet_cancel); btnCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { cancel(); } }); } /** * 获取通知栏的高度 * @param context * @return */ public int getStatusBarHeight(Context context){ int result = 0; int resourceId = context.getResources().getIdentifier("status_bar_height", "dimen", "android"); if (resourceId > 0) { result = context.getResources().getDimensionPixelSize(resourceId); } return result; } /** * This view implements the drawing canvas. * * It handles all of the input events and drawing functions. */ class PaintView extends View { private Paint paint; private Canvas cacheCanvas; private Bitmap cachebBitmap; private Path path; public Bitmap getCachebBitmap() { return cachebBitmap; } public PaintView(Context context) { super(context); init(); } private void init() { paint = new Paint(); paint.setAntiAlias(true); paint.setStrokeWidth(10); paint.setStyle(Paint.Style.STROKE); paint.setColor(Color.BLACK); path = new Path(); cachebBitmap = Bitmap.createBitmap(p.width, (int) (p.height * 0.8), Config.ARGB_8888); cacheCanvas = new Canvas(cachebBitmap); cacheCanvas.drawColor(Color.WHITE); //设置背景为白色,不然点击缩略图查看的时候是全黑色 //cacheCanvas.drawColor(R.color.transparent); } public void clear() { if (cacheCanvas != null) { paint.setColor(BACKGROUND_COLOR); cacheCanvas.drawPaint(paint); paint.setColor(Color.BLACK); cacheCanvas.drawColor(Color.WHITE); invalidate(); } } @Override protected void onDraw(Canvas canvas) { // canvas.drawColor(BRUSH_COLOR); canvas.drawBitmap(cachebBitmap, 0, 0, null); canvas.drawPath(path, paint); } @Override protected void onSizeChanged(int w, int h, int oldw, int oldh) { int curW = cachebBitmap != null ? cachebBitmap.getWidth() : 0; int curH = cachebBitmap != null ? cachebBitmap.getHeight() : 0; if (curW >= w && curH >= h) { return; } if (curW < w) curW = w; if (curH < h) curH = h; Bitmap newBitmap = Bitmap.createBitmap(curW, curH, Bitmap.Config.ARGB_8888); Canvas newCanvas = new Canvas(); newCanvas.setBitmap(newBitmap); if (cachebBitmap != null) { newCanvas.drawBitmap(cachebBitmap, 0, 0, null); } cachebBitmap = newBitmap; cacheCanvas = newCanvas; } private float cur_x, cur_y; @Override public boolean onTouchEvent(MotionEvent event) { float x = event.getX(); float y = event.getY(); switch (event.getAction()) { case MotionEvent.ACTION_DOWN: { cur_x = x; cur_y = y; path.moveTo(cur_x, cur_y); break; } case MotionEvent.ACTION_MOVE: { path.quadTo(cur_x, cur_y, x, y); cur_x = x; cur_y = y; break; } case MotionEvent.ACTION_UP: { cacheCanvas.drawPath(path, paint); path.reset(); break; } } invalidate(); return true; } } }
main.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:background="@drawable/all_bg" android:orientation="vertical" > <ImageView android:id="@+id/iv_sign" android:layout_marginTop="50dp" android:layout_width="100dp" android:layout_height="100dp" /> <TextView android:id="@+id/tv_sign" android:layout_marginTop="50dp" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="点此签名" /> </LinearLayout>
write_pad.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF" android:orientation="vertical" > <FrameLayout android:id="@+id/tablet_view" android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" > </FrameLayout> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" > <Button android:id="@+id/tablet_ok" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="确定" /> <Button android:id="@+id/tablet_clear" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="清除" /> <Button android:id="@+id/tablet_cancel" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_weight="1" android:text="取消" /> </LinearLayout> </LinearLayout>
亲测可用,所以不放资源包
-
安卓 手写签名 电子签名
2018-11-03 10:56:48安卓手写签名,电子签名。安卓手写签名可以显示手写签名动画 -
手写签名Demo
2015-09-18 10:30:32Android手写签名实例 Android手写签名Demo Android手写更为平滑的签名效果实现 手写签名 手写 签名,android -
Android手写签名
2018-06-05 15:50:40手写签名的一个小demo,可以实现手写签名,保存到相册中。 -
html手写签名
2017-06-20 17:01:55html手写签名 -
一个基于canvas开发,封装于Vue组件的通用手写签名板(电子签名板),支持pc端和移动端
2020-05-08 09:35:40sign-canvas 一个基于canvas开发,封装于Vue组件的通用手写签名板(电子签名板),支持pc端和移动端; 同时支持重新签名,覆盖签名,下载,保存等 github地址:https://github.com/mose-x/vue-sign-canvas.git ...sign-canvas 一个基于canvas开发,封装于Vue组件的通用手写签名板(电子签名板),支持pc端和移动端;
同时支持重新签名,覆盖签名,下载,保存等 -
WPF手写签名
2018-12-04 13:45:28WPF,在签名区范围内进行手写签名,并将签名保存为图片。 -
android手写签名
2017-09-18 11:55:53android手写签名demo,实现了android手写签名的功能,eclipse开发工具直接导入即可,里面的部分代码参考了网上其他资源的 -
SignView手写签名
2018-06-05 14:48:18手写签名的自定义view及使用,适合初学自定义view者下载学习 -
PDF手写签名源码
2020-09-28 21:26:30为您提供PDF手写签名源码下载, PDF手写签名源码使用了第三方PDF阅读器源码mupdf类库。打开以后先对手机文件目录的显示及操作选择PDF文件后会读取并显示pdf内容点击menu键可以显示一些选项、如签名、预览、撤销签名... -
手写签名插件
2019-02-20 10:45:42手写签名插件,可以满足你在PC端上上面的一切签字行为。可以完美的吧你所画,所签,所想给展现出来! -
在钉钉上怎么手写_数码知识:钉钉手写签名如何设置开启手写签名教程
2020-12-30 08:40:58如今使用IT数码设备的小伙伴们是越来越多了,那么IT数码设备当中是有很多小技巧的,这些技巧很多小伙伴一般都是不知道如何来实用的,就好比最近就有很多小伙伴们想要知道钉钉手写签名如何设置开启手写签名教程,那么...如今使用IT数码设备的小伙伴们是越来越多了,那么IT数码设备当中是有很多小技巧的,这些技巧很多小伙伴一般都是不知道如何来实用的,就好比最近就有很多小伙伴们想要知道钉钉手写签名如何设置开启手写签名教程,那么既然现在大家对于钉钉手写签名如何设置开启手写签名教程都感兴趣,小编就来给大家分享下关于钉钉手写签名如何设置开启手写签名教程的一些信息吧。
1、手机端:【工作台】-【智能填表】-【新建】-【添加】-【手写签名】
2、电脑端:左侧任务栏点击【工作】-【智能填表】-【创建】或者选择现有的模板-左侧选择手写签名
【温馨提示】:
1、针对之前已创建好的表单,可以通过手机端/电脑端-【工作台】-【智能填表】-【统计】-找到对应的表单-【…】-【修改表单】即可添加【手写签名】功能;
2、表单创建者还可以将手写签名设置是否必填、标题、签名方式(若选择【可使用上次签名】,选择后就不需要每次都重新签名),
注:本文适用于钉钉V5.1.31版本。
-
Android实现手写签名
2021-01-06 01:44:25本文实例为大家分享了Android手写签名的实现方法,产品要求用户可以在app上签协议。。所以得弄个手写签名版,参考了一些资料自己写了个PaintView去继承View,实现签名功能。 package com.****.*****.widget; import... -
安卓手写签名模块源码
2020-09-28 21:26:34为您提供安卓手写签名模块源码下载, 安卓手写签名模块源码是一款关于安卓手写签名的解决方案源码,现在的领导出差如果需要签名的话在手机上就可以直接完成了。会在签名完成以后自动形成缩略图。 效果图... -
vue手写签名,canvas手写签名,canvas签名图片旋转
2020-12-23 11:49:211.手写签名在“手机竖屏”的情况下会展示横屏的画板样式, 2.如果手机横屏的话,系统会进行适配,所以这时候展示竖屏的样式(手机翻转的时候重新生成canvas) 3.因为"手机竖屏“展示横屏的样式,所以提交的时候要...安装: npm install vue-esign --save
在main.js 中引入
import vueEsign from 'vue-esign'
Vue.use(vueEsign)
1.手写签名在“手机竖屏”的情况下会展示横屏的画板样式,
2.如果手机横屏的话,系统会进行适配,所以这时候展示竖屏的样式(手机翻转的时候重新生成canvas)
3.因为"手机竖屏“展示横屏的样式,所以提交的时候要把签名的图片旋转一下
4.设备的x,y轴坐标与画布的坐标不准确,还有页面布局的因素,所以获取x,y轴坐标后要进行调试
<template>
<div>
<div v-if="show&&(phone && windowWidth < windowHeight)" class="signatureBox signatureBox1">
<div class="canvasBox" ref="canvasHW">
<div v-if="show" class="btnBox" :style="status == '0' ? {top: '45%'} : ''">
<button @click="overwrite" style="background:#BC6FFF;border-radius:40px;width:120px;height:40px">重签</button>
<button @click="surewrite" style="background:#71B9FC;border-radius:40px;width:120px;height:40px">提交</button>
</div>
<div v-if="show" class="closeBox">
<span>温馨提示:请签写公司法人代表的英文/拼音名字:</span><span style="color:red">{{realname}}</span>
</div>
<canvas
class="canvas_box"
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
v-if="show"
ref="canvasF"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="mouseUp"
></canvas>
<div class="tit">签名输入框:</div>
</div>
</div>
<div v-if="show&&(!phone || windowWidth > windowHeight)" class="signatureBox">
<div class="canvasBox" ref="canvasHW">
<div class="tit">签名输入框:</div>
<canvas
@touchstart="touchStart"
@touchmove="touchMove"
@touchend="touchEnd"
v-if="show"
ref="canvasF"
@mousedown="mouseDown"
@mousemove="mouseMove"
@mouseup="mouseUp"
></canvas>
<div v-if="show" class="closeBox">
<span>温馨提示:请签写公司法人代表的英文/拼音名字:</span><span style="color:red">{{realname}}</span>
</div>
<div v-if="show" class="btnBox" style="width:300px">
<button @click="overwrite" style="background:#BC6FFF;border-radius:40px;width:120px;height:40px">重签</button>
<button @click="surewrite" style="background:#71B9FC;border-radius:40px;width:120px;height:40px">提交</button>
</div>
</div>
</div>
</div>
</template>
<script>
import { sendSignImg,austriaSendSignImg } from "@/api/sign";
import { debounce } from "@/util/util.js";
// import axios from "axios";
export default {
name: "signature",
data() {
return {
points: [],
canvasTxt: null,
startX: 0,
startY: 0,
moveY: 0,
moveX: 0,
endY: 0,
endX: 0,
w: null,
h: null,
isDown: false,
color: "#000",
linewidth: 3,
imgBase64: "",
isDraw: false, //签名标记
show: true,
realname: '',
windowHeight: undefined,
windowWidth:undefined,
phone:true,
status: undefined
};
},
created() {
document.title = '手写签名-欧税通'
this.windowWidth = document.documentElement.clientWidth || document.body.clientWidth
this.windowHeight = document.documentElement.clientHeight || document.body.clientHeight
},
mounted() {
let phone = navigator.userAgent;//设备机型的相关信息
phone = phone.substring(phone.indexOf('(')+1,phone.indexOf(';'));//处理信息,输出phone
console.log(phone.indexOf('Windows') == -1,phone.indexOf('Macintosh') == -1,phone.indexOf('iPad') == -1,phone.indexOf('iPad'),'--------------设备信息--------------------')
if ((phone.indexOf('Windows') == -1 && phone.indexOf('Macintosh') == -1 && phone.indexOf('iPad') == -1)) {
this.phone = true
} else {
this.equipment = false
this.phone = false
}
if (!this.$route.query.taxIdKey && !this.$route.query.declareIdKey) {
this.show = false;
return this.$toast({
message: "二维码已失效,请重新扫码",
duration: 3000,
position: top
})
}
if (this.$route.query.realname) {
this.realname = this.$route.query.realname
}
let canvas = this.$refs.canvasF;
if ((this.phone && this.windowWidth < this.windowHeight)) {
canvas.height = this.windowHeight - 2;
canvas.width = this.windowWidth - 150;
} else {
canvas.height = this.windowHeight * 0.6;
canvas.width = this.windowWidth - 10;
}
this.canvasTxt = canvas.getContext("2d");
this.canvasTxt.strokeStyle = this.color;
this.canvasTxt.lineWidth = this.linewidth;
const that = this
window.onresize = () => {
that.$toast({message: '系统已为您适配,请关闭旋转模式'})
that.overwrite()
that.windowWidth = document.documentElement.clientWidth || document.body.clientWidth
that.windowHeight = document.documentElement.clientHeight || document.body.clientHeight
if ((that.phone && that.windowWidth < that.windowHeight)) {
that.status = '0'
canvas.height = that.windowHeight-2;
canvas.width = that.windowWidth - 150;
} else {
that.status = '1'
canvas.height = that.windowHeight * 0.6;
canvas.width = that.windowWidth - 10;
}
}
},
components: {},
methods: {
//电脑设备事件
mouseDown(ev) {
this.isDraw = true; //签名标记
ev = ev || event;
ev.preventDefault();
let obj = {
x: ev.offsetX,
y: ev.offsetY
};
this.startX = obj.x;
this.startY = obj.y;
this.canvasTxt.beginPath();
this.points.push(obj);
this.isDown = true;
},
//移动设备事件
touchStart(ev) {
ev = ev || event;
ev.preventDefault();
if (ev.touches.length == 1) {
this.isDraw = true; //签名标记
let obj = {}; //y的计算值中:document.body.offsetHeight*0.5代表的是除了整个画板signatureBox剩余的高,this.$refs.canvasHW.offsetHeight*0.1是画板中标题的高
if (this.windowWidth < this.windowHeight && this.phone) {
obj = {
x: ev.targetTouches[0].clientX-120,
y: ev.targetTouches[0].clientY
};
} else {
obj = {
x: ev.targetTouches[0].clientX,
y: ev.targetTouches[0].clientY - 55
};
}
this.startX = obj.x;
this.startY = obj.y;
this.canvasTxt.beginPath();
this.points.push(obj);
}
},
//电脑设备事件
mouseMove(ev) {
ev = ev || event;
ev.preventDefault();
if (this.isDown) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
};
this.moveY = obj.y;
this.moveX = obj.x;
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.startY = obj.y;
this.startX = obj.x;
this.points.push(obj);
}
},
//移动设备事件
touchMove(ev) {
ev = ev || event;
ev.preventDefault();
let obj = {}
if (this.windowWidth < this.windowHeight && this.phone) {
obj = {
x: ev.targetTouches[0].clientX-120,
y: ev.targetTouches[0].clientY
};
} else {
obj = {
x: ev.targetTouches[0].clientX,
y: ev.targetTouches[0].clientY - 55
};
}
this.moveY = obj.y;
this.moveX = obj.x;
this.canvasTxt.moveTo(this.startX, this.startY);
this.canvasTxt.lineTo(obj.x, obj.y);
this.canvasTxt.stroke();
this.startY = obj.y;
this.startX = obj.x;
this.points.push(obj);
},
//电脑设备事件
mouseUp(ev) {
ev = ev || event;
ev.preventDefault();
if (1) {
let obj = {
x: ev.offsetX,
y: ev.offsetY
};
this.canvasTxt.closePath();
this.points.push(obj);
this.points.push({ x: -1, y: -1 });
this.isDown = false;
}
},
//移动设备事件
touchEnd(ev) {
ev = ev || event;
ev.preventDefault();
if (ev.touches.length == 1) {
let obj = {};
if (this.windowWidth < this.windowHeight && this.phone) {
obj = {
x: ev.targetTouches[0].clientX-120,
y: ev.targetTouches[0].clientY
};
} else {
obj = {
x: ev.targetTouches[0].clientX,
y: ev.targetTouches[0].clientY - 55
};
}
this.canvasTxt.closePath();
this.points.push(obj);
this.points.push({ x: -1, y: -1 });
}
},
//重写
overwrite() {
this.canvasTxt.clearRect(
0,
0,
this.$refs.canvasF.width,
this.$refs.canvasF.height
);
this.points = [];
this.isDraw = false; //签名标记
},
//确认签名
surewrite:debounce(function() {
if (this.isDraw) {
let toast1 = this.$toast.loading({
message: '上传中...',
forbidClick: true,
duration: 0
});
let imgBase64 = undefined
let api = null
let params = {}
if (this.$route.query.declareIdKey) {
api = austriaSendSignImg
params.declareIdKey = this.$route.query.declareIdKey
} else if (this.$route.query.taxIdKey) {
api = sendSignImg
params.taxIdKey = this.$route.query.taxIdKey
}
if (this.phone && this.windowWidth < this.windowHeight) {
this.rotateBase64(this.$refs.canvasF.toDataURL()).then((img) => {
imgBase64 = img
params.file = this.dataURLtoFile(imgBase64, "name")
api(params).then(res => {
if (res.code == 500) {
this.$toast({
message: res.msg,
duration: 3000,
position: top
})
}
if (res.code == 0) {
this.$toast.success('上传成功,请关闭当前页面')
this.show =false
}
setTimeout(() => {toast1.clear()},3000)
}).catch(err => {
console.log(err,'-----------err------------')
setTimeout(() => {toast1.clear()},3000)
this.$toast({message: '网络不稳定,请稍后重试'})
})
});
} else {
imgBase64 = this.$refs.canvasF.toDataURL()
params.file = this.dataURLtoFile(imgBase64, "name")
api(params).then(res => {
if (res.code == 500) {
this.$toast({
message: res.msg,
duration: 3000,
position: top
})
}
if (res.code == 0) {
this.$toast.success('上传成功,请关闭当前页面')
this.show =false
}
setTimeout(() => {toast1.clear()},3000)
}).catch(err => {
console.log(err,'-----------err------------')
setTimeout(() => {toast1.clear()},3000)
this.$toast({message: '网络不稳定,请稍后重试'})
})
}
} else {
this.$toast({
message: "请签字之后再提交",
duration: 3000,
position: top
})
}
},500),
rotateBase64(data){ //传入需要旋转的base64图片
return new Promise((resolve, reject) => {
const imgView = new Image();
imgView.src = data;
const canvas = document.createElement('canvas');
const context = canvas.getContext('2d');
const cutCoor = {sx: 0, sy: 0, ex: 0, ey: 0}; // 裁剪坐标
imgView.onload = () => {
const imgW = imgView.width;
const imgH = imgView.height;
const size = imgH;
canvas.width = size * 2;
canvas.height = size * 2;
cutCoor.sx = size;
cutCoor.sy = size - imgW;
cutCoor.ex = size + imgH;
cutCoor.ey = size + imgW;
context.translate(size, size);
context.rotate(Math.PI/2*3);
context.drawImage(imgView, 0, 0);
const imgData = context.getImageData(cutCoor.sx, cutCoor.sy, cutCoor.ex, cutCoor.ey);
canvas.width = imgH;
canvas.height = imgW;
context.putImageData(imgData, 0, 0);
resolve(canvas.toDataURL('image/png'));
};
});
},
dataURLtoFile(dataurl, filename) {
// 调用如下
let bold = this.dataURLtoBlob(dataurl);
let file = this.blobToFile(bold, "sign");
// 上传file就可以了
return file;
},
//转成blob
dataURLtoBlob(toDataURL) {
var arr = toDataURL.split(","),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
var blob = null;
// 解决低版本浏览器没有new Blob()问题
try {
blob = new Blob([u8arr], { type: mime });
} catch (e) {
var BlobBuilder = (window.BlobBuilder =
window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder);
if (e.name === "TypeError" && BlobBuilder) {
var builder = new BlobBuilder();
builder.append(u8arr);
blob = builder.getBlob(mime);
}
}
return blob;
},
//转成file
blobToFile(Blob, fileName) {
Blob.lastModifiedDate = new Date();
Blob.name = fileName;
return Blob;
}
}
};
</script>
<style scoped>
.signatureBox {
position: fixed;
top: 0px;
left: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
overflow: hidden;
z-index: 100;
}
.signatureBox1{
height: 100%;
}
.signatureBox1 .canvasBox{
height: 100%;
}
.signatureBox1 .tit{
position: absolute;
right: -30px;
top: 35px;
transform:rotate(90deg);
-ms-transform:rotate(90deg); /* IE 9 */
-moz-transform:rotate(90deg); /* Firefox */
-webkit-transform:rotate(90deg); /* Safari 和 Chrome */
-o-transform:rotate(90deg);
}
.signatureBox1 .closeBox{
position: absolute;
right: 110px;
top: 190px;
width: 100%;
height: 20px;
transform:rotate(90deg);
-ms-transform:rotate(90deg); /* IE 9 */
-moz-transform:rotate(90deg); /* Firefox */
-webkit-transform:rotate(90deg); /* Safari 和 Chrome */
-o-transform:rotate(90deg);
}
.canvas_box {
position: absolute;
right: 50px;
top: 0;
}
.signatureBox1 .btnBox{
height: 1rem;
margin: auto;
position: absolute;
top: 50%;
margin-top: -0.5rem;
right: 50%;
transform:rotate(90deg);
-ms-transform:rotate(90deg); /* IE 9 */
-moz-transform:rotate(90deg); /* Firefox */
-webkit-transform:rotate(90deg); /* Safari 和 Chrome */
-o-transform:rotate(90deg);
}
.tit{
text-align: left;
font-size: 20px;
height: 40px;
line-height: 40px;
margin: 0 10px;
}
.canvasBox {
padding: 0px 5px;
height: 90%;
}
canvas {
border: 1px dashed gray;
}
.btnBox {
padding: 5px;
text-align: center;
line-height: 30px;
display: flex;
}
.signatureBox .btnBox{
padding: 5px;
text-align: center;
line-height: 30px;
display: flex;
margin: auto;
justify-content: space-between;
}
.btnBox button {
border: 1px solid dodgerblue;
background: dodgerblue;
color: #fff;
border-radius: 4px;
padding: 2px 30px;
margin: 0 15px;
font-size: 14px;
outline: none;
}
.closeBox {
text-align: center;
height: 10%;
}
.closeBox span {
font-size: 13px;
float: left;
}
.closeBox p {
font-size: 22px;
width: 30px;
height: 30px;
line-height: 30px;
border-radius: 30px;
border: none;
background: gray;
color: white;
float: right;
}
@media only screen and (min-width: 730px) {
/* .signatureBox {
position: fixed;
bottom: 0px;
width: 100%;
height: 50%;
background: darkgray;
box-sizing: border-box;
overflow: visible;
} */
}
</style>
-
web手写签名功能
2019-07-09 11:27:36实现web手写签名功能 打开就能用 鼠标手写触摸板手写 手机端也可以用 写完直接转image 很实用 -
移动端手写签名js
2018-05-07 17:30:14javascript移动端手写签名,通过canvas绘制,base64图片 -
手写签名js插件
2018-07-27 11:22:52该插件用于PC端或移动端的手写签名功能主要应用在电子合同平台。 -
微信小程序 手写签名_小程序手写签名(wepy)
2020-12-20 12:31:03对于手写签名组件组件晚上有很多种写法,我选择了一种进行了wepy的框架的改造。如果使用wepy框架做手写签名的话可以直接复制下面的代码。这里需要提醒的是:安卓手机和苹果手机有适配性的问题,苹果手机在签名的以后... -
uniapp手写_手写签名
2020-12-31 08:49:54前言:简单的手写签名参考 https://www.auiaa.com/fron/uni/2019-03-17/103.html 的例子,进行了修改主要代码@touchcancel='cancel' @longtap='tap' disable-scroll='true' @error='error'>重签完成签名var ... -
Android实现屏幕手写签名
2020-08-25 20:13:18主要为大家详细介绍了Android实现屏幕手写签名,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 -
canvasSignature是基于canvas实现手写签名电子签名功能
2019-08-11 07:40:40canvasSignature是基于html5 canvas及jquery实现手写签名(电子签名)功能的js组件
-
判断推理题
-
2021-01-23
-
讲稿_Robust Multi-Modality Multi-Object Tracking.docx
-
Excel高级图表技巧
-
自己动手写操作系统 ----总计
-
GJB150.22A-2009第22部分:积冰_冻雨试验.pdf
-
【2021】Python3+Selenium3自动化测试(不含框架)
-
查 找 算 法 的 实 现.docx
-
SubstancePainter插件开发-基础入门
-
【笔记】操作系统(十三)——I/O输入系统
-
免费下载 [discuz!插件] 全站链自动SEO推送 V1.0
-
WordPress某易云音乐插件,WordPress主题在线音乐歌单插件
-
2021上海益生菌展资讯-我国首次分离得到新乳杆菌 助推益生菌食品升级
-
实验一基本电路实验.circ
-
springboot整合quartz实现动态定时任务
-
JavaEE框架(Maven+SSM)全程实战开发教程(源码+讲义)
-
Dart入门宝典第二章——赋值运算符、控制语句、方法和闭包的相关介绍
-
微信支付2021系列之扫码支付一学就会java版
-
Centos7安装Oracle必备的rpm包
-
特殊矩阵、稀疏矩阵的表示实现与运算.docx