This article mainly introduces some ideas of using Canvas to realize graphic captta-verification code and how to use javascript object-oriented way to realize the function of Canvas in a more friendly way. I have organized a mind map about some basic use methods and APIS of Canvas, and you can refer to and learn those who are interested in it.

You will reap

  • Use of closures
  • Canvas common API use
  • Javascript object-oriented implementation
  • To achieve a Canvas graphics verification code of the general idea and commonly used algorithms

Design ideas

  1. Use Canvas to generate canvas
  2. Use canvas to draw interference lines or dots
  3. Generates random nonrepeating letters of n
  4. Draw text on canvas
  5. Initialize and canvas click events
  6. Componentized encapsulation

At the end of the text will attach the component package source code, welcome to communicate at any time. For project packaging, I will use my own 9012 based on GULP4 to teach you how to use gulP4 development project scaffolding.

Results the preview

Implementation approach

I will implement it step by step according to the above design ideas. First, we define an ES5 class:

function Gcode(el, option) {
    this.el = typeof el === 'string' ? document.querySelector(el) : el;
    this.option = option;
    this.init();
}
Copy the code

Where init is used for initialization, el is the element or the element ID that you want to mount, and option is the optional option that you pass in, which will be reflected later in the code, and this is usually an object oriented routine.

  1. Draw the canvas
Gcode.prototype = {
    constructor: Gcode,
    init: function() {
        if(this.el.getContext) {
            isSupportCanvas = true;
            var ctx = this.el.getContext('2d'),
            // Set the canvas width and height
            cw = this.el.width = this.option.width || 200,
            ch = this.el.height = this.option.height || 40; }}}Copy the code

Here we first define a canvas in the initialization method, the width and height of the user defined by the width and height, the default is 200*40.

  1. Draw interference lines
// Draw the interference line
drawLine: function(ctx, lineNum, maxW, maxH) {
    ctx.clearRect(0.0, maxW, maxH);
    for(var i=0; i < lineNum; i++) {
        var dx1 = Math.random()* maxW,
            dy1 = Math.random()* maxH,
            dx2 = Math.random()* maxW,
            dy2 = Math.random()* maxH;
        ctx.strokeStyle = 'rgb(' + 255*Math.random() + ', ' + 255*Math.random() + ', ' + 255*Math.random() + ') '; ctx.beginPath(); ctx.moveTo(dx1, dy1); ctx.lineTo(dx2, dy2); ctx.stroke(); }}Copy the code

Here we define the prototype method drawLine on the Gcode class, and then draw lines at random positions through a for loop. In order to clear the canvas with each click, we use clearRect to clear the canvas.

  1. Generate n random characters that do not repeat

We do this recursively, as follows == :

// Generate unique characters
generateUniqueText: function(source, hasList, limit) {
    var text = source[Math.floor(Math.random()*limit)];
    if(hasList.indexOf(text) > - 1) {
        return this.generateUniqueText(source, hasList, limit)
    }else {
        return text
    }  
}
// Generate a specified number of random characters
randomText: function(len) {
    var source = ['a'.'b'.'c'.'d'.'e'.'f'.'g'.'h'.'i'.'j'.'k'.'l'.'m'.'o'.'p'.'q'.'r'.'s'.'t'.'u'.'v'.'w'.'x'.'y'.'z'];
    var result = [];
    var sourceLen = source.length;
    for(var i=0; i< len; i++) {
        var text = this.generateUniqueText(source, result, sourceLen);
        result.push(text)
    }
    return result.join(' ')}Copy the code

We define an alphabet, pass in the number of generated random letters, and generateUniqueText to generate n unique random characters. Of course, I think this method is not elegant, you can also use the UUID method or better, feel free to talk to me.

  1. Draw text on canvas
/ / draw text
drawText: function(ctx, text, maxH) {
    var len = text.length;
    for(var i=0; i < len; i++) {
        var dx = 30 * Math.random() + 30* i,
            dy = Math.random()* 5 + maxH/2;
        ctx.fillStyle = 'rgb(' + 255*Math.random() + ', ' + 255*Math.random() + ', ' + 255*Math.random() + ') ';
        ctx.font = '30px Helvetica';
        ctx.textBaseline = 'middle'; ctx.fillText(text[i], dx, dy); }},Copy the code

This is similar to the implementation underlined above. I won’t go into too much detail.

  1. Initialize and canvas click events

Next, let’s look at the complete initialization code:

init: function() {
    if(this.el.getContext) {
        isSupportCanvas = true;
        var ctx = this.el.getContext('2d'),
        // Set the canvas width and height
        cw = this.el.width = this.option.width || 200,
        ch = this.el.height = this.option.height || 40,
        textLen = this.option.textLen || 4,
        lineNum = this.option.lineNum || 4;
        var text = this.randomText(textLen);

        this.onClick(ctx, textLen, lineNum, cw, ch);
        this.drawLine(ctx, lineNum, cw, ch);
        this.drawText(ctx, text, ch); }}Copy the code

Click event is mainly for the user to click to switch the verification code:

onClick: function(ctx, textLen, lineNum, cw, ch) {
    var _ = this;
    this.el.addEventListener('click'.function(){
        text = _.randomText(textLen);
        _.drawLine(ctx, lineNum, cw, ch);
        _.drawText(ctx, text, ch);
    }, false)}Copy the code

At this point, a complete verification code component implementation is complete, how to use? As follows:

new Gcode('#canvas_code', {
        lineNum: 6./ / is optional
        textLen: 4./ / is optional
        width: 200./ / is optional
        height: 50   / / is optional
    })
Copy the code

The complete code is as follows:

// Canvas draws the graph verification code
    (function(){
        function Gcode(el, option) {
            this.el = typeof el === 'string' ? document.querySelector(el) : el;
            this.option = option;
            this.init();
        }
        Gcode.prototype = {
            constructor: Gcode,
            init: function() {
                if(this.el.getContext) {
                    isSupportCanvas = true;
                    var ctx = this.el.getContext('2d'),
                    // Set the canvas width and height
                    cw = this.el.width = this.option.width || 200,
                    ch = this.el.height = this.option.height || 40,
                    textLen = this.option.textLen || 4,
                    lineNum = this.option.lineNum || 4;
                    var text = this.randomText(textLen);
        
                    this.onClick(ctx, textLen, lineNum, cw, ch);
                    this.drawLine(ctx, lineNum, cw, ch);
                    this.drawText(ctx, text, ch); }},onClick: function(ctx, textLen, lineNum, cw, ch) {
                var _ = this;
                this.el.addEventListener('click'.function(){
                    text = _.randomText(textLen);
                    _.drawLine(ctx, lineNum, cw, ch);
                    _.drawText(ctx, text, ch);
                }, false)},// Draw the interference line
            drawLine: function(ctx, lineNum, maxW, maxH) {
                ctx.clearRect(0.0, maxW, maxH);
                for(var i=0; i < lineNum; i++) {
                    var dx1 = Math.random()* maxW,
                        dy1 = Math.random()* maxH,
                        dx2 = Math.random()* maxW,
                        dy2 = Math.random()* maxH;
                    ctx.strokeStyle = 'rgb(' + 255*Math.random() + ', ' + 255*Math.random() + ', ' + 255*Math.random() + ') '; ctx.beginPath(); ctx.moveTo(dx1, dy1); ctx.lineTo(dx2, dy2); ctx.stroke(); }},/ / draw text
            drawText: function(ctx, text, maxH) {
                var len = text.length;
                for(var i=0; i < len; i++) {
                    var dx = 30 * Math.random() + 30* i,
                        dy = Math.random()* 5 + maxH/2;
                    ctx.fillStyle = 'rgb(' + 255*Math.random() + ', ' + 255*Math.random() + ', ' + 255*Math.random() + ') ';
                    ctx.font = '30px Helvetica';
                    ctx.textBaseline = 'middle'; ctx.fillText(text[i], dx, dy); }},// Generate a specified number of random characters
            randomText: function(len) {
                var source = ['a'.'b'.'c'.'d'.'e'.'f'.'g'.'h'.'i'.'j'.'k'.'l'.'m'.'o'.'p'.'q'.'r'.'s'.'t'.'u'.'v'.'w'.'x'.'y'.'z'];
                var result = [];
                var sourceLen = source.length;
                for(var i=0; i< len; i++) {
                    var text = this.generateUniqueText(source, result, sourceLen);
                    result.push(text)
                }
                return result.join(' ')},// Generate unique characters
            generateUniqueText: function(source, hasList, limit) {
                var text = source[Math.floor(Math.random()*limit)];
                if(hasList.indexOf(text) > - 1) {
                    return this.generateUniqueText(source, hasList, limit)
                }else {
                    return text
                }  
            }
        }
        new Gcode('#canvas_code', {
            lineNum: 6
        })
    })();
Copy the code

If you want to experience the effect of actual cases and technical exchanges, or feel more original Canvas, H5 game demo, you can pay attention to the following public account experience oh

More recommended

  • With JavaScript and C3 to achieve a turntable small game
  • Teach you to use 200 lines of code to write a love bean spell H5 small game (with source code)
  • Exploration and summary of front-end integrated solutions based on React/VUE ecology
  • How to use gulP4 development project scaffolding
  • How to write your own JS library in less than 200 lines of code
  • A summary of common JS functions that make you more productive in an instant
  • A picture shows you how to play vue-Cli3 quickly
  • 3 minutes teach you to use native JS implementation with progress listening file upload preview component
  • 3 minutes teach you to use native JS implementation with progress listening file upload preview component
  • Developing travel List with Angular8 and Baidu Maps API
  • Js basic search algorithm implementation and 1.7 million data under the performance test
  • How to make front-end code 60 times faster
  • Front End Algorithm series array deweighting
  • Vue Advanced Advanced series – Play with Vue and vuex in typescript
  • In the first three years, talk about the top five books worth reading