SoFunction
Updated on 2025-04-14

A drawing board based on Javascript to implement web version

Project Introduction

This is a simple web-based drawing editor based on HTML5 Canvas and jQuery implementation. Provides basic image editing functions, including brush tools, erasers, brightness/contrast adjustment and other functions. Can be used for simple picture editing and drawing requirements.

Main functions

1. Basic drawing tools

Brush Tool: Supports custom colors and sizes

Eraser tool: Supports custom size

Undo/redo: Supports multi-step operation history

2. Image processing

Image upload: Support uploading local pictures

Image adjustment: Supports brightness and contrast adjustment

Image saving: You can save the edited image locally

Key points for technical implementation

1. Canvas Initialization

const canvas = $('#imageCanvas')[0];
const ctx = ('2d');

Use HTML5 Canvas as the basis for drawing, and set a white background by default.

2. Drawing implementation

The drawing function is implemented by listening to mouse events:

  • mousedown: start drawing
  • mousemove: Continuous drawing
  • mouseup/mouseleave: end drawing

Key Code:

function startDrawing(e) {
    isDrawing = true;
    ();
    
    if (currentTool === 'eraser') {
        ();
         = 'destination-out';
    } else {
         = 'source-over';
    }
    
    (, );
}

3. Eraser implementation

Eraser achieves transparent erasing by setting the globalCompositeOperation property of Canvas to ‘destination-out’:

if (currentTool === 'eraser') {
    ();
     = 'destination-out';
}

4. Image processing

The image will be automatically resized after uploading to fit the canvas, maintaining the original proportion:

const scale = ( / ,  / );
const x = ( -  * scale) / 2;
const y = ( -  * scale) / 2;

5. Brightness and contrast adjustment

Implementation using Canvas' filter property:

 = `brightness(${brightness}%) contrast(${contrast}%)`;

6. Undo/redo function

Implemented by saving the canvas state:

function saveState() {
    (());
    redoStack = [];
    updateUndoRedoButtons();
}

Instructions for use

1. Upload the picture: Click the "Upload picture" button to select the local picture

2. Basic editor:

  • Draw with the Brush Tool
  • Use the Eraser Tool to erase content
  • Adjust brightness and contrast slider to modify image effects

3. Undo/redo: Use the corresponding buttons to manage the operation history

4. Save the picture: Click the "Save" button to save the result in PNG format

Technology dependency

HTML5 Canvas

jQuery 3.7.1

Modern browser (supports ES6+)

Directions for improvement

1. Functional extension

  • Add image rotation/flip function
  • Implement image cropping function
  • Add more filter effects
  • Implement layer functions

2. User experience optimization

  • Add shortcut key support
  • Optimization tool switching interaction
  • Add operation prompts
  • Improve error handling

3. Performance optimization

  • Optimize large image processing
  • Improve the cancellation/redo mechanism
  • Add operation status cache
  • Optimize Canvas rendering performance

Things to note

There is no limit on the upload size of the picture, but it is recommended not to exceed 5MB.

The saved image format is PNG, and it supports transparency

The browser needs to support Canvas-related APIs

Complete code

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Web version picture editor</title>
    <!-- Introduced jQuery -->
    <script src="/ajax/libs/jquery/3.7.1/"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
            background-color: #f0f0f0;
        }
        
        .container {
            max-width: 1200px;
            margin: 0 auto;
        }
        
        .toolbar {
            background: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-bottom: 20px;
        }
        
        .toolbar button {
            padding: 8px 15px;
            margin: 0 5px;
            border: 1px solid #ddd;
            border-radius: 4px;
            background: #fff;
            cursor: pointer;
            transition: all 0.3s ease;
        }
        
        .toolbar button:hover {
            background: #f5f5f5;
        }
        
        .toolbar  {
            background: #e0e0e0;
        }
        
        .canvas-container {
            position: relative;
            margin: 20px 0;
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
        }
        
        #imageCanvas {
            border: 1px solid #ddd;
            margin: 0 auto;
            display: block;
        }
        
        .controls {
            background: white;
            padding: 15px;
            border-radius: 8px;
            box-shadow: 0 2px 4px rgba(0,0,0,0.1);
            margin-top: 20px;
        }
        
        .control-group {
            margin: 10px 0;
        }
        
        .control-group label {
            display: block;
            margin-bottom: 5px;
        }
        
        input[type="range"] {
            width: 200px;
        }
        
        input[type="color"] {
            width: 50px;
            height: 30px;
            padding: 0;
            border: none;
        }
        
        .hidden {
            display: none;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="toolbar">
            <input type="file"  class="hidden" accept="image/*">
            <button >Upload pictures</button>
            <button  disabled>Revoke</button>
            <button  disabled>Rework</button>
            <button  disabled>save</button>
            <button >brush</button>
            <button >Eraser</button>
        </div>

        <div class="canvas-container">
            <canvas  width="800" height="600"></canvas>
        </div>

        <div class="controls">
            <div class="control-group">
                <label for="brightnessRange">brightness:</label>
                <input type="range"  min="0" max="200" value="100">
                <span >100%</span>
            </div>

            <div class="control-group">
                <label for="contrastRange">Contrast:</label>
                <input type="range"  min="0" max="200" value="100">
                <span >100%</span>
            </div>

            <div class="control-group">
                <label for="brushSize">brush大小:</label>
                <input type="range"  min="1" max="50" value="5">
                <span >5px</span>
            </div>

            <div class="control-group">
                <label for="brushColor">brush颜色:</label>
                <input type="color"  value="#000000">
            </div>
        </div>
    </div>

    <script>
        $(document).ready(function() {
            const canvas = $('#imageCanvas')[0];
            const ctx = ('2d');
            let isDrawing = false;
            let currentTool = 'brush';
            let originalImage = null;
            let undoStack = [];
            let redoStack = [];
            
            // Initialize the canvas, set a white background             = 'white';
            (0, 0, , );
            saveState();

            // Tool selection            $('#brushBtn').click(function() {
                currentTool = 'brush';
                $(this).addClass('active');
                $('#eraserBtn').removeClass('active');
            });

            $('#eraserBtn').click(function() {
                currentTool = 'eraser';
                $(this).addClass('active');
                $('#brushBtn').removeClass('active');
            });

            // Drawing function            function startDrawing(e) {
                isDrawing = true;
                ();
                
                if (currentTool === 'eraser') {
                    ();
                     = 'destination-out';
                } else {
                     = 'source-over';
                }
                
                (, );
            }

            function draw(e) {
                if (!isDrawing) return;
                
                if (currentTool === 'eraser') {
                    ();
                     = 'destination-out';
                } else {
                     = 'source-over';
                }
                
                (, );
                ();
                
                if (currentTool === 'eraser') {
                    ();
                }
            }

            function stopDrawing() {
                if (isDrawing) {
                    isDrawing = false;
                    ();
                    
                    if (currentTool === 'eraser') {
                        ();
                    }
                    
                    saveState();
                }
            }

            $('#imageCanvas').mousedown(startDrawing)
                           .mousemove(draw)
                           .mouseup(stopDrawing)
                           .mouseleave(stopDrawing);

            // Brush control            $('#brushColor').change(function() {
                 = $(this).val();
            });

            $('#brushSize').on('input', function() {
                const size = $(this).val();
                 = size;
                $('#brushSizeValue').text(size + 'px');
            });

            // Image upload processing            $('#uploadBtn').click(function() {
                $('#imageInput').click();
            });

            $('#imageInput').change(function(e) {
                const file = [0];
                if (file) {
                    const reader = new FileReader();
                     = function(event) {
                        const img = new Image();
                         = function() {
                            // Keep the picture proportion                            const scale = ( / ,  / );
                            const x = ( -  * scale) / 2;
                            const y = ( -  * scale) / 2;
                            
                            (0, 0, , );
                            (img, x, y,  * scale,  * scale);
                            
                            originalImage = img;
                            saveState();
                            $('#saveBtn').prop('disabled', false);
                        };
                         = ;
                    };
                    (file);
                }
            });

            // Picture adjustment            function applyAdjustments() {
                if (!originalImage) return;

                const brightness = $('#brightnessRange').val();
                const contrast = $('#contrastRange').val();

                // Calculate the scaling of maintaining aspect ratio                const scale = ( / ,  / );
                const x = ( -  * scale) / 2;
                const y = ( -  * scale) / 2;

                 = `brightness(${brightness}%) contrast(${contrast}%)`;
                (0, 0, , );
                (originalImage, x, y,  * scale,  * scale);
                 = 'none';

                saveState();
            }

            $('#brightnessRange, #contrastRange').on('input', function() {
                const value = $(this).val();
                const id = $(this).attr('id');
                $(`#${id}Value`).text(value + '%');
                applyAdjustments();
            });

            // Undo/redo function            function saveState() {
                (());
                redoStack = [];
                updateUndoRedoButtons();
            }

            function updateUndoRedoButtons() {
                $('#undoBtn').prop('disabled',  <= 1);
                $('#redoBtn').prop('disabled',  === 0);
            }

            $('#undoBtn').click(function() {
                if ( <= 1) return;
                
                (());
                const lastState = undoStack[ - 1];
                loadState(lastState);
                updateUndoRedoButtons();
            });

            $('#redoBtn').click(function() {
                if ( === 0) return;
                
                const nextState = ();
                (nextState);
                loadState(nextState);
                updateUndoRedoButtons();
            });

            function loadState(state) {
                const img = new Image();
                 = function() {
                    (0, 0, , );
                    (img, 0, 0);
                };
                 = state;
            }

            // Save function            $('#saveBtn').click(function() {
                const link = ('a');
                 = 'Edited Picture.png';
                 = ();
                ();
            });

            // Set initial brush properties             = $('#brushColor').val();
             = $('#brushSize').val();
             = 'round';
             = 'round';
        });
    </script>
</body>
</html>

This is the article about the web version of the drawing board based on Javascript. For more related Javascript drawing board content, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!