在 HTML5 画布中绘制鼠标移动的半透明线

Drawing semi-transparent lines on mouse movement in HTML5 canvas(在 HTML5 画布中绘制鼠标移动的半透明线)
本文介绍了在 HTML5 画布中绘制鼠标移动的半透明线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图让用户通过在画布上绘制半透明线条的绘画"工具在区域上绘画来指定区域.其目的是为将在画布下方绘制的图像指定一个蒙版".

I'm trying to let users specify an area by painting over it with a "paint" tool that draws semi-transparent lines on a canvas. Its purpose is specifying a "mask" for an image that will be drawn below on the canvas.

这是我迄今为止尝试过的:

This is what I tried so far:

var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var canvasPos = canvas.getBoundingClientRect();

var dragging = false;

drawImage();

$(canvas).mousedown(mouseDown);
$(canvas).mouseup(mouseUp);
$(canvas).mousemove(mouseMove);

function drawImage() {
    var img = new Image();
    img.src = 'http://img2.timeinc.net/health/img/web/2013/03/slides/cat-allergies-400x400.jpg';

    img.onload = function () {
        ctx.drawImage(img, 0, 0);
    };
}

function mouseDown(e) {
    var pos = getCursorPosition(e);

    dragging = true;

    ctx.strokeStyle = 'rgba(0, 100, 0, 0.25)';
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.lineWidth = 15;
    ctx.beginPath();
    ctx.moveTo(pos.x, pos.y);
}

function mouseUp(e) {
    dragging = false;
}

function mouseMove(e) {
    var pos, i;

    if (!dragging) {
        return;
    }

    pos = getCursorPosition(e);

    ctx.lineTo(pos.x, pos.y);
    ctx.stroke();
}

function getCursorPosition(e) {
    return {
        x: e.clientX - canvasPos.left,
        y: e.clientY - canvasPos.top
    };
}

  • 上述代码的 jsfiddle 链接:http://jsfiddle.net/s34PL/2/

此示例代码的问题是,随后绘制的像素使不透明度变得越来越不可见.我认为这是因为这条线是 15 像素宽(但我希望它那么宽).

The issue with this example code is that subsequent pixels that are drawn are making the opacity becomes less and less visible. I think it's because the line is 15 pixels wide (but I want it that wide though).

我该如何解决这个问题?

How can I solve this issue?

谢谢!

推荐答案

问题是你一遍又一遍地画整个路径:

The problem is that you are drawing the whole path again and again:

function mouseMove(e) {
    ...
    ctx.stroke(); // Draws whole path which begins where mouseDown happened.
}

您只需绘制路径的新段 (http://jsfiddle.net/jF9a6/).然后......你遇到了 15px 宽度的问题.

You have to draw only the new segment of the path (http://jsfiddle.net/jF9a6/). And then ... you have the problem with the 15px width of the line.

那么如何解决呢?我们必须像你一样立即画线,但要避免在现有线的顶部画线.这是代码:http://jsfiddle.net/yfDdC/

So how to solve this? We have to draw the line at once as you did, but avoid painting on top of existing lines. Here is the code: http://jsfiddle.net/yfDdC/

最大的变化是 paths 数组.它包含是的,路径 :-) 路径是存储在 mouseDownmouseMove 函数中的点数组.在 mouseDown 函数中创建新路径:

The biggest change is the paths array. It contains yeah, paths :-) A path is an array of points stored in mouseDown and mouseMove functions. New path is created in mouseDown function:

paths.push([pos]); // Add new path, the first point is current pos.

在 mouseMove 中,将当前鼠标位置添加到 paths 数组中的最后一个路径并刷新图像.

In the mouseMove you add current mouse position to the last path in paths array and refreshs the image.

paths[paths.length-1].push(pos); // Append point tu current path.
refresh();

refresh() 函数清除整个画布,再次绘制猫并绘制每条路径.

The refresh() function clears the whole canvas, draws the cat again and draws every path.

function refresh() {
    // Clear canvas and draw the cat.
    ctx.clearRect(0, 0, ctx.width, ctx.height);
    if (globImg)
        ctx.drawImage(globImg, 0, 0);

    for (var i=0; i<paths.length; ++i) {
        var path = paths[i];

        if (path.length<1)
            continue; // Need at least two points to draw a line.

        ctx.beginPath();
        ctx.moveTo(path[0].x, path[0].y);
        ... 
        for (var j=1; j<path.length; ++j)
            ctx.lineTo(path[j].x, path[j].y);
        ctx.stroke();

    }
}

这篇关于在 HTML5 画布中绘制鼠标移动的半透明线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

Update another component when Formik form changes(当Formik表单更改时更新另一个组件)
Formik validation isSubmitting / isValidating not getting set to true(Formik验证正在提交/isValiating未设置为True)
React Validation Max Range Using Formik(使用Formik的Reaction验证最大范围)
Validation using Yup to check string or number length(使用YUP检查字符串或数字长度的验证)
Updating initialValues prop on Formik Form does not update input value(更新Formik表单上的初始值属性不会更新输入值)
password validation with yup and formik(使用YUP和Formick进行密码验证)