在 canvas 上绘制不透明度(直线上的点)javascript
Drawing on canvas with opacity (dots in line) javascript
我有这样的绘图逻辑:
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 事件。
是的,这是意料之中的,因为每条线在连接点处都被透支了,它们的 alpha 数据会相加。
我建议采用以下方法并在最后附上一个概念验证演示,请随意将该代码应用到您的项目中:
- 创建两个 canvases,一个主要的和一个草稿在上面
- 使用 CSS(不透明度)直接在顶部元素上设置 alpha,并始终保持
globalAlpha=1
- 对于每个笔划(下笔、上笔)在草稿上绘制 canvas(在每个点之间使用线条)
- 在起笔时,在主 canvas 上设置
globalAlpha
等于顶部 canvas 的 CSS 不透明度
- 使用
drawImage()
. 将顶部 canvas 绘制到主要 canvas
- 清除顶部 canvas,吃饭,睡觉,重复(从 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>
我有这样的绘图逻辑:
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 事件。
是的,这是意料之中的,因为每条线在连接点处都被透支了,它们的 alpha 数据会相加。
我建议采用以下方法并在最后附上一个概念验证演示,请随意将该代码应用到您的项目中:
- 创建两个 canvases,一个主要的和一个草稿在上面
- 使用 CSS(不透明度)直接在顶部元素上设置 alpha,并始终保持
globalAlpha=1
- 对于每个笔划(下笔、上笔)在草稿上绘制 canvas(在每个点之间使用线条)
- 在起笔时,在主 canvas 上设置
globalAlpha
等于顶部 canvas 的 CSS 不透明度
- 使用
drawImage()
. 将顶部 canvas 绘制到主要 canvas
- 清除顶部 canvas,吃饭,睡觉,重复(从 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>