【问题标题】:Drawing on canvas with opacity (dots in line) javascript在不透明的画布上绘图(行中的点)javascript
【发布时间】:2015-05-18 07:45:06
【问题描述】:

我有那个绘图逻辑:

Draw = function(canvas, ctx, mousePosition) {

    var grad = ctx.createLinearGradient(0, 0, canvas[0].width, 0);
    grad.addColorStop(0, currentLineColor);
    grad.addColorStop(1, currentLineColor);

    ctx.lineWidth = currentLineWidth;
    ctx.strokeStyle = grad;
    ctx.lineCap = 'round';
    ctx.lineJoin = 'round';
    ctx.globalAlpha = 0.4;

    ctx.beginPath();
    ctx.moveTo(lastMousePosition.x, lastMousePosition.y);
    ctx.lineTo(mousePosition.x, mousePosition.y);
    ctx.stroke();
};

当我在这段代码中设置 globalAlpha 以设置不透明度时,会看到我画线中的点。此逻辑附加到 mosemove 事件。

【问题讨论】:

    标签: javascript html canvas drawing


    【解决方案1】:

    是的,这是意料之中的,因为每条线在连接点处都被透支了,并且它们的 alpha 数据将相加。

    我建议采用以下方法,并在最后附上一个概念验证演示,您可以随意将该代码应用到您的项目中:

    1. 创建两个画布,一个主要的,一个在顶部的草稿
    2. 使用 CSS(不透明度)直接在顶部元素上设置 alpha 并始终保持globalAlpha=1
    3. 对于每个笔画(下笔、上笔)在草稿画布上绘制(在每个点之间使用线条)
    4. 上笔时,在主画布上设置 globalAlpha 等于顶部画布的 CSS 不透明度
    5. 使用drawImage() 将顶部画布绘制到主画布。
    6. 清除顶部画布,吃饭,睡觉,重复(从 3 开始)。

    概念验证

    var draft = document.getElementById("draft");
    var main = document.getElementById("main");
    var ctx = draft.getContext("2d");
    var mctx = main.getContext("2d");
    var isDown = false, prev, alpha = 0.4;
    
    // setup pen
    ctx.strokeStyle = "rgb(0,200,127)";
    ctx.lineWidth = 16;
    ctx.lineCap = "round";                              // important to make lines cont.
    
    // set up alpha
    draft.style.opacity = alpha;                        // CSS alpha for draft
    mctx.globalAlpha = alpha;                           // context alpha for main
    
    draft.onmousedown = function(e){
      isDown = true; 
      prev = getXY(e);                                  // set prev. point as start
    };
    
    window.onmousemove = function(e){
      if (!isDown) return;
      var point = getXY(e);
      ctx.beginPath();                                  // new path
      ctx.moveTo(prev.x, prev.y);                       // start at prev. point
      ctx.lineTo(point.x, point.y);                     // line to new point
      ctx.stroke();                                     // stroke
      prev = point;                                     // update prev. point
    };
    
    window.onmouseup = function(){
      isDown = false;                                   // when up:
      mctx.drawImage(draft, 0, 0);                      // copy drawing to main
      ctx.clearRect(0, 0, draft.width, draft.height);   // clear draft
    };
    
    function getXY(e) {
      var r = draft.getBoundingClientRect();
      return {x: e.clientX - r.left, y: e.clientY - r.top}
    }
    #draft {cursor:crosshair}
    .sandwich {position:relative}
    .sandwich>canvas {position:absolute;left:0;top:0}
    <div class="sandwich">
      <canvas id="main" width=600 height=600></canvas>
      <canvas id="draft" width=600 height=600></canvas>
    </div>

    【讨论】:

    • 这太棒了,而且效果很好。我有一个问题,是否可以右键单击并保存图像?目前它返回一个空图像,因为我猜返回的是空画布而不是主画布?
    • @almostabeginner 这是一个好问题,几乎值得单独发帖 :) 但一个快速的解决方法是将草稿画布'pointer-events 设置为无,将画布特定事件处理程序附加到主要事件处理程序,但保留使用草稿上下文进行绘制。
    • 令人印象深刻,这似乎是一个非常好的解决方案。谢谢!
    • 是否可以撤消/重做它?
    猜你喜欢
    • 2015-10-20
    • 2012-05-07
    • 1970-01-01
    • 2015-06-29
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    • 2013-11-25
    • 2012-12-18
    相关资源
    最近更新 更多