Files
UNION_NJUST/target/classes/static/assets/platform/js/signature.min.js
T
2026-09-23 09:38:39 +08:00

271 lines
9.4 KiB
JavaScript

"use strict";
(function (root, factory) {
if (typeof exports === "object" && typeof module !== "undefined") {
module.exports = factory()
} else if (typeof define === "function" && define.amd) {
define(factory)
} else {
root = root || self
root.Signature = factory()
}
})(typeof self !== "undefined" ? self : this, function () {
function isHexColor(color) {
return typeof color === "string" && /^#([0-9a-fA-F]{3}|[0-9a-fA-F]{6})$/.test(color)
}
function Signature(options) {
var self = this
var history = []
var drawing = false
var currentPoint = null
var activePointerId = null
var canvas
var context
self.obj = options && !Array.isArray(options) ? options : {}
self.option = {
el: self.obj.el ? self.obj.el : "body",
lineWidth: !isNaN(parseInt(self.obj.lineWidth, 10)) ? parseInt(self.obj.lineWidth, 10) : 5,
lineColor: isHexColor(self.obj.lineColor) ? self.obj.lineColor : "#000000",
overflow: typeof self.obj.overflow === "boolean" ? self.obj.overflow : true,
background: isHexColor(self.obj.background) ? self.obj.background : "#ffffff"
}
self.status = history
self.step = -1
self.firstStatus = ""
canvas = document.querySelector(self.option.el)
if (!canvas || canvas.tagName !== "CANVAS") {
throw new Error("Target element must be canvas")
}
context = canvas.getContext("2d")
canvas.style.backgroundColor = self.option.background
canvas.style.touchAction = "none"
function syncHistoryIndex() {
self.step = history.length - 1
}
function clearCanvas() {
context.clearRect(0, 0, canvas.width, canvas.height)
}
function drawImage(dataUrl) {
clearCanvas()
if (!dataUrl) {
return
}
var image = new Image()
image.onload = function () {
context.drawImage(image, 0, 0)
}
image.src = dataUrl
}
function saveSnapshot() {
var dataUrl = canvas.toDataURL("image/png")
if (history.length === 0 || history[history.length - 1] !== dataUrl) {
history.push(dataUrl)
syncHistoryIndex()
}
}
function getPoint(event) {
var source = event
var rect = canvas.getBoundingClientRect()
if (event.touches && event.touches.length > 0) {
source = event.touches[0]
} else if (event.changedTouches && event.changedTouches.length > 0) {
source = event.changedTouches[0]
}
return {
x: source.clientX - rect.left,
y: source.clientY - rect.top
}
}
function preventDefault(event) {
if (event && event.cancelable) {
event.preventDefault()
}
}
function startDraw(event) {
preventDefault(event)
drawing = true
currentPoint = getPoint(event)
}
function moveDraw(event) {
if (!drawing || !currentPoint) {
return
}
preventDefault(event)
var nextPoint = getPoint(event)
context.beginPath()
context.moveTo(currentPoint.x, currentPoint.y)
context.lineTo(nextPoint.x, nextPoint.y)
context.closePath()
context.stroke()
currentPoint = nextPoint
}
function endDraw(event) {
if (!drawing) {
return
}
preventDefault(event)
drawing = false
currentPoint = null
activePointerId = null
saveSnapshot()
}
// Prefer capability detection so Harmony / modern WebView devices do not rely on UA strings.
function bindEvents() {
if (window.PointerEvent) {
canvas.addEventListener("pointerdown", function (event) {
activePointerId = event.pointerId
if (canvas.setPointerCapture) {
canvas.setPointerCapture(event.pointerId)
}
startDraw(event)
}, { passive: false })
canvas.addEventListener("pointermove", function (event) {
if (activePointerId !== null && event.pointerId !== activePointerId) {
return
}
moveDraw(event)
}, { passive: false })
canvas.addEventListener("pointerup", endDraw, { passive: false })
canvas.addEventListener("pointercancel", endDraw, { passive: false })
return
}
if ("ontouchstart" in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0) {
canvas.addEventListener("touchstart", startDraw, { passive: false })
canvas.addEventListener("touchmove", moveDraw, { passive: false })
canvas.addEventListener("touchend", endDraw, { passive: false })
canvas.addEventListener("touchcancel", endDraw, { passive: false })
return
}
canvas.addEventListener("mousedown", startDraw, false)
canvas.addEventListener("mousemove", moveDraw, false)
canvas.addEventListener("mouseup", endDraw, false)
canvas.addEventListener("mouseleave", endDraw, false)
}
self.create = function (option) {
var currentOption = option || self.option
context.lineWidth = currentOption.lineWidth
context.lineCap = "round"
context.lineJoin = "round"
context.strokeStyle = currentOption.lineColor
if (currentOption.overflow === true && document.body) {
document.body.style.overflow = "hidden"
}
self.firstStatus = canvas.toDataURL("image/png")
history.length = 0
history.push(self.firstStatus)
syncHistoryIndex()
bindEvents()
}
self.getContentBase64 = function (rotate, callback) {
if (!rotate) {
var dataUrl = canvas.toDataURL("image/png")
if (callback) {
callback(dataUrl)
}
return dataUrl
}
var tempCanvas = document.createElement("canvas")
tempCanvas.width = canvas.offsetHeight || canvas.height
tempCanvas.height = canvas.offsetWidth || canvas.width
var tempContext = tempCanvas.getContext("2d")
var image = new Image()
image.onload = function () {
var centerX = Math.round(tempCanvas.width / 2)
var centerY = Math.round(tempCanvas.height / 2)
tempContext.save()
tempContext.translate(centerX, centerY)
tempContext.rotate(-90 * Math.PI / 180)
tempContext.drawImage(image, -image.width / 2, -image.height / 2)
tempContext.restore()
if (callback) {
callback(tempCanvas.toDataURL("image/png"))
}
}
image.src = self.getContentBase64(false)
}
self.getBlob = function (dataUrl) {
var content = dataUrl || self.getContentBase64()
var parts = content.split(",")
var mime = parts[0].match(/:(.*?);/)[1]
var binary = atob(parts[1])
var length = binary.length
var bytes = new Uint8Array(length)
while (length--) {
bytes[length] = binary.charCodeAt(length)
}
return new Blob([bytes], { type: mime })
}
self.getFile = function (fileName, dataUrl) {
var content = dataUrl || self.getContentBase64()
var name = fileName || "file"
var parts = content.split(",")
var mime = parts[0].match(/:(.*?);/)[1]
var suffix = mime.split("/")[1]
var binary = atob(parts[1])
var length = binary.length
var bytes = new Uint8Array(length)
while (length--) {
bytes[length] = binary.charCodeAt(length)
}
return new File([bytes], name + "." + suffix, { type: mime })
}
self.reset = function () {
if (!self.firstStatus) {
return false
}
drawImage(self.firstStatus)
history.length = 0
history.push(self.firstStatus)
syncHistoryIndex()
return true
}
self.undo = function (callback) {
if (history.length <= 1 || self.step <= 0) {
console.warn("no more undo")
if (callback) {
callback()
}
return
}
self.step -= 1
drawImage(history[self.step])
}
self.redo = function (callback) {
if (self.step >= history.length - 1) {
console.warn("no more redo")
if (callback) {
callback()
}
return
}
self.step += 1
drawImage(history[self.step])
}
}
return Signature
});