123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202 |
- <template>
- <view class="vericode">
- <canvas class="canvas" canvas-id="codecanvas" id="codecanvas"> </canvas>
- <canvas class="tcanvas" canvas-id="tcanvas" id="tcanvas"> </canvas>
- </view>
- </template>
- <script>
- export default {
- data() {
- return {
- inDraw: false,
- width: 0,
- height: 0,
- // 每次生成的验证码
- vericode: "",
- // 生成的数字个数
- nums: 4,
- // 混淆线的条数
- drawNums: 1,
- // 混淆线宽度
- lineWidth: 1,
- };
- },
- methods: {
- async drawCode() {
- const self = this;
- if (this.inDraw) {
- return;
- }
- this.inDraw = true;
- const w = this.width;
- const h = this.height;
- let vericode = "";
- const nums = this.nums;
- const xspan = w / (nums + 1);
- const ctx = uni.createCanvasContext("codecanvas", this);
- ctx.clearRect(0, 0, w, h);
- ctx.draw();
- function drawBg() {
- const imageData = Array.from({ length: w * h * 4 });
- for (let i = 0; i < imageData.length; i += 4) {
- imageData[i + 0] = Math.random() * 255;
- imageData[i + 1] = Math.random() * 255;
- imageData[i + 2] = Math.random() * 255;
- imageData[i + 3] = 30;
- }
- uni.canvasPutImageData(
- {
- canvasId: "codecanvas",
- x: 0,
- y: 0,
- width: w,
- data: new Uint8ClampedArray(imageData),
- },
- self
- );
- return new Promise((resolv) => {
- uni.canvasToTempFilePath(
- {
- x: 0,
- y: 0,
- width: w,
- height: h,
- canvasId: "codecanvas",
- success: function (res) {
- ctx.drawImage(res.tempFilePath, 0, 0);
- resolv();
- },
- },
- self
- );
- });
- }
- // 去掉大写 0和o gq和9 1和l 等abcdefhjkmnprstuvwyz
- const source = "23456789";
- const indexArr = Array.prototype.map.call(source, (e, i) => i);
- function getAlpha() {
- const len = indexArr.length - 1 < 0 ? 0 : indexArr.length - 1;
- let i = Math.round(Math.random() * len);
- const ch = source[indexArr[i]];
- indexArr.splice(i, 1);
- return ch;
- }
- const { drawText } = (() => {
- let i = 0;
- let fontbase = Math.round(h * 0.5);
- let fontspan = fontbase / 2;
- let font = Math.round(Math.random() * fontspan) + fontbase;
- const tctx = uni.createCanvasContext("tcanvas", self);
- function drawText() {
- const xpos = (i++ % nums) * xspan;
- font = fontbase + Math.round(fontspan * Math.random());
- const txspan = 2 * xspan;
- tctx.fillStyle = `rgb(${Math.random() * 255},${Math.random() * 255},${
- Math.random() * 255
- })`;
- tctx.setFontSize(font*1.2);
- const ybase = h / 2 + font / 2;
- const xtrans = ((Math.random() - 0.5) * 2) / 5;
- const ytrans = ((Math.random() - 0.5) * 2) / 5;
- tctx.transform(1, xtrans, ytrans, 1, 0, 0);
- const txt = getAlpha();
- tctx.fillText(txt, 0.5 * txspan, ybase);
- tctx.draw();
- vericode += txt;
- return new Promise((resolv) => {
- uni.canvasToTempFilePath(
- {
- x: 0,
- y: 0,
- width: 2 * xspan,
- height: h,
- destWidth: 2 * xspan,
- destHeight: h,
- canvasId: "tcanvas",
- success: function (res) {
- ctx.drawImage(res.tempFilePath, xpos, 0);
- tctx.clearRect(0, 0, txspan, h);
- tctx.draw();
- resolv();
- },
- },
- self
- );
- });
- }
- return { drawText };
- })();
- function drawLine() {
- const drawnums = self.drawNums;
- for (let i = 0; i < drawnums; i++) {
- ctx.beginPath();
- ctx.lineWidth = self.lineWidth;
- ctx.strokeStyle = `rgba(${Math.random() * 255},${
- Math.random() * 255
- },${Math.random() * 255},0.8)`;
- // 左右非正中区域
- const x1 =
- ((Math.random() > 0.5 ? 1 : -1) * (Math.random() + 1) * w) / 4 +
- w / 2;
- // 上下非正中区域
- const y1 =
- ((Math.random() + 1) * h) / 4 + (Math.random() > 0.5 ? h / 2 : 0);
- const x2 =
- ((Math.random() > 0.5 ? 1 : -1) * (Math.random() + 1) * w) / 4 +
- w / 2;
- const y2 =
- ((Math.random() + 1) * h) / 4 + (Math.random() > 0.5 ? h / 2 : 0);
- ctx.moveTo(x1, y1);
- ctx.lineTo(x2, y2);
- ctx.closePath();
- ctx.stroke();
- }
- }
- await drawBg();
- for (let i = 0; i < nums; i++) {
- await drawText();
- }
- drawLine();
- ctx.draw();
- this.vericode = vericode;
- this.inDraw = false;
- },
- },
- mounted() {
- const self = this;
- const query = uni.createSelectorQuery().in(this);
- query
- .select(".vericode")
- .boundingClientRect((data) => {
- self.width = Math.round(data.width);
- self.height = Math.round(data.height);
- self.drawCode();
- })
- .exec();
- },
- };
- </script>
- <style scoped>
- .vericode {
- width: 100%;
- height: 100%;
- position: relative;
- overflow: hidden;
- }
- .canvas {
- position: absolute;
- left: 0;
- top: 0;
- width: 1000px;
- height: 1000px;
- }
- .tcanvas {
- position: fixed;
- top: 9999px;
- width: 1000px;
- height: 1000px;
- }
- </style>
|