deary-sign
Version:
178 lines (177 loc) • 6.14 kB
JavaScript
import { ref as r, computed as D, onMounted as J, onUnmounted as O, openBlock as A, createElementBlock as H } from "vue";
const G = {
__name: "DearySign",
props: {
width: {
type: Number,
default: 800
},
height: {
type: Number,
default: 300
},
lineWidth: {
type: Number,
default: 4
},
lineColor: {
type: String,
default: "#000000"
},
bgColor: {
type: String,
default: ""
},
isCrop: {
type: Boolean,
default: !1
},
isClearBgColor: {
type: Boolean,
default: !0
},
format: {
type: String,
default: "image/png"
},
quality: {
type: Number,
default: 1
}
},
setup(X, { expose: Y }) {
const l = r(null), y = r(!1), C = r(""), d = r([]), f = r(0), p = r(0), w = r(!1), c = r(1), o = X, B = D(() => o.height / o.width), g = D(() => l.value.getBoundingClientRect()), b = D(() => o.bgColor ? o.bgColor : "rgba(255, 255, 255, 0)"), T = () => {
const e = l.value;
e.style.width = o.width + "px";
const t = parseFloat(window.getComputedStyle(e).width);
e.style.height = B.value * t + "px";
const u = e.getContext("2d");
u.scale(1 * c.value, 1 * c.value), c.value = t / o.width, u.scale(1 / c.value, 1 / c.value);
}, M = (e) => {
f.value = e.x, p.value = e.y;
const t = l.value.getContext("2d");
t.beginPath(), t.moveTo(f.value, p.value), t.lineTo(e.x, e.y), t.lineCap = "round", t.lineJoin = "round", t.lineWidth = o.lineWidth * c.value, t.stroke(), t.closePath(), d.value.push(e);
}, S = (e) => {
const t = l.value.getContext("2d");
t.beginPath(), t.moveTo(f.value, p.value), t.lineTo(e.x, e.y), t.strokeStyle = o.lineColor, t.lineWidth = o.lineWidth * c.value, t.lineCap = "round", t.lineJoin = "round", t.stroke(), t.closePath(), p.value = e.y, f.value = e.x, d.value.push(e);
}, _ = (e) => {
const t = l.value.getContext("2d");
t.beginPath(), t.moveTo(f.value, p.value), t.lineTo(e.x, e.y), t.lineCap = "round", t.lineJoin = "round", t.stroke(), t.closePath(), d.value.push(e), d.value.push({ x: -1, y: -1 });
}, I = (e) => {
e.preventDefault(), w.value = !0, y.value = !0;
let t = {
x: e.offsetX,
y: e.offsetY
};
M(t);
}, P = (e) => {
if (e.preventDefault(), w.value) {
let t = {
x: e.offsetX,
y: e.offsetY
};
S(t);
}
}, E = (e) => {
e.preventDefault();
let t = {
x: e.offsetX,
y: e.offsetY
};
_(t), w.value = !1;
}, W = (e) => {
if (e.preventDefault(), y.value = !0, e.touches.length === 1) {
let t = {
x: e.targetTouches[0].clientX - g.value.left,
y: e.targetTouches[0].clientY - g.value.top
};
M(t);
}
}, q = (e) => {
if (e.preventDefault(), e.touches.length === 1) {
let t = {
x: e.targetTouches[0].clientX - g.value.left,
y: e.targetTouches[0].clientY - g.value.top
};
S(t);
}
}, F = (e) => {
if (e.preventDefault(), e.touches.length === 1) {
let t = {
x: e.targetTouches[0].clientX - g.value.left,
y: e.targetTouches[0].clientY - g.value.top
};
_(t);
}
}, k = (e) => {
let t = e && e.format ? e.format : o.format, u = e && e.quality ? e.quality : o.quality;
return new Promise((s, i) => {
if (!y.value) {
i("未签名");
return;
}
const a = l.value, n = a.getContext("2d"), v = n.getImageData(0, 0, a.width, a.height);
n.globalCompositeOperation = "destination-over", n.fillStyle = b.value, n.fillRect(0, 0, a.width, a.height), C.value = a.toDataURL(t, u);
let R = C.value;
if (n.clearRect(0, 0, a.width, a.height), n.putImageData(v, 0, 0), n.globalCompositeOperation = "source-over", o.isCrop) {
const m = U(v.data);
let h = document.createElement("canvas");
const x = h.getContext("2d");
h.width = m[2] - m[0], h.height = m[3] - m[1];
const z = n.getImageData(...m);
x.globalCompositeOperation = "destination-over", x.putImageData(z, 0, 0), x.fillStyle = b.value, x.fillRect(0, 0, 0, h.width, h.height), R = h.toDataURL(t, u), h = null;
}
s(R);
});
}, L = (e) => new Promise((t, u) => {
k(e).then((s) => {
fetch(s).then((i) => i.blob()).then((i) => {
const a = new File([i], "sign.png", { type: "image/png" });
t({
file: a,
base64: s
});
});
}).catch((s) => {
u(s);
});
}), N = () => {
const e = l.value;
e.getContext("2d").clearRect(0, 0, e.width, e.height), o.isClearBgColor && (e.style.background = "rgba(255, 255, 255, 0)"), d.value = [], y.value = !1, C.value = "";
}, U = (e) => {
let t = l.value.width, u = 0, s = l.value.height, i = 0;
for (let a = 0; a < l.value.width; a++)
for (let n = 0; n < l.value.height; n++) {
const v = (a + l.value.width * n) * 4;
(e[v] > 0 || e[v + 1] > 0 || e[v + 2] || e[v + 3] > 0) && (i = Math.max(n, i), u = Math.max(a, u), s = Math.min(n, s), t = Math.min(a, t));
}
return t++, u++, s++, i++, [t, s, u, i];
};
return J(() => {
const e = l.value;
e.height = o.height, e.width = o.width, e.style.background = b.value, T(), document.onmouseup = () => {
w.value = !1;
}, window.addEventListener("resize", T);
}), O(() => {
document.onmouseup = null, window.removeEventListener("resize", T);
}), Y({
generate: k,
generateFile: L,
reset: N
}), (e, t) => (A(), H("canvas", {
class: "deary-sign",
ref_key: "canvasRef",
ref: l,
style: { "max-width": "100%", display: "block" },
onMousedown: I,
onMousemove: P,
onMouseup: E,
onTouchstart: W,
onTouchmove: q,
onTouchend: F
}, null, 544));
}
};
export {
G as DearySign
};