使用canvas元素和JavaScript花费您的星期日(或任何一天)。

by Ashish Nandan Singh

通过Ashish Nandan Singh

使用canvas元素和JavaScript花费您的星期日(或任何一天)。 (Spend your Sunday (or any day) with the canvas element and JavaScript.)

Recently during the JavaScript30 days challenge, I had the chance to get my hands dirty with the HTML inbuilt canvas property. What convinced me to write about the entire experience was the relative comfort level and learning curve.

最近在JavaScript30天挑战赛中,我有幸接触到HTML内置的canvas属性。 使我写出全部经历的是相对舒适度和学习曲线。

In its simplest form, HTML canvas element enables a web developer to draw graphics on a web page, through javaScript, and this very aspect makes this HTML element far more interesting.

HTML画布元素以其最简单的形式,使Web开发人员可以通过javaScript在网页上绘制图形,而这一方面使该HTML元素更加有趣。

The <canvas> element is just a container — you would always use JavaScript to actually draw the graphics. One may argue that we can always have the points added or maybe an SVG for that matter, but again — what fun would that be? :D

<canva s>元素只是一个容器-您将始终使用JavaScript实际绘制图形。 有人可能会争辩说,我们可以始终为此添加点,或者也许添加SVG,但是再次重申–那会是什么乐趣? :D

Coming back to the <canvas> element: a canvas is a rectangular area on an HTML page. By default, a canvas has no border and no content.

回到<canva s>元素:画布是HTML页面上的矩形区域。 默认情况下,画布没有边框且没有内容。

The markup looks like this:

标记如下所示:

<canvas id=”canvas” width=”200" height=”100"></canvas>
<canvas id =“ canvas” width =“ 200” height =“ 100”> </ canvas>
开始 (The beginning)

Alright so much for the introduction. Let’s focus on building something fun using some plain old JavaScript, (not so old — ES6!). First, we’ll take a look at the starter files.

好了,介绍。 让我们专注于使用一些普通的旧JavaScript(不是那么旧的ES6!)构建一些有趣的东西。 首先,我们来看看启动文件。

Let’s break it down. We have a stylesheet named style.css. Then we go about defining a canvas element with 800 width and 800 height. Lastly, we have a script tag named app.js where all the magic happens. On that note, lets start doing stuff with our very own app.js.

让我们分解一下。 我们有一个名为style.css的样式表 然后,我们定义一个宽度为800,高度为800的canvas元素。 最后,我们有一个名为app.js脚本标签,其中发生了所有魔术。 关于这一点,让我们开始使用我们自己的app.js做事。

  • We start with selecting the canvas element in the first line and store the value in a const variable named canvas for simplicity.

    为了简单起见,我们从选择第一行的canvas元素开始,然后将值存储在名为canvas的const变量中。

  • Then we capture the context of the same canvas in 2D aspect and set it to the variable.

    然后,我们在2D方面捕获同一画布的上下文并将其设置为变量。

  • Set the width and height of the canvas to be the inner width of window and height respectively.

    将画布的宽度和高度分别设置为窗口的内部宽度和高度。

Now that we finally have our canvas in place, we move on to defining the most basic attributes of the canvas.

现在我们终于有了画布,接下来继续定义画布的最基本属性。

  • ctx.strokeStyle sets or returns the color, gradient, or pattern used for strokes. Yes, you read it right: the default color looks #BADASS.

    ctx.strokeStyle设置或返回用于笔触的颜色,渐变或图案。 是的,您没看错:默认颜色为#BADASS。

  • ctx.lineWidth sets or returns the current line width. We set it to 1, and we will come to this later on.

    ctx.lineWidth设置或返回当前线宽。 我们将其设置为1,稍后再进行讨论。

  • ctx.lineJoin sets or returns the type of corner created when two lines meet. We set it to round so that when two lines meet, we have a neat connection point.

    ctx.lineJoin设置或返回两条线相遇时创建的角的类型。 我们将其设置为圆形,以便当两条线相遇时,我们有一个整洁的连接点。

  • ctx.lineCap sets or returns the style of the end caps for a line. We set it to round so that when we don’t meet any other line, we still end up getting that same neat pipe figure depending on the width of stroke defined earlier.

    ctx.lineCap设置或返回一条线的端盖样式。 我们将其设置为圆形,以便当我们不遇到其他任何线时,仍然可以得到相同的整洁的管形图,具体取决于之前定义的笔划宽度。

Now that we have all these pieces in place, let’s see how we can go about actually drawing on the canvas.

现在我们已经准备好所有这些片段,让我们看看如何在画布上进行实际绘制。

First, we need to add some event listeners for the mouse movement on canvas, and then trigger a function that would actually draw something on the canvas. Let’s take a look at the additions we may have in the app.js file.

首先,我们需要为画布上的鼠标移动添加一些事件侦听器,然后触发一个实际上会在画布上绘制内容的函数。 让我们看一下我们可能在app.js文件中添加的内容。

Let’s break this down:

让我们分解一下:

  • We start by defining a variable called isDrwaing which would help us figure out if the user is actually trying to draw on the canvas or not. We’ll come back to this later on.

    我们首先定义一个名为isDrwaing的变量,该变量将帮助我们确定用户是否实际上在尝试在画布上绘画。 稍后我们将再次讨论。

  • For now, let’s have a function called draw which will be triggered and later on will be responsible for the whole action.

    现在,让我们有一个名为draw的函数,该函数将被触发,稍后将负责整个操作。

  • Lastly, we add a bunch for event listeners for various events just to make sure we capture the right events and only execute the draw function when it’s needed.

    最后,我们为各种事件添加了一些事件监听器,以确保捕获正确的事件并仅在需要时执行draw函数。

By declaring the isDrawing variable and setting its property to false, we set the initial state of the canvas as soon as the canvas element is loaded as not drawing. Then in every subsequent event listener, we use an inline function and change the value of the isDrawing function every time according to the type of event fired.

通过声明isDrawing变量并将其属性设置为false,我们在将canvas元素加载为未绘制后立即设置了画布的初始状态 。 然后,在随后的每个事件侦听器中,我们都使用内联函数并根据触发的事件的类型每次更改isDrawing函数的值。

At the start of the draw function, if the value of isDrawing is set to false, the function gets called off after encountering the return statement. If isDrawing is set to true, the draw function gets executed.

在draw函数的开始处,如果isDrawing的值设置为false,则在遇到return语句后该函数将被取消。 如果isDrawing设置为true,则执行draw函数。

绘图功能 (Draw Function)

Let’s expand on that draw function:

让我们扩展一下绘制函数:

  • We start by defining two variables globally, lastX, lastY, and set the initial value to be 0.

    我们首先全局定义两个变量lastX,lastY,并将初始值设置为0。

  • If you go to the console of your browser now, you’ll see that you have an enormous log of all the mouse movements you have been making. This MouseEvent object has some very important and useful properties:

    如果现在转到浏览器的控制台,您会发现您已经对所有鼠标移动进行了大量记录。 此MouseEvent对象具有一些非常重要和有用的属性:

We are only interested in the offsetX and offsetY property of this object.

我们只对该对象的offsetX和offsetY属性感兴趣。

  • With the very ctx.beginPath, we begin a path, or reset a current path. Both of which we want we do for every event triggered.

    使用ctx.beginPath,我们开始一个路径,或者重置当前路径。 我们都希望我们为触发的每个事件都做这两个事情。

  • ctx.moveTo moves the path to the specified point in the canvas, without creating a line. In our case this would be the lastX and lastY defined outside the function at global scope.

    ctx.moveTo将路径移动到画布中的指定点,而不创建线。 在我们的例子中,这将是在函数范围之外在全局范围内定义的lastX和lastY。

  • ctx.lineTo adds a new point and creates a line to that point from the last specified point in the canvas.

    ctx.lineTo添加一个新点,并从画布中最后指定的点到该点创建一条线。

  • ctx.stroke() actually draws the path you have defined — the real hard worker, guys!

    ctx.stroke()实际上绘制了您定义的路径-真正的辛勤工作,伙计们!

Inside the ctx.lineTo, we have leveraged the event property offsetX and offsetY to get the latest point of X and Y in the canvas only to draw a line with ctx.lineTo.

ctx.lineTo内,我们利用事件属性offsetXoffsetY来获取画布中X和Y的最新点,只是用ctx.lineTo画了一条线

We have pretty much everything in place. Every mouse event on the webpage draws a line on the canvas — but with some trouble and not much swag. So lets add some swag.

我们几乎已准备就绪。 网页上的每个鼠标事件都会在画布上画一条线,但是会带来一些麻烦,并且不会造成太多拖延。 因此,让我们添加一些赃物。

赃物! (Swag!)

For now, all the lines are drawn from the 0 and 0 point in canvas. We set this as the initial set of points to start drawing from when we load the canvas or even when we execute the draw function.

现在,所有线条都是从画布中的0和0点绘制的。 我们将其设置为初始点集,以便从加载画布甚至执行绘制功能时开始绘制。

Let’s fix this to have a better real time experience. If you think about it, the answer is very simple: every time the draw function is executed, we want the initial point to always be the offsetX and offsetY property of the MouseEvent object.

让我们对其进行修复,以获得更好的实时体验。 如果您考虑一下,答案很简单:每次执行draw函数时,我们都希望初始点始终是MouseEvent对象offsetXoffsetY属性。

By using ES6 array destructuring, we can reset the values of lastX and lastY to be the offsetX and offsetY property of the MouseEvent object. We can do this at the very end of the draw function. Lets take a look at the app.js file after adding some swag in it.

通过使用ES6数组解构,我们可以将lastX和lastY的值重置为MouseEvent对象的offsetX和offsetY属性。 我们可以在draw函数的最后完成此操作。 在添加一些赃物之后,让我们看一下app.js文件。

  • As soon as the mousemove event occurs, we fire the draw function. Then we go ahead and set the value of lastX and lastY in the draw function using ES6 destructuring.

    一旦发生mousemove事件,我们便会触发绘制函数。 然后,我们继续使用ES6解构在draw函数中设置lastX和lastY的值。

  • In the case of a mousedown event, first we change the inline function to block, as you can see, and then we again set the lastX and lastY values to be the event’s offset property. This is to make sure we have the line visible to us on the canvas while we are moving from one point to another point in canvas.

    对于mousedown事件,首先,我们将内联函数更改为block,如您所见,然后再次将lastX和lastY值设置为事件的offset属性。 这是为了确保当我们从画布上的一个点移动到另一点时,该线条在画布上对我们可见。

Let’s make it colorful and add some dynamics in the stroke.

让我们使其色彩丰富,并在笔触中添加一些动态效果。

HOLY MOLY!!

天哪!

That is lot to handle, but let’s break it down.

要处理很多,但让我们对其进行分解。

  • I defined a new variable called hue and set its property to 0.

    我定义了一个名为hue的新变量,并将其属性设置为0。

  • If you don’t already know about hue and why is it awesome, head over to Google and give it a try, or just click here.

    如果您还不了解色相及其为何如此出色,请前往Google尝试一下,或单击此处

In its simplest form, hsl lets us use the same rainbow of colors ranging between 0 and 360. Each number has a lightness and alpha value. Defining hsl looks something like this: hsl(173, 99%, 50%). Here number 173 represents a color — 99% is the lightness and 50% is the alpha value.

以最简单的形式,hsl允许我们使用0到360之间的相同彩虹色。每个数字都有亮度和alpha值。 定义hsl看起来像这样:hsl(173,99%,50%)。 此处的数字173代表一种颜色-亮度为99%,alpha值为50%。

Again, by using some awesome ES6 backticks, we can leverage the hsl and influence it by doing something like this:

同样,通过使用一些很棒的ES6反引号,我们可以利用hsl并通过执行以下操作来影响它:

ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`

ctx.strokeStyle = `hsl(${hue}, 100%, 50%)`

as we did on the line 7 in the above gist.

就像我们在上述要点中的第7行一样。

Next we increase the value of the hue variable which changes the color of the stroke with every mousemove event. Once the hue value has been incremented until 360, we reset the value of hue to be 0 on line 14 of the above gist. But even if we don’t do this, we will still have the same result. Even so, let’s just do the right thing. :D lol

接下来,我们增加hue变量的值,该变量在每次mousemove事件时都会更改笔触的颜色。 一旦色相值增加到360,我们将在上述要点的第14行上将色相值重置为0。 但是,即使我们不这样做,我们仍然会得到相同的结果。 即使这样,我们还是要做正确的事情。 :D哈哈

if(hue>360){ hue =0 }

if(hue>360){ hue = 0 }

Next, let’s add some dynamics to the width of the stroke being drawn every time, like this:

接下来,让我们为每次绘制的笔划宽度添加一些动态效果,如下所示:

if(ctx.lineWidth>=75 || ctx.lineWidth<=1){ direction = !direction;}

if(ctx.lineWidth>=75 || ctx.lineWidth<=1){ direction = !direct离子;}

if(direction){ ctx.lineWidth++} else { ctx.lineWidth = 0}

if(direction){ ctx.lineWidth++ } else { ctx.lineWidth = 0 }

All we did here is first check if the current lineWidth is bigger than 75 or less than 1. If it is, then we reverse the value of the variable direction which is set to true as default.

我们在这里所做的只是首先检查当前的lineWidth是否大于75或小于1。如果是,则反转可变方向的值,该值默认设置为true。

Next we check if the value of the variable direction is true. If it is, then increment the value of lineWidth by 1, else reset the lineWidth to be 0.

接下来,我们检查可变方向的值是否为true。 如果是,则将lineWidth的值增加1,否则将lineWidth重置为0。

That was not very much JavaScript. You should have your pretty canvas ready by now if you have been following along properly.

那不是很多JavaScript。 如果您一直遵循正确的方法,那么现在应该准备好漂亮的画布。

Let’s take a quick look at what the final file structure looks like. Since we only changed the app.js file, I’ll show you only that, as index.html remains almost unchanged since the beginning.

让我们快速看一下最终文件的结构。 由于我们仅更改了app.js文件,因此仅向您显示,因为index.html自开始以来几乎保持不变。

This is just the tip of the iceberg when thinking about the total power of the canvas element combined with JavaScript. I would encourage you to do a little more research and make the canvas look even better. Maybe add a couple of button’s to clear the screen, or maybe select a specific color to draw on canvas. So many options!

在考虑canvas元素与JavaScript结合使用的全部功能时,这只是冰山一角。 我鼓励您多做一些研究,使画布看起来更好。 也许添加几个按钮来清除屏幕,或者选择一种特定的颜色在画布上绘制。 这么多的选择!

All I am saying is there are million ways to make this better. I’ll definitely update the story if I have anything worth updating.

我要说的是,有数百万种方法可以改善这种情况。 如果我有任何值得更新的内容,我一定会更新。

Lastly, I’d like to leave you with a video of how the canvas would look like at the very end.

最后,我想给您留下一段视频,介绍一下画布的外观。

Hope you enjoyed reading all this! Any comments or suggestions to improve or discuss this further would really be appreciated. You can connect with me on twitter and linkedIn as well.

希望您喜欢阅读所有这些内容! 任何对改进或讨论此问题的意见或建议将不胜感激。 您也可以在twitterlinkedIn上与我联系。

翻译自: https://www.freecodecamp.org/news/sunday-with-canvas-element-and-javascript-38ae80e0fbeb/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值