JS 30 是由加拿大的全端工程师 Wes Bos 免费提供的 JavaScript 简单应用课程,课程主打 No Frameworks
、No Compilers
、No Libraries
、No Boilerplate
在30天的30部教学影片里,建立30个JavaScript的有趣小东西。
另外,Wes Bos 也很无私地在 Github 上公开了所有 JS 30 课程的程序码,有兴趣的话可以去 fork 或下载。
使用 JavaScript 实作出能在 HTML Canvas 上用笔刷画图的极简版小画家。
在 body
内放入 canvas
标签作为我们的画布,这里虽然指定大小为 800*800,但之後会利用 JS 把它改成跟视窗(window)一样大。
<canvas id="draw" width="800" height="800"></canvas>
取得 canvas
标签後,将画布的宽、高,将其改成跟视窗内部的宽、高一样的数值。
const canvas = document.querySelector('#draw');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
canvas
只是一个空白的画布,实际上我们需要"取得画布的渲染环境
(rendering context)"才能在渲染环境上作画。
我们呼叫 canvas
的 getContext()
方法并放入 "2d
" 作为参数,顺利取得 canvas
的 2D 渲染环境
,若是要取得 3D 渲染环境只要放入 "3d" 作为参数就好。
紧接着,我们调整 context
的 strokeStyle
属性值,更改作画时的画笔颜色。
context
的 lineJoin
是用来设定两条长度不为0的线段如何在接合处连接,把值设定为 "round
" 则在相连部分以扇形连接。
context
的 lineCap
是用来设定线段末端的呈现方式,把值设定为 "round
" 则在末端部分以扇形呈现。
context
的 lineWidth
用来设定线条的粗细。
const ctx = canvas.getContext('2d');
ctx.strokeStyle = '#BADASS';
ctx.lineJoin = 'round';
ctx.lineCap = 'round';
ctx.lineWidth = 100;
我们希望在视窗下按住滑鼠拖曳时作画,所以在 canvas
上注册4个事件监听器。
触发'mousedown
'事件时,设定 isDrawing = true
,表示现在可以作画;设定 [lastX,lastY] = [e.offsetX,e.offsetY]
,更新作画的起始点。
触发'mousemove
'事件时,用 draw()
方法持续的作画。
触发'mouseup
'、'mouseout
'时,皆设定 isDrawing = false
,表示在滑鼠没被按住和滑鼠离开视窗的情况下都停止作画。
let isDrawing = false;//flag
let lastX = 0;
let lastY = 0;
canvas.addEventListener('mousemove',draw);
canvas.addEventListener('mousedown',(e)=> {
isDrawing = true;
[lastX,lastY] = [e.offsetX,e.offsetY];
}
);
canvas.addEventListener('mouseup',()=> isDrawing = false);
canvas.addEventListener('mouseout',()=> isDrawing = false);
事件处理方法 draw()
,在最初就先判断现在能不能作画,不能的话(isDrawing = false
)就直接返回。
ctx.beginPath()
用来建立一个新的作画路径。
ctx.moveTo()
用来移动路径起始点的座标。
ctx.lineTo()
用来指定这条路径的终点座标。
ctx.stroke()
将这条路径描出来。
[lastX,lastY] = [e.offsetX,e.offsetY]
用来不断更新"此次"按住滑鼠拖曳作画过程中持续变动的路径起始点。
function draw(e){
if(!isDrawing) return;
ctx.beginPath();
//start from
ctx.moveTo(lastX,lastY);
//go to
ctx.lineTo(e.offsetX,e.offsetY);
ctx.stroke();
[lastX,lastY] = [e.offsetX,e.offsetY];
}
HSL
的 H(Hue,色相角度),是由 0~360 为止的色相循环,0是红色、120是绿色、240是蓝色,Hue 本身不加单位,详细说明可以参考下方补充资料 CSS Coke 大大的文章。
宣告 hue
变数指定画笔颜色,并持续的将 hue + 1,当 hue >= 360时,代表颜色已经循环过一次,故将其重设为0。
宣告 direction
变数作为目前该加粗画笔还是让画笔变细的判断,direction
的初始值是 true
也就是让画笔变粗。第一个 if 判断目前的画笔粗细是不是 >= 100 或 <= 1,如果条件符合就将 direction
变为相反值(true 变 false)。在第二个的 if-else 判断,如果 direction = true
就加粗画笔、反之则让画笔变得更细。
let hue = 0;
let direction = true;
function draw(e){
/*.......省略*/
ctx.strokeStyle = `hsl(${hue},100%,50%)`;
/*.......省略*/
hue++;
if(hue >= 360){
hue = 0;
}
if(ctx.lineWidth >= 100 || ctx.lineWidth <= 1){
direction = !direction;
}
if(direction){
ctx.lineWidth++;
}else{
ctx.lineWidth--;
}
}
最後来介绍一个特别的东西,ctx
的 globalCompositeOperation
主要用来处理叠图(线段重叠)的情况,若将其设定为 'multiply
' 则将上层像素与相对应的下层像素相乘,整体效果是让颜色更加趋於黑色。
ctx.globalCompositeOperation = 'multiply';
globalCompositeOperation
)Canvas 基本用途
CanvasRenderingContext2D.strokeStyle
CanvasRenderingContext2D.lineJoin
CanvasRenderingContext2D.lineCap
CanvasRenderingContext2D.lineWidth
CanvasRenderingContext2D.beginPath()
CanvasRenderingContext2D.moveTo()
CanvasRenderingContext2D.lineTo()
RGB、HSL、Hex 网页色彩码,看完这篇全懂了
JS一秒区分clientX,offsetX,screenX,pageX之间关系
CanvasRenderingContext2D.globalCompositeOperation
<<: Day08 - Docker 101 Image 建置篇
想问一下大家觉得要是想从事软件开发或是前端web的工程师,大家会推荐念硕士课程吗?还是大家觉得实战经...
上一篇我们讲到如何用Slider去改变颜色 这篇会介绍如何使用输入框 程序码如下: //控制红色的输...
除了可以用CDN(Content Delivery Network)的方式来引入Vue之外,我们还可...
昨天学习到了JSX的几大特色与优点之後,今天就正式来学习用JSX搭配react。载入JSX之前先引用...
If you want your iPhone to be more original and st...