当前位置:首页 > JavaScript

js插件实现画笔绘图

2026-01-31 04:49:05JavaScript

使用HTML5 Canvas实现画笔绘图

HTML5的Canvas API是浏览器原生支持的绘图工具,无需额外插件即可实现画笔功能。以下是一个基础实现示例:

const canvas = document.getElementById('drawingCanvas');
const ctx = canvas.getContext('2d');
let isDrawing = false;

canvas.addEventListener('mousedown', startDrawing);
canvas.addEventListener('mousemove', draw);
canvas.addEventListener('mouseup', stopDrawing);
canvas.addEventListener('mouseout', stopDrawing);

function startDrawing(e) {
    isDrawing = true;
    ctx.beginPath();
    ctx.moveTo(e.offsetX, e.offsetY);
}

function draw(e) {
    if (!isDrawing) return;
    ctx.lineTo(e.offsetX, e.offsetY);
    ctx.stroke();
    ctx.beginPath();
    ctx.moveTo(e.offsetX, e.offsetY);
}

function stopDrawing() {
    isDrawing = false;
}

使用第三方库Fabric.js

Fabric.js是一个功能强大的Canvas库,提供更高级的绘图功能:

js插件实现画笔绘图

const canvas = new fabric.Canvas('drawingCanvas');
let isDrawing = false;

canvas.on('mouse:down', (o) => {
    isDrawing = true;
    const pointer = canvas.getPointer(o.e);
    canvas.freeDrawingBrush.startFrom({ x: pointer.x, y: pointer.y });
});

canvas.on('mouse:move', (o) => {
    if (!isDrawing) return;
    const pointer = canvas.getPointer(o.e);
    canvas.freeDrawingBrush.moveTo({ x: pointer.x, y: pointer.y });
});

canvas.on('mouse:up', () => {
    isDrawing = false;
});

// 设置画笔样式
canvas.freeDrawingBrush = new fabric.PencilBrush(canvas);
canvas.freeDrawingBrush.color = '#000000';
canvas.freeDrawingBrush.width = 5;

使用SVG实现矢量绘图

SVG也是浏览器原生支持的矢量绘图方案:

const svg = document.getElementById('drawingSvg');
let isDrawing = false;
let currentPath;

svg.addEventListener('mousedown', (e) => {
    isDrawing = true;
    currentPath = document.createElementNS('http://www.w3.org/2000/svg', 'path');
    currentPath.setAttribute('stroke', 'black');
    currentPath.setAttribute('fill', 'none');
    currentPath.setAttribute('stroke-width', '2');
    const startPoint = `M ${e.offsetX} ${e.offsetY} `;
    currentPath.setAttribute('d', startPoint);
    svg.appendChild(currentPath);
});

svg.addEventListener('mousemove', (e) => {
    if (!isDrawing) return;
    const newPoint = `L ${e.offsetX} ${e.offsetY}`;
    const existingPath = currentPath.getAttribute('d');
    currentPath.setAttribute('d', existingPath + newPoint);
});

svg.addEventListener('mouseup', () => {
    isDrawing = false;
});

添加触摸屏支持

为移动设备添加触摸事件支持:

js插件实现画笔绘图

canvas.addEventListener('touchstart', (e) => {
    e.preventDefault();
    const touch = e.touches[0];
    const mouseEvent = new MouseEvent('mousedown', {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvas.dispatchEvent(mouseEvent);
});

canvas.addEventListener('touchmove', (e) => {
    e.preventDefault();
    const touch = e.touches[0];
    const mouseEvent = new MouseEvent('mousemove', {
        clientX: touch.clientX,
        clientY: touch.clientY
    });
    canvas.dispatchEvent(mouseEvent);
});

canvas.addEventListener('touchend', (e) => {
    e.preventDefault();
    const mouseEvent = new MouseEvent('mouseup', {});
    canvas.dispatchEvent(mouseEvent);
});

实现撤销重做功能

为绘图工具添加历史记录功能:

const history = [];
let historyIndex = -1;

function saveState() {
    historyIndex++;
    if (historyIndex < history.length) {
        history.length = historyIndex;
    }
    history.push(canvas.toDataURL());
}

function undo() {
    if (historyIndex <= 0) return;
    historyIndex--;
    const img = new Image();
    img.onload = () => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(img, 0, 0);
    };
    img.src = history[historyIndex];
}

function redo() {
    if (historyIndex >= history.length - 1) return;
    historyIndex++;
    const img = new Image();
    img.onload = () => {
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.drawImage(img, 0, 0);
    };
    img.src = history[historyIndex];
}

添加画笔样式选项

提供多种画笔样式选择:

function setBrushColor(color) {
    ctx.strokeStyle = color;
    ctx.fillStyle = color;
}

function setBrushSize(size) {
    ctx.lineWidth = size;
}

function setBrushType(type) {
    switch(type) {
        case 'pencil':
            ctx.globalCompositeOperation = 'source-over';
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
            break;
        case 'marker':
            ctx.globalCompositeOperation = 'multiply';
            ctx.lineCap = 'square';
            ctx.lineJoin = 'bevel';
            break;
        case 'eraser':
            ctx.globalCompositeOperation = 'destination-out';
            ctx.lineCap = 'round';
            ctx.lineJoin = 'round';
            break;
    }
}

标签: 画笔插件
分享给朋友:

相关文章

vue实现功能插件

vue实现功能插件

Vue 插件实现方法 Vue 插件通常用于封装全局功能(如指令、过滤器、混入等),以下是实现 Vue 插件的典型方式: 插件基本结构 const MyPlugin = { instal…

vue实现皮肤插件

vue实现皮肤插件

实现思路 Vue实现皮肤插件通常通过动态切换CSS变量或类名实现。核心思路是将皮肤样式抽离为独立的CSS文件或变量,通过用户交互或配置切换不同的皮肤主题。 基础实现方案 定义皮肤变量 在全局CSS中…

vue实现插件功能

vue实现插件功能

Vue 插件实现方法 安装与注册插件 在 Vue 项目中,插件通常以独立模块形式存在。通过 Vue.use() 方法注册插件,该方法会自动调用插件的 install 函数。 // 引入插件 i…

vue插件实现联动

vue插件实现联动

Vue 插件实现联动的方法 使用全局事件总线 在 Vue 中可以通过创建一个全局事件总线来实现组件间的联动。首先创建一个新的 Vue 实例作为事件总线。 // event-bus.js import…

vue分页插件实现

vue分页插件实现

Vue 分页插件实现方法 使用现成组件库(推荐) Element UI、Ant Design Vue 等主流库已提供成熟分页组件,可直接集成: <template> <el-…

php 插件实现

php 插件实现

PHP 插件实现方法 PHP 插件可以通过多种方式实现,具体取决于插件的用途和功能需求。以下是一些常见的实现方法: 使用钩子(Hooks)和过滤器(Filters) 钩子和过滤器是一种常见的插…