当前位置: 首页 > news >正文

牟平网站制作公司北京小程序制作公司

牟平网站制作公司,北京小程序制作公司,滑县网站建设哪家便宜,电子商务网站开发相关技术文章目录 Canvas—从入门到案例实现一、设置canvas环境1.1 canvas元素1.2 渲染上下文context 二、形状与路径的绘制2.1 形状绘制2.2 路径绘制2.3 绘制一个笑脸 三、使用样式和颜色四、绘制文本五、使用图像5.1 图片源5.2 获取页面内的图片5.3 缩放Scaling5.4 切片Slici… 文章目录 Canvas—从入门到案例实现一、设置canvas环境1.1 canvas元素1.2 渲染上下文context 二、形状与路径的绘制2.1 形状绘制2.2 路径绘制2.3 绘制一个笑脸 三、使用样式和颜色四、绘制文本五、使用图像5.1 图片源5.2 获取页面内的图片5.3 缩放Scaling5.4 切片Slicing5.5 控制图像的缩放行为 六、状态的保存与恢复七、变形 Transformations7.1 移动 Translating7.2 旋转 Rotating7.3 缩放 Scaling 八、综合案例多功能画板九、综合案例时钟十、更多内容 Canvas—从入门到案例实现 canvas是一个可以使用脚本通常是JavaScript来绘制图形的HTML元素例如它可以用于绘制图表、制作图片构图或者制作简单的动画。 本篇博客就基础开始描述了如何使用canvas元素来绘制2D图形。 并通过多功能画板和时钟两个综合案例带大家练习canvas。 多功能画板展示 时钟展示 一、设置canvas环境 1.1 canvas元素 canvas看起来和img元素很相像与img的不同就是它没有src和alt属性并且canvas元素需要结束标签/canvas。 实际上canvas标签只有两个属性width和height这两个属性是可选的当没有设置宽高时canvas会初始化宽度为300像素和高度为150像素另外canvas也可以使用CSS来定义宽高但在绘制时图像会伸缩以适应它的框架尺寸如果CSS的尺寸与初始化画布的比例不一致它会出现扭曲。 注意如果你绘制出来的图像是扭曲的尝试用width和height属性为canvas明确规定宽高而不是使用CSS。 1.2 渲染上下文context canvas元素创造了一个固定大小的画布它公开了一个或多个渲染上下文其可以用来绘制和处理要展示的内容。 canvas起初是空白的为了展示首先脚本需要找到渲染上下文然后在它的上面绘制canvas元素有一个叫做**getContext()的方法这个方法用来获取渲染上下文和它的绘画功能getContext()**接受一个参数即上下文的类型对于2D图像而言传2d即可。 下面我们来看一个实例 !DOCTYPE html html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlecanvas/titlestyle#canvas {border: 1px solid #000;/* 这里使用css定义canvas宽高经常会出现画出的图形被压缩的问题 可以删掉canvas dom元素上的宽高属性试试 *//* width: 150px;height: 150px; */position: relative;top: 150px;left: 50%;transform: translate(-50%);}/style /headbodycanvas idcanvas width150 height150!-- 如果当前浏览器不支持canvas将会显示盒子内的内容作为兜底提示 --current browoser not support canvas/canvasscriptfunction draw () {// 拿到canvas的dom对象let canvas document.getElementById(canvas);// 拿到canvas的上下文对象let ctx canvas.getContext(2d);if(ctx) { // 判断上下文对象是否存在 即检查支持性// canvas-supported code herectx.fillStyle rgba(200, 0, 0);ctx.fillRect(10, 10, 50, 50);ctx.fillStyle rgba(0, 0, 200, 0.5);ctx.fillRect(30, 30, 50, 50);}else {// canvas-unsupported code herealert(当前浏览器不支持canvas)return}}draw()/script /body/html上面代码通过拿到canvas的dom对象然后根据上下文是否存在来检查canvas的支持性以做不同处理如果支持则进行绘制不支持则给出提示【现今所有主流浏览器都支持canvas】上面代码运行结果如下 二、形状与路径的绘制 在开始画图之前我们需要了解一下画布栅格以及坐标空间 如上图所示canvas元素默认被网格所覆盖通过来说网格中的一个单元相当于canvas元素中的一像素栅格的起点为左上角坐标为(0,0)。所有元素的位置都相对于原点定位。 2.1 形状绘制 这里我们主要介绍一下矩形的绘制canvas提供了三种方法绘制矩形 fillRect(x, y, width, height)绘制一个填充的矩形strokeRect(x, y, width, height)绘制一个矩形的边框clearRect(x, y, width, height)清除指定矩形区域让清除部分完全透明 xy分别表示矩形的起始点即左上角的位置相对于坐标轴原点的距离width和height分别表示矩形的宽高。 实例如下 function draw () {let canvas document.getElementById(canvas);let ctx canvas.getContext(2d);if(ctx) { // 判断上下文对象是否存在 即检查支持性// canvas-supported code herectx.fillRect(25, 25, 100, 100) // 填充矩形ctx.clearRect(45, 45, 60, 60) // 透明/空心矩形ctx.strokeRect(50, 50, 50, 50) // 轮廓矩形}else {// canvas-unsupported code herealert(当前浏览器不支持canvas)return} } draw()输出如下 这里再介绍一下圆弧的绘制语法ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise) 圆弧路径的圆心在(xy)位置半径为radius根据anticlockwise默认为顺时针指定的方向从startAngle开始绘制到endAngle结束。 startAngle圆弧的起始点x轴方向开始计算单位以弧度表示。 endAngle圆弧的终点单位以弧度表示。 anticlockwise可选的Boolean值如果为true逆时针制圆弧反之顺时针绘制默认为false。 2.2 路径绘制 图形的基本元素是路径。路径是通过不同颜色和宽度的线段或曲线相连形成的不同形状的点的集合。一个路径甚至一个子路径都是闭合的。使用路径绘制图形需要一些额外的步骤。 首先你需要创建路径起始点然后使用画图命令去画出路径之后把路径封闭一旦路径生成你就能通过描边或填充路径区域来渲染图形 以下是所要用到的函数 beginPath()新建一条路径生成之后图形绘制命令被指向到路径上生成路径。 closePath()闭合路径之后图形绘制命令又重新指向到上下文中。 stroke()通过线条来绘制图形轮廓。 fill()通过填充路径的内容区域生成实心的图形。 moveTo()移动笔触将笔触移动到指定的坐标x以及y上就类似手写笔记时将笔尖移动到A4纸上的某个位置这个方法跟python的海龟作图一样。 关于beiginPath()生成路径的第一步本质上路径是由很多子路径构成这些子路径都是在一个列表中所有的子路径线弧形等等构成图形而每次这个方法调用之后列表清空重置然后我们就可以重新绘制新的图形了。 注意前路径为空即调用 beginPath() 之后或者 canvas 刚建的时候第一条路径构造命令通常被视为是 moveTo()无论实际上是什么。出于这个原因你几乎总是要在设置路径之后专门指定你的起始位置。 关于closePath()非必需这个方法会通过绘制一条从当前点到开始点的直线来闭合图形。如果图形是已经闭合了的即当前点为开始点该函数什么也不做。当调用fill()函数之后形状会自动闭合所以不需要调用此函数、 下面我们通过使用canvas绘制一个三角形来体会前面讲的函数 function draw() {let canvas document.getElementById(canvas);let ctx canvas.getContext(2d);ctx.beginPath(); // 新建一条路径ctx.moveTo(75, 50); // 将路径的起始点定在(75, 50)位置ctx.lineTo(100, 75); // 从路径起始点到(100, 75)绘制一条线ctx.lineTo(75, 100);ctx.fill(); // 自动填充图形 如果图形没闭合会自动闭合 } draw()结果如下 2.3 绘制一个笑脸 下面我们结合图形绘制和路径绘制实现一个简单的笑脸。 function draw() {let canvas document.getElementById(canvas);let ctx canvas.getContext(2d);ctx.beginPath(); // 开始绘制ctx.arc(75, 75, 50, 0, 2 * Math.PI)ctx.moveTo(110, 75)ctx.arc(75, 75, 35, 0, Math.PI)ctx.moveTo(65, 65)ctx.arc(60, 65, 5, 0, Math.PI * 2)ctx.moveTo(95, 65)ctx.arc(90, 65, 5, 0, Math.PI * 2)ctx.stroke(); // 展示线条 } draw()结果如下 三、使用样式和颜色 可配置颜色、透明度、线型样式、线型渐变、径向渐变、图案样式、阴影等。 api比较多详细可看MDN——使用样式和颜色 四、绘制文本 canvas提供了两种方法来渲染文本 fillText(text, x, y, [, maxWidth])在指定的xy位置填充指定的文本绘制的最大宽度是可选的。strokeText(text, x, y, [, maxWidth])在指定的xy位置绘制文本边框绘制的最大宽度是可选的。 文本也可以通过一些样式属性来调整文本样式 ctx.font value这个属性和CSS的font属性相同语法默认的字体是10px sans-seriftextAlign value文本对齐选项可选的值包括start、end、left、rightorcenter默认值是starttextBaseline value基线对齐选项可选的值包括top、hanging、middle、alphabetic、ideographic、bottom。默认值是alphabetic。direction value文本方向。可能的值包括ltrrtlinherit。默认值是inherit。 下面我们看实例 function draw() {let canvas document.getElementById(canvas);let ctx canvas.getContext(2d);ctx.font 10px serif;ctx.fillText(Hello World, 0, 10);ctx.font 30px serif;ctx.strokeText(Hello World, 0, 150);let text ctx.measureText(Hello World);console.log(text.width); // 165 } draw()结果如下 需要注意的是canvas绘制图形和路径往往是以左上角的位置为参考而canvas使用fillText()和strokeText()设置文字位置时是以文字左下角的位置为相对位置。 上面的代码段中还使用了measureText()对象获取文本的更多细节它将返回一个TextMetrics对象的宽度、所在像素这些体现文本特性的属性其中输出文本宽度可以使用.width。 五、使用图像 canvas更有意思的一项特性就是图像操作能力。可以用于动态的图像合成或者作为图形的背景以及游戏界面Sprites等等。浏览器支持的任意格式的外部图片都可以使用比如PNG、GIF或者JPEG。你甚至可以将同一个页面中其他canvas元素生成的图片作为图片源。 引入图形到canvas里需要以下两步基本操作 获得一个指向HTMLImageElement的对象或者另一个canvas元素的引用作为源也可以通过提供一个URL的方式来使用图片。使用drawImage()函数将图片绘制到画布上。 drawImage()函数的常规语法如下 drawImage(image, dx, dy)。 其中dx表示图片相对canvas左上角的x轴位置dy表示图片相对canvas左上角的y轴位置。 更高阶的用法如缩放Scaling切片Slicing会在后面详细讲解。 5.1 图片源 canvas的API可以使用下面这些类型中的一个作为图片的源 HTMLImageElement这种类型是由Image()函数构造出来的或者任何的img元素。HTMLVideoElement用一个HTML的video元素作为你的图片源可以从视频中抓取当前帧作为一个图像。HTMLCanvasElement可以使用另一个canvas元素作为你的图片源。ImageBitmap这是一个高性能的位图可以低延迟地绘制它可以从上述的所有源以及其他几种源中生成。 5.2 获取页面内的图片 我们可以通过下列方法的一种来获得与canvas相同页面内的图片的引用 document.images集合document.getElementsByTagName()方法如果你知道你想使用的指定图片的ID你可以用document.getElementById()获得这个图片 也可以通过new Image()创建img元素自定义图片。 下面我们来看实例 let img new Image(); img.src ./canvas_drawimage2.jpg; ctx.drawImage(img, 0, 0);当脚本执行后图片开始装载若调用drawImage时图片没装载完那什么都不会发生在一些旧浏览器中可能会抛出异常。因此你应该用load事件来保证不会在加载完毕之前使用这个图片 let img new Image(); img.onload function () {// 执行drawImage语句ctx.drawImage(img, 0, 0); } img.src ./canvas_drawimage2.jpg;结果如下 5.3 缩放Scaling drawImage()的缩放用法比常规用法多了两个参数语法如下 drawImage(image, x, y, width, height)其中 x, y表示图片位置width, height表示图片缩放的大小 下面我们通过缩放功能实现在canvas上平铺图像 let img new Image(); img.onload function () {for (let i 0; i 4; i) {for (let j 0; j 3; j) {ctx.drawImage(frame, j * 50, i * 38, 50, 38);}} } img.src ./canvas_drawimage2.jpg;结果如下 5.4 切片Slicing drawImage()的切片方法需要传递9个参数除了第一个参数和常规方法和缩放方法一样其他参数都不一样下面我们来详细看看它的语法 drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)其余八个参数中前4个定义图片源的切片位置和大小后4个则是定义切片的目标显示位置和大小。 切片是做图片合成的强大工具。假设有一张包含了所有元素的图像那么你可以用这个方法来合成一个完整图像。例如你想画一张图表而手上有一个包含所有必需的文字的 PNG 文件那么你可以很轻易的根据实际数据的需要来改变最终显示的图表。这方法的另一个好处就是你不需要单独装载每一个图像。 下面我们来实现用另一张图片来替换前面章节的相框内的犀牛头。 bodycanvas idcanvas width300 height300!-- 如果当前浏览器不支持canvas将会显示盒子内的内容作为兜底提示 --current browoser not support canvas/canvasdiv styledisplay: none;img idsource src./img22_min.png width132 height150 alt资源img idframe src./canvas_drawimage2.jpg width190 height190 alt相框/divscriptfunction draw() {// 获取canvas元素const canvas document.getElementById(canvas);// 获取绘图环境const ctx canvas.getContext(2d);// 获取图片元素const source document.getElementById(source);const frame document.getElementById(frame);// 绘制相框ctx.drawImage(frame, 0, 0);// 绘制图片ctx.drawImage(source, 10, 10, 250, 120, 52, 43, 124, 102);}draw();/script /body结果如下 5.5 控制图像的缩放行为 过度缩放图像可能会导致图像模糊或像素化。你可以通过使用绘图环境的imageSmoothingEnabled属性来控制是否在缩放图像时使用平滑算法。默认值为true即启用平滑缩放。你也可以像这样禁用此功能 ctx.mozImageSmoothingEnabled false; ctx.webkitImageSmoothingEnabled false; ctx.msImageSmoothingEnabled false; ctx.imageSmoothingEnabled false;六、状态的保存与恢复 在了解变形之前我们先了解两个你在开始绘制复杂图形时必不可少的方法。 save()保存画布canvas的所有状态restore()save和restore方法是用来保存和恢复canvas状态的都没有参数。 canvas的状态就是当前画面应用的所有样式和变形的一个快照。 canvas状态存储在栈中每当save()方法被调用后当前的状态就被推送到栈中保存。一个绘画状态包括 当前应用的变形即移动旋转和缩放以及下面这些属性strokeStyle,fillStyle,globalAppha,lineWidth,lineCap…当前的裁剪路径clipping path 你可以调用任意次save方法。每一次调用restore方法上一个保存的状态就从栈中弹出所有设定都恢复。 下面我们看实例 function draw() {const canvas document.getElementById(canvas);const ctx canvas.getContext(2d);// 使用默认状态画一个矩形 背景色是黑色的ctx.fillRect(0, 0, 150, 150)ctx.save() // 保存默认状态ctx.fillStyle #ff0000// 使用新状态绘制一个矩形 背景色红色ctx.fillRect(15, 15, 120, 120)ctx.save() // 保存新状态ctx.fillStyle #0000ffctx.globalAlpha 0.5// 使用新状态绘制一个矩形 背景色蓝色 透明度0.5ctx.fillRect(30, 30, 90, 90)// 恢复到之前保存的状态 根据栈后进先出原则 弹出的状态应该是红色背景的状态ctx.restore()ctx.fillRect(45, 45, 60, 60)// 再次弹出的应该是默认状态ctx.restore()ctx.fillRect(60, 60, 30, 30) } draw();上面这段代码实现了两次保存状态第一次是默认状态第二次是红色背景状态在restore()恢复状态时根据栈后进先出原则第一次恢复弹出的状态是红色背景状态第二次弹窗的是默认状态结果展示如下 七、变形 Transformations canvas的变形和css的变形比较类似变形可以将canvas原点移动到另一点、对网格进行旋转和缩放。 这里主要讲解移动 Translating、旋转 Rotating、缩放 Scaling有关变形Transforms的内容建议查看MDN——Transformations。 7.1 移动 Translating 使用translate(x, y)方法实现移动canvas和它的原点到一个不同的位置。 其中x表示左右偏移量y表示上下偏移量。 在做变形之前先保存状态是一个良好的习惯大多数情况下调用restore方法比手动恢复原先的状态要简单得多。又如果你是在一个循环中做位移但没有保存和恢复canvas的状态很可能到最后会发现怎么有些东西不见了那是因为它很可能已经超出canvas范围以外了。 下面我们看实例 function draw() {const canvas document.getElementById(canvas);const ctx canvas.getContext(2d);for (let i 0; i 3; i) {for (let j 0; j 3; j) {// 保存默认状态ctx.save()// 改变填充颜色ctx.fillStyle rgb( 80 * i , 80 * j , 255)// 移动原点ctx.translate(10 50 * j, 10 50 * i)ctx.fillRect(0, 0, 30, 30)// 恢复默认状态ctx.restore()}} } draw();上面的代码段使用循环实现了通过tranlate()改变原点位置从而绘制不同颜色的矩形结果如下 7.2 旋转 Rotating 使用rotate(angle)方法实现旋转canvas这个方法只接收一个参数旋转的角度angle它是顺时针方向的以弧度为单位的值并且是以原点为中心旋转canvas。 旋转的中心始终是canvas的原点如果要改变它我们需要用到translate(x, y)方法。 下面我们看实例 function draw() {const canvas document.getElementById(canvas);const ctx canvas.getContext(2d);ctx.save()ctx.fillStyle #88f;ctx.fillRect(10, 10, 60, 60);// 绕默认原点旋转ctx.rotate(Math.PI / 180 * 25);ctx.fillStyle #f88;ctx.fillRect(10, 10, 60, 60);ctx.restore();ctx.fillStyle #8f8ctx.fillRect(80, 10, 60, 60);ctx.translate(110, 40)// 改变原点 绕新的原点旋转 这里就相当于设置了一个旋转用的圆心ctx.rotate(Math.PI / 180 * 45);ctx.translate(-110, -40)ctx.fillStyle #88f;ctx.fillRect(80, 10, 60, 60); } draw();上面的代码段实现了矩形绕默认原点旋转以及绕通过translate(x, y)新设置的原点旋转结果如下 7.3 缩放 Scaling 使用scale(x, y)实现缩放我们用它来增减图形在canvas中的像素数目对形状位图进行缩小或者放大。 scale方法可以缩放画布的水平和垂直的单位。两个参数都是实数可以为负数x为水平缩放因子y为垂直缩放因子如果比1小会缩放图形如果比1大会放大图形。默认值为1为实际大小。 画布初始情况下是以左上角坐标为原点的第一象限。如果参数为负实数相当于以 x 或 y 轴作为对称轴镜像反转例如使用translate(0,canvas.height); scale(1,-1); 以 y 轴作为对称轴镜像反转就可得到著名的笛卡尔坐标系左下角为原点。 默认情况下canvas 的 1 个单位为 1 个像素。举例说如果我们设置缩放因子是 0.51 个单位就变成对应 0.5 个像素这样绘制出来的形状就会是原先的一半。同理设置为 2.0 时1 个单位就对应变成了 2 像素绘制的结果就是图形放大了 2 倍 下面我们看案例 function draw() {const canvas document.getElementById(canvas);const ctx canvas.getContext(2d);ctx.save()// 参照矩阵ctx.fillRect(1, 10, 10, 10)// 设置缩放因子x为10 y为3 则canvas的一个单位[默认是一个像素]就会变成x方向上10像素y方向上3像素ctx.scale(10, 3)// 因此第二个矩形相对于为缩放前的canvas的参数应该是(10, 30, 100, 30)ctx.fillRect(1, 10, 10, 10)ctx.restore()ctx.font 20px serifctx.save()// 参照文字ctx.fillText(canvas, 80, 80)// 水平镜像ctx.scale(-1, 1)ctx.fillText(canvas, -80, 100)ctx.restore()// 垂直镜像ctx.scale(1, -1)ctx.fillText(canvas, 80, -120) } draw();上面代码段画了一个初识盒子并按照x方向10倍、y方向3倍缩放盒子以及实现了文字的水平镜像和垂直镜像结果如下 八、综合案例多功能画板 接下来我们结合前面章节所学的知识使用原生html和js实现一个画板画板要具有保存图片、清除画板、设置画笔粗细功能。 结果界面展示 功能演示 保存的图片展示 下面我们看代码 drawBoard.html !DOCTYPE html html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titlecanvas/titlestyle* {padding: 0;margin: 0;box-sizing: border-box;}.main-box {width: 100%;height: 100vh;position: relative;overflow: hidden;user-select: none;.bgc {z-index: -1;position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%);object-fit: cover;}.operate-box {height: 32px;line-height: 30px;display: flex;/* column-gap: 20px; */padding-left: 10px;font-size: 20px;background-color: rgba(255, 255, 255, .9);.title {font-weight: 600;padding: 0 10px;margin-right: 20px;}.btn {cursor: pointer;padding: 0 5px;}.btn:hover {background-color: rgba(204, 204, 204, 0.8);}}.canvas-box {position: absolute;top: calc(50% 16px);left: 50%;transform: translate(-50%, -50%);border-radius: 10px;background-color: #fff;padding: 10px;box-shadow: 4px 5px 10px rgba(0, 0, 0, .7);}}.dialog {width: 100vw;height: 100vh;position: absolute;top: 0;z-index: 2;display: none;/* 文字无法选中 */user-select: none;.setting-box {width: 400px;height: 290px;position: relative;left: 50%;top: 50%;transform: translate(-50%, -50%);border: 1px solid #ccc;border-radius: 10px;padding: 10px;display: flex;flex-direction: column;background-color: #fff;.header {display: flex;align-items: center;justify-content: space-between;font-size: 20px;.close {width: 24px;height: 24px;cursor: pointer;}}.content {display: flex;flex-direction: column;align-items: center;justify-content: center;flex: 1;.item {width: 100%;display: flex;align-items: center;.item-name {width: 80px;text-align: right;font-size: 18px;}.item-value {display: flex;align-items: center;.sub,.add {font-size: 26px;height: 20px;line-height: 18px;cursor: pointer;}.sub {margin: 0 6px 0 10px;}.add {margin: 0 10px 0 6px;}.progress-box {height: 20px;display: flex;align-items: center;width: 180px;cursor: pointer;.horizontal-line {position: relative;width: 100%;height: 4px;border: 1px solid #000;.vertical-line {position: absolute;top: 50%;transform: translateY(-50%);height: 20px;width: 4px;background-color: #000;border: 1px solid #000;}}}}}}.footer {display: flex;align-items: center;padding: 0 100px;justify-content: space-between;font-size: 20px;.setting-confirm,.setting-reset {text-align: center;width: 60px;border: 1px solid #ccc;border-radius: 4px;cursor: pointer;}}}}/style /headbodydiv classmain-box!-- 背景图 --img classbgc src./bgc_1.jpg alt!-- 操作栏 --div classoperate-boxdiv classtitle这是一块画板/divdiv classbtn idsetting设置/divdiv classbtn idclear清除/divdiv classbtn idsave保存/div/divdiv classcanvas-box!-- 画布 --canvas idcanvas!-- 如果当前浏览器不支持canvas将会显示盒子内的内容作为兜底提示 --current browoser not support canvas/canvas/div/divdiv classdialog iddialogdiv classsetting-boxdiv classheaderdiv classtheme设置/divimg classclose idclose src./close_icon.png alt关闭按钮/img/divdiv classcontentdiv classitemdiv classitem-name线粗:/divdiv classitem-valuediv classsub idsub-/divdiv classprogress-box idlinediv classhorizontal-linediv classvertical-line idprogress/div/div/divdiv classadd idadd/divdiv classvalue idline_width_value/div/div/div/divdiv classfooterdiv classsetting-confirm idsetting_save保存/divdiv classsetting-reset idsetting_reset重置/div/div/div/divscript src./drawBoard.js/script /body/htmldrawBoard.js let canvasWidth window.innerWidth * 0.8; let canvasHeight window.innerHeight * 0.88;// 拿到画板、重置按钮、保存按钮的dom元素 let canvas document.getElementById(canvas); let clear document.getElementById(clear); let save document.getElementById(save); // 设置相关数据 let setting document.getElementById(setting); // 设置按钮dom元素 let close document.getElementById(close); // 关闭设置按钮dom元素 let line_width_value document.getElementById(line_width_value); // 当前值dom元素 let add document.getElementById(add); // 加按钮dom元素 let sub document.getElementById(sub); // 减按钮dom元素 let line document.getElementById(line); // 进度线dom元素 let progress document.getElementById(progress); // 进度线标签dom元素 let setting_save document.getElementById(setting_save); // 保存按钮dom元素 let setting_reset document.getElementById(setting_reset); // 重置按钮dom元素 let defaultConfig {// 默认设置数据lineWidth: 3, };let tempConfig {// 临时存的设置数据lineWidth: defaultConfig.lineWidth, }; // 初始化画板宽高 canvas.width canvasWidth; canvas.height canvasHeight;// 监听窗口大小变化 实现canvas大小自适应 window.addEventListener(resize, () {canvasWidth window.innerWidth * 0.9;canvasHeight window.innerHeight * 0.88;canvas.width canvasWidth;canvas.height canvasHeight; });let startTag false; // 开始绘画的标识 鼠标按下设为true 鼠标弹起设为false let ctx canvas.getContext(2d);// 初始化 ctx.lineWidth defaultConfig.lineWidth; // 初始化canvas路径宽度 line_width_value.innerText ctx.lineWidth; progress.style.left (ctx.lineWidth / 10) * 100 %; ctx.fillStyle #fff; // 初始化canvas背景色 ctx.fillRect(0, 0, canvasWidth, canvasHeight); // 填个矩形 避免下载下来的图片背景是镂空的 // 监听鼠标按下事件 canvas.addEventListener(mousedown, (e) {// 新建一条路径ctx.beginPath();// 设置路径原点为鼠标按下出ctx.moveTo(e.offsetX, e.offsetY);startTag true; });// 监听鼠标移动事件 canvas.addEventListener(mousemove, (e) {if (!startTag) return;// 生成路径ctx.lineTo(e.offsetX, e.offsetY);ctx.stroke(); // 绘制当前或已经存在的路径的方法 也就是让路径看得到 默认是黑色的 });canvas.addEventListener(mouseup, (e) {ctx.closePath();startTag false; });// 清除事件 clear.onclick () {ctx.fillStyle #fff;ctx.fillRect(0, 0, canvasWidth, canvasHeight); };// 保存图片事件 save.onclick () {let img canvas.toDataURL(image/jpg);let a document.createElement(a);a.href img;a.download 画板.png;a.target _blank; // a标签的属性target _blank表示在新标签页打开a.click(); };// 控制设置弹窗的显示 setting.onclick () {dialog.style.display block; }; // 控制设置弹窗的隐藏 close.onclick () {ctx.lineWidth tempConfig.lineWidth;line_width_value.innerText ctx.lineWidth;progress.style.left (ctx.lineWidth / 10) * 100 %;dialog.style.display none; };// add.onclick () {if (ctx.lineWidth 10) {ctx.lineWidth ctx.lineWidth 1;line_width_value.innerText ctx.lineWidth;progress.style.left (ctx.lineWidth / 10) * 100 %;} };// - sub.onclick () {if (ctx.lineWidth 1) {ctx.lineWidth ctx.lineWidth - 1;line_width_value.innerText ctx.lineWidth;progress.style.left (ctx.lineWidth / 10) * 100 %;} };// 重置 恢复默认数据 setting_reset.onclick () {ctx.lineWidth defaultConfig.lineWidth;line_width_value.innerText ctx.lineWidth;progress.style.left (ctx.lineWidth / 10) * 100 %; };// 保存 设置数据 setting_save.onclick () {tempConfig.lineWidth ctx.lineWidth;dialog.style.display none; };// 点击进度条更改值 line.addEventListener(click, (e) {ctx.lineWidth ((e.offsetX / 180) * 10).toFixed()? ((e.offsetX / 180) * 10).toFixed(): 1;line_width_value.innerText ctx.lineWidth;progress.style.left (ctx.lineWidth / 10) * 100 %; }); 代码上传github了canvas实现画板欢迎大家光临我的空间 九、综合案例时钟 下面我们再实现一个案例——时钟 界面展示如下 效果展示如下 下面我们看代码 clock.html !DOCTYPE html html langenheadmeta charsetUTF-8meta nameviewport contentwidthdevice-width, initial-scale1.0titleclock/titlestyle* {margin: 0;padding: 0;}.main-box {width: 100%;height: 100vh;display: flex;align-items: center;justify-content: center;overflow: hidden;#canvas {border: 1px solid #000;}}/style /headbodydiv classmain-boxcanvas idcanvas width600 height600/canvas/divscript src./clock.js/script /body/htmlclock.js /*** window.requestAnimationFrame()告诉浏览器——你希望执行一个动画并且要求浏览器在下次重绘之前调用指定的回调函数更新动画* 该方法需要传入一个回调函数作为参数该回调函数会在浏览器下一次重绘之前执行*/ let animate (time) {let now new Date();let hour now.getHours();let minus now.getMinutes();let second now.getSeconds();hour hour % 12;let ctx document.getElementById(canvas).getContext(2d);ctx.clearRect(0, 0, 600, 600);// 保存默认状态ctx.save();ctx.lineWidth 10;// 画个圆ctx.beginPath();ctx.arc(300, 300, 250, 0, Math.PI * 2);ctx.stroke();// 画完圆后恢复到默认状态ctx.restore();// 画小时数字ctx.save();ctx.lineWidth 2;ctx.translate(300, 300);ctx.beginPath();ctx.font 48px serif;for (let i 0; i 12; i) {let x Math.sin((Math.PI / 6) * (i 1)) * 180;let y Math.cos((Math.PI / 6) * (i 1)) * 180 * -1; // 注意 这里一定要乘以负一// console.log(x, x, y, y);ctx.textAlign center;ctx.textBaseline middle;ctx.strokeText((i 1).toString(), x, y);}ctx.restore();// 保存默认状态ctx.save();// canvas初始化原点移到canvas中心旋转-90度因为默认选择是从左上角原点y轴方向开始旋转的ctx.translate(300, 300);ctx.rotate(-Math.PI / 2);ctx.lineCap round;// 画小时刻度// 保存初始化ctx.save();ctx.lineWidth 8;ctx.beginPath();for (let i 0; i 12; i) {ctx.rotate((Math.PI / 180) * 30);ctx.moveTo(210, 0);ctx.lineTo(250, 0);ctx.stroke();}ctx.restore();// 画分钟刻度ctx.save();ctx.lineWidth 4;ctx.beginPath();for (let i 0; i 60; i) {ctx.rotate((Math.PI / 180) * 6);ctx.moveTo(230, 0);ctx.lineTo(250, 0);ctx.stroke();}ctx.restore();// 画时针ctx.save();ctx.beginPath();ctx.lineWidth 20;ctx.rotate((Math.PI / 6) * (hour minus / 60 second / 3600));ctx.moveTo(-60, 0);ctx.lineTo(140, 0);ctx.stroke();ctx.restore();// 画分针ctx.save();ctx.beginPath();ctx.lineWidth 14;ctx.rotate((Math.PI / 30) * (minus second / 60));ctx.moveTo(-60, 0);ctx.lineTo(190, 0);ctx.stroke();ctx.restore();// 画秒针ctx.save();ctx.beginPath();ctx.lineWidth 10;ctx.rotate((Math.PI / 30) * second);ctx.moveTo(-60, 0);ctx.lineTo(220, 0);ctx.strokeStyle #f00;ctx.stroke();ctx.restore();// 画圆心ctx.save();ctx.beginPath();ctx.fillStyle #f00;ctx.arc(0, 0, 15, 0, Math.PI * 2);ctx.fill();ctx.restore();ctx.restore();window.requestAnimationFrame(animate); };window.requestAnimationFrame(animate);需要注意的是 在修改默认状态前一定要先save状态每画一部分内容记得restore状态并且使用beiginPath重新开始绘制否则画出的结果将会出现奇怪的内容比如页面无限闪动、偏移等问题 源码同样上传了github:canvas实现clock。欢迎访问 十、更多内容 以上是我所介绍的canvas所有基础内容。 更多内容建议查看MDN——canvas教程。
http://www.dnsts.com.cn/news/254810.html

相关文章:

  • 天津自助建站软件设计类网站建设规划书
  • 陕西正天建设有限公司网站晋中市住房与城乡建设厅网站
  • 便宜建站北京 网站 公司
  • 什么是网络营销调研网络优化与维护是做什么
  • 一般可以在哪些网站做推广舟山房产信息交易网
  • 做网站开发的方案大众的网站建设
  • 费县做网站wordpress游戏系统模型
  • 企业做网站哪家公司好湛江外包做网站
  • 万网怎样做网站调试网络销售的理解
  • 开发网站开发工程师招聘要求自动做设计的网站
  • 沧州网站建设推广三亚北京网站建设
  • 电子商务公司网站设计网站备案密码查询
  • 锚文本对网站装修网土巴兔
  • python做电商网站在国外建网站方便吗
  • 华为企业网站建设分析python做网页界面
  • 个人网站模板之家网页制作与网站建设教程视频
  • 青海网站建设企业任丘市做网站
  • 网站正能量点进去就能看网站模板d一品资源网
  • 抖音代运营成功案例南宁seo咨询
  • 环境文化建设方案网站3d建模师工资一般多少
  • 为什么只有建设网站打不开网站建设线框图
  • 国内公司网站需要备案商务型网站模板
  • 手机电影网站怎么做的网页制作软件推荐
  • 电子商务网站建设的方法有哪些方面如何做网站稳定客户
  • 如何保存个人网站交流网站建设心得体会
  • 学网站开发网页制作网站 空间 备案
  • 旅游景区网站建设规划mip网站模板
  • 网站托管代运营wordpress 删除分类目录
  • 高明顺德网站建设义乌企业网站设计
  • 服装模板网站信息流优化师简历