平滑线条并创建渐变
Smoothing a line and creating a gradient
我正在为 class 做这个,我已经设法创建了一个绘图应用程序,其中笔划对鼠标的速度作出反应,并且笔划的颜色根据角度而变化。
链接here。
不过看起来真的很粗糙,我想了解如何通过连接笔划来平滑线条(这样它看起来就像是改变宽度的单个笔划),以及是否可以创建渐变,从红色到绿色。我试图从老师那里得到一些帮助,但我们每周大约有 10 分钟的时间专门为我们的项目获得个人帮助,很难提出所有这些问题并理解代码中发生的事情......
请注意,我在这方面得到了很多帮助。我以前使用 paper.js 做过类似的事情,但我的老师更喜欢我为此使用 "pure" canvas。我有网页设计的背景,但它远非编程,我只知道标记语言和使用 html 和 css,偶尔使用一些 jquery 滑块。因此,即使是最简单的教程,我也完全感到困惑,我尝试按照 this 进行操作,但我什至不明白将所有内容放在哪里,而且它根本不起作用。
如果有人能在这方面给我一些帮助,我将非常高兴...ELI5,拜托了。我学得很快,但我仍然处于困惑状态,被所有这些我(还)不理解但真的很想理解的代码行弄得不知所措。
提前致谢!
几个提示:
设置context.lineCap='round'
。这四舍五入每行的开头和结尾。该舍入有助于在视觉上将一行合并到下一行。
将您的线宽限制在一个较小的范围内。这使您的线条在视觉上更流畅,因为当用户快速更改速度时,尺寸不会有很大的跳跃。
这是重构代码和演示:
// cache a reference to the canvas element & its context
// because they are used often
var canvas=$('#canvas')[0];
var context = canvas.getContext('2d');
//full-screen
canvas.width = 500;
canvas.height = 500;
// style lines with rounded end-caps & rounded joins
context.lineJoin='round';
context.lineCap='round';
var mouseX = undefined;
var mouseY = undefined;
var mouseIsDown = false;
var PI2=Math.PI*2;
var speed=-1000;
(function(){Math.clamp=function(a,b,c){return Math.max(b,Math.min(c,a));}})();
onMouseDown = function( event ){
// tell the browser we're handling this event
event.preventDefault();
event.stopPropagation();
mouseIsDown = true;
}
onMouseMove = function( event ){
// tell the browser we're handling this event
event.preventDefault();
event.stopPropagation();
var previousMouseX = mouseX;
var previousMouseY = mouseY;
mouseX = event.pageX;
mouseY = event.pageY;
var dx = Math.abs( mouseX - previousMouseX );
var dy = Math.abs( mouseY - previousMouseY );
var speed = Math.sqrt( dx * dx + dy * dy );
// limit the min/max width of the line
speed=Math.clamp(speed,2,12);
var angle = 2 * Math.PI * Math.acos( dx / ( speed + 0.00001 ) );
if( angle < Math.PI ){
context.strokeStyle = 'rgb( 0, 255, 0 )';
}
else{
context.strokeStyle = 'rgb( 255, 0, 0 )';
}
if( mouseIsDown ){
context.lineWidth=speed;
context.beginPath();
context.moveTo( previousMouseX, previousMouseY );
context.lineTo( mouseX, mouseY );
context.stroke();
}
}
//drawing only is the mouse is down
onMouseUp = function( event ){
// tell the browser we're handling this event
event.preventDefault();
event.stopPropagation();
mouseIsDown = false;
}
$( '#canvas' ).on( 'mousedown', onMouseDown );
$( '#canvas' ).on( 'mousemove', onMouseMove );
$( '#canvas' ).on( 'mouseup', onMouseUp );
$( '#canvas' ).on( 'mouseout', onMouseUp );
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="canvas" width=500 height=500></canvas>
应用渐变要困难得多。您将必须:
- 保存每个鼠标点
- 在每个鼠标点之间插入点,使每个新点与前一个点相距 1px。
- 清除canvas
- 在每个鼠标点之间重新绘制一条线,每条线的 strokeStyle 根据您想要的渐变变化。
我正在为 class 做这个,我已经设法创建了一个绘图应用程序,其中笔划对鼠标的速度作出反应,并且笔划的颜色根据角度而变化。
链接here。
不过看起来真的很粗糙,我想了解如何通过连接笔划来平滑线条(这样它看起来就像是改变宽度的单个笔划),以及是否可以创建渐变,从红色到绿色。我试图从老师那里得到一些帮助,但我们每周大约有 10 分钟的时间专门为我们的项目获得个人帮助,很难提出所有这些问题并理解代码中发生的事情......
请注意,我在这方面得到了很多帮助。我以前使用 paper.js 做过类似的事情,但我的老师更喜欢我为此使用 "pure" canvas。我有网页设计的背景,但它远非编程,我只知道标记语言和使用 html 和 css,偶尔使用一些 jquery 滑块。因此,即使是最简单的教程,我也完全感到困惑,我尝试按照 this 进行操作,但我什至不明白将所有内容放在哪里,而且它根本不起作用。
如果有人能在这方面给我一些帮助,我将非常高兴...ELI5,拜托了。我学得很快,但我仍然处于困惑状态,被所有这些我(还)不理解但真的很想理解的代码行弄得不知所措。
提前致谢!
几个提示:
设置
context.lineCap='round'
。这四舍五入每行的开头和结尾。该舍入有助于在视觉上将一行合并到下一行。将您的线宽限制在一个较小的范围内。这使您的线条在视觉上更流畅,因为当用户快速更改速度时,尺寸不会有很大的跳跃。
这是重构代码和演示:
// cache a reference to the canvas element & its context
// because they are used often
var canvas=$('#canvas')[0];
var context = canvas.getContext('2d');
//full-screen
canvas.width = 500;
canvas.height = 500;
// style lines with rounded end-caps & rounded joins
context.lineJoin='round';
context.lineCap='round';
var mouseX = undefined;
var mouseY = undefined;
var mouseIsDown = false;
var PI2=Math.PI*2;
var speed=-1000;
(function(){Math.clamp=function(a,b,c){return Math.max(b,Math.min(c,a));}})();
onMouseDown = function( event ){
// tell the browser we're handling this event
event.preventDefault();
event.stopPropagation();
mouseIsDown = true;
}
onMouseMove = function( event ){
// tell the browser we're handling this event
event.preventDefault();
event.stopPropagation();
var previousMouseX = mouseX;
var previousMouseY = mouseY;
mouseX = event.pageX;
mouseY = event.pageY;
var dx = Math.abs( mouseX - previousMouseX );
var dy = Math.abs( mouseY - previousMouseY );
var speed = Math.sqrt( dx * dx + dy * dy );
// limit the min/max width of the line
speed=Math.clamp(speed,2,12);
var angle = 2 * Math.PI * Math.acos( dx / ( speed + 0.00001 ) );
if( angle < Math.PI ){
context.strokeStyle = 'rgb( 0, 255, 0 )';
}
else{
context.strokeStyle = 'rgb( 255, 0, 0 )';
}
if( mouseIsDown ){
context.lineWidth=speed;
context.beginPath();
context.moveTo( previousMouseX, previousMouseY );
context.lineTo( mouseX, mouseY );
context.stroke();
}
}
//drawing only is the mouse is down
onMouseUp = function( event ){
// tell the browser we're handling this event
event.preventDefault();
event.stopPropagation();
mouseIsDown = false;
}
$( '#canvas' ).on( 'mousedown', onMouseDown );
$( '#canvas' ).on( 'mousemove', onMouseMove );
$( '#canvas' ).on( 'mouseup', onMouseUp );
$( '#canvas' ).on( 'mouseout', onMouseUp );
canvas{border:1px solid red;}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<canvas id="canvas" width=500 height=500></canvas>
应用渐变要困难得多。您将必须:
- 保存每个鼠标点
- 在每个鼠标点之间插入点,使每个新点与前一个点相距 1px。
- 清除canvas
- 在每个鼠标点之间重新绘制一条线,每条线的 strokeStyle 根据您想要的渐变变化。