做者:©liyuechun
简介:JavaScript30 是 Wes Bos 推出的一个 30 天挑战。项目免费提供了 30 个视频教程、30 个挑战的起始文档和 30 个挑战解决方案源代码。目的是帮助人们用纯 JavaScript 来写东西,不借助框架和库,也不使用编译器和引用。如今你看到的是这系列指南的第 8 篇。完整中文版指南及视频教程在 从零到壹全栈部落。javascript
用 HTML5 中的 Canvas 的路径绘制实现一个绘画板,可供鼠标画画,颜色呈彩虹色渐变,画笔大小一样呈渐变效果。这部分不涉及 CSS 内容,所有由 JS 来实现。css
Canvas:html
模板骨架java
基本属性git
getContext()
github
strokeStyle
编程
fillStyle
canvas
fillRect
浏览器
lineCap
微信
lineJoin
路径绘制
beginPath()
lineTo()
moveTo()
鼠标事件处理:
mousemove
mousedown
mouseup
mouseout
获取 HTML 中的 <canvas>
元素,并设定宽度和高度
.getContext('2d')
获取上下文,下面以 ctx 表示
设定 ctx 基本属性
描边和线条颜色
线条宽度
线条末端形状
绘画效果
设定一个用于标记绘画状态的变量
鼠标事件监听,不一样类型的事件将标记变量设为不一样值
编写发生绘制时触发的函数,设定绘制路径起点、终点
线条彩虹渐变效果(运用 hsl 的 h
值的变化,累加)
线条粗细渐变效果(设定一个范围,当超出这个范围时,线条粗细进行逆向改变
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>HTML5 Canvas 实现彩虹画笔绘画板</title> <script type="text/javascript"> function draw() { var canvas = document.getElementById('tutorial'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); } } </script> <style type="text/css"> canvas { border: 1px solid black; } </style> </head> <body> <canvas id="tutorial" width="150" height="150"></canvas> </body> </html>
canvas> 元素
<canvas id="tutorial" width="150" height="150"></canvas>
canvas
看起来和 img
元素很相像,惟一的不一样就是它并无 src
和alt
属性。实际上,canvas
标签只有两个属性——width
和height
。这些都是可选的,而且一样利用 DOM properties
来设置。当没有设置宽度和高度的时候,canvas
会初始化宽度为300
像素和高度为150
像素。该元素能够使用CSS来定义大小,但在绘制时图像会伸缩以适应它的框架尺寸:若是CSS的尺寸与初始画布的比例不一致,它会出现扭曲。
渲染上下文(The rendering context)
var canvas = document.getElementById('tutorial'); var ctx = canvas.getContext('2d');
canvas
元素创造了一个固定大小的画布,它公开了一个或多个渲染上下文,其能够用来绘制和处理要展现的内容。
canvas
起初是空白的。为了展现,首先脚本须要找到渲染上下文,而后在它的上面绘制。canvas
元素有一个叫作 getContext()
的方法,这个方法是用来得到渲染上下文和它的绘画功能。getContext()
只有一个参数,上下文的格式。对于2D图像而言,基本教程,你能够使用CanvasRenderingContext2D
检查支持性
替换内容是用于在不支持 canvas
标签的浏览器中展现的。经过简单的测试getContext()
方法的存在,脚本能够检查编程支持性。
var canvas = document.getElementById('tutorial'); if (canvas.getContext){ //支持 var ctx = canvas.getContext('2d'); // drawing code here } else { //不支持 // canvas-unsupported code here }
一开始,让咱们来看个简单的例子,咱们绘制了两个有趣的长方形,其中的一个有着alpha透明度。咱们将在接下来的例子里深刻探索一下这是如何工做的。
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>HTML5 Canvas 实现彩虹画笔绘画板</title> <script type="text/javascript"> function draw() { var canvas = document.getElementById('tutorial'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect (10, 10, 55, 50); ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; ctx.fillRect (30, 30, 55, 50); } } </script> <style type="text/css"> canvas { border: 1px solid black; } </style> </head> <body onload="draw();"> <canvas id="tutorial" width="300" height="300"></canvas> </body> </html>
效果图:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>HTML5 Canvas</title> <style> html, body { margin: 0; overflow: hidden; } canvas { overflow: hidden; } </style> </head> <body> <canvas id="draw" width="800" height="800" style="overflow:auto;"></canvas> <script> // 1.获取canvas节点 const canvas = document.querySelector('#draw'); if (canvas.getContext) { //支持 var ctx = canvas.getContext('2d'); // drawing code here } else { //不支持 // canvas-unsupported code here console.log("canvas-unsupported code here"); } canvas.width = window.innerWidth; canvas.height = window.innerHeight; let isDrawing = false; let lastX = 0; let lastY = 0; ctx.lineWidth = 90; ctx.lineCap = "round"; ctx.lineJoin = "round"; ctx.strokeStyle = "#f00"; ctx.fillStyle = "#f00"; let hue = 0; let direction = true; let x = 0; let y = 0; function draw(e) { if (!isDrawing) return; x = e.offsetX; y = e.offsetY; // 彩虹效 ctx.strokeStyle = `hsl(${ hue }, 90%, 50%)`; if (hue >= 360) hue = 0; hue++; // 控制笔触大小 if (ctx.lineWidth > 120 || ctx.lineWidth < 10) { direction = !direction; } if (direction) { ctx.lineWidth++; } else { ctx.lineWidth--; } // 控制绘制路径 ctx.beginPath(); ctx.moveTo(lastX, lastY); ctx.lineTo(x, y); ctx.stroke(); [lastX, lastY] = [x, y]; } canvas.addEventListener('mousedown', (e) => { isDrawing = true; [lastX, lastY] = [e.offsetX, e.offsetY]; }); canvas.addEventListener('mousemove', draw); canvas.addEventListener('mouseup', () => isDrawing = false); canvas.addEventListener('mouseout', () => isDrawing = false); </script> </body> </html>
canvas.width = window.innerWidth; canvas.height = window.innerHeight;
lineCap
:笔触的形状,有 round | butt | square 圆、平、方三种。
lineJoin
:线条相交的样式,有 round | bevel | miter 圆交、斜交、斜接三种。
lineWidth
:线条的宽度
strokeStyle
:线条描边的颜色
fillStyle
:填充的颜色
beginPath()
:新建一条路径
stroke()
:绘制轮廓
moveTo()
:(这次)绘制操做的起点
lineTo()
:路径的终点
在这个挑战中,涉及到改变线条的颜色,如何实现彩虹的渐变效果?咱们须要利用 HSL 色彩模式,首先能够去这个网站 http://mothereffinghsl.com 感觉一下 HSL 不一样色彩值对应的效果。
H(hue) 表明色调,取值为 0~360,专业术语叫色相
S 是饱和度,能够理解为掺杂进去的灰度值,取值为 0~1
L 则是亮度,取值也是 0~1,或者百分比。
这之中 H 值从 0 到 360 的变化表明了色相的角度的值域变化,利用这一点就能够实现绘制时线条颜色的渐变了,只须要在它的值超过 360 时恢复到 0 从新累加便可。
let hue = 0; ctx.strokeStyle = `hsl(${ hue }, 100%, 50%)`; if(hue >= 360) hue = 0; hue++;
除此以外,若是想实现黑白水墨的颜色,能够将颜色设置为黑色,经过透明度的改变来实现深浅不一的颜色。
// 控制笔触大小 if (ctx.lineWidth > 120 || ctx.lineWidth < 10) { direction = !direction; } if (direction) { ctx.lineWidth++; } else { ctx.lineWidth--; }
上面的代码中,根据线条的宽度的变化来控制direction
的值,根据direction
的值来控制线宽是增长仍是减小。
// 控制绘制路径 ctx.beginPath(); ctx.moveTo(lastX, lastY); ctx.lineTo(x, y); ctx.stroke(); // 坐标重置 [lastX, lastY] = [x, y];
canvas.addEventListener('mousedown', (e) => { <!--开始绘图--> isDrawing = true; <!--绘图起始坐标初始化--> [lastX, lastY] = [e.offsetX, e.offsetY]; }); <!--鼠标移动时,调用draw方法--> canvas.addEventListener('mousemove', draw); <!--鼠标抬起时,将isDrawing置为false--> canvas.addEventListener('mouseup', () => isDrawing = false); <!--当鼠标不在可绘图区域范围内时,将isDrawing置为fals--> canvas.addEventListener('mouseout', () => isDrawing = false);
社群品牌:从零到壹全栈部落
定位:寻找共好,共同窗习,持续输出全栈技术社群
业界荣誉:IT界的逻辑思惟
文化:输出是最好的学习方式
官方公众号:全栈部落
社群发起人:春哥(从零到壹创始人,交流微信:liyc1215)
技术交流社区:全栈部落BBS
全栈部落完整系列教程:全栈部落完整电子书学习笔记
关注全栈部落官方公众号,每晚十点接收系列原创技术推送 |
---|
![]() |