机械制图国家标准的绘图模板
The theme for week #5 of the Weekly Coding Challenge is:
每周编码挑战第5周的主题是:
创建绘图应用程序 (Creating a Drawing Application)
This is the first application that we are building in the #weeklyCodingChallenge program. So far we have built smaller projects, so this is pretty exciting if you ask me! ?
这是我们在#weeklyCodingChallenge程序中构建的第一个应用程序。 到目前为止,我们已经建立了较小的项目,因此如果您问我,这将非常令人兴奋! ?
In this article we’ll use p5js, a drawing library, to build a Drawing Application:
在本文中,我们将使用绘图库p5js来构建绘图应用程序 :
Check out the CodePen here:
在此处查看CodePen:
If you want to learn more about p5js and what it does, you can visit their official website. Basically, I am using it because it works very well on top of the browser’s canvas element by providing a clear API.
如果您想了解更多有关p5js及其功能的信息,可以访问其官方网站 。 基本上,我使用它是因为它通过提供一个清晰的API在浏览器的canvas元素上很好地工作。
HTML (The HTML)
As you can notice in the example above, on the left side of the screen we have a .sidebar
. We'll put inside it our 'tools' - a color
picker, a weight
selector and the clear
button (trashcan icon):
您可以在上面的示例中注意到,在屏幕的左侧,我们有一个.sidebar
。 我们将在其中放入“工具”-一个color
选择器,一个weight
选择器和一个clear
按钮(垃圾桶图标):
<div class="sidebar"><ul><li><label for="color">Color:</label><input type="color" id="color" /></li><li><label for="weight">Stroke:</label><input type="number" id="weight" min="2" max="200" value="3" /></li><li><button id="clear"><i class="fa fa-trash"></i></button></li></ul>
</div>
CSS (The CSS)
Using CSS we’ll move the .sidebar
and everything that’s inside it in the left side. We will style it a little bit to make it look nicer (nothing fancy, basic CSS):
使用CSS,我们将.sidebar
及其内部的所有内容移到左侧。 我们将对其进行一些样式设置,使其看起来更好(没什么花哨的,基本CSS):
.sidebar {background-color: #333;box-shadow: 0px 0px 10px rgba(30, 30, 30, 0.7);color: #fff;position: absolute;left: 0;top: 0;height: 100vh;padding: 5px;z-index: 1000;
}.sidebar ul {display: flex;justify-content: center;align-items: flex-start;flex-direction: column;list-style-type: none;padding: 0;margin: 0;height: 100%;
}.sidebar ul li {padding: 5px 0;
}.sidebar input,
.sidebar button {text-align: center;width: 45px;
}.sidebar li:last-of-type {margin-top: auto;
}.sidebar button {background-color: transparent;border: none;color: #fff;font-size: 20px;
}.sidebar label {display: block;font-size: 12px;margin-bottom: 3px;
}
Now for the important part…
现在重要的是……
JS / P5JS (The JS / P5JS)
As you might have noticed, we haven’t added a canvas
element into our HTML since p5js will create it for us.
您可能已经注意到,我们没有在HTML中添加canvas
元素,因为p5js会为我们创建它。
There are two important functions which we’ll use from the p5js library:
我们将在p5js库中使用两个重要的函数:
setup — is called once when the program starts. It’s used to define initial environment properties such as screen size and background color.
设置 —在程序启动时被调用一次。 它用于定义初始环境属性,例如屏幕尺寸和背景色。
draw —is called directly after
setup()
. Thedraw()
function continuously executes the lines of code contained inside its block.draw —在
setup()
之后直接调用。draw()
函数连续执行其块内包含的代码行。
function setup() {// create a canvas which is full width and heightcreateCanvas(window.innerWidth, window.innerHeight);// Add a white background to the canvasbackground(255);
}function draw() {}
Before moving forward, let’s stop for a moment and see what we want to achieve.
在继续前进之前,让我们先停下来看看我们要实现的目标。
So, basically, we want to add a mousepressed
eventListener to the canvas
that will start 'drawing' a shape inside it as long as the mouseIsPressed
.
所以,基本上,我们要添加一个mousepressed
事件监听到canvas
,将启动“绘制”里面的形状,只要mouseIsPressed
。
We’ll create an array of points which we’re going to use to create a path
(or a shape) using the beginShape and endShape methods to draw this shape inside the canvas. The shape is going to be constructed by connecting a series of vertices (see vertex for more information).
我们将使用BeginShape和endShape方法创建一个点数组,这些点将用于创建path
(或形状)以在画布内绘制该形状。 将通过连接一系列顶点来构造形状(有关更多信息,请参见顶点 )。
As we want this shape to be re-drawn every time, we’ll put this code inside the draw
method:
由于我们希望每次都重新绘制此形状,因此将这段代码放入draw
方法中:
const path = [];function draw() {// disabled filling geometry - p5js functionnoFill();if (mouseIsPressed) {// Store the location of the mouseconst point = {x: mouseX,y: mouseY};path.push(point);}beginShape();path.forEach(point => {// create a vertex at the specified locationvertex(point.x, point.y);});endShape();
}
As you can see, p5js has a mouseIsPressed flag that we can use to detect when the mouse buttons are pressed.
如您所见,p5js有一个mouseIsPressed标志,我们可以用来检测何时按下鼠标按钮。
Everything might look good so far, but there is a big issue. Once the mouse button is released and we try to draw another shape, the last point from the previous shape will be connected to the first point of the new shape. This is definitely not what we want, so we need to change our approach a little bit.
到目前为止,一切看起来都不错,但是有一个大问题。 释放鼠标按钮并尝试绘制其他形状后,先前形状的最后一个点将连接到新形状的第一个点。 这绝对不是我们想要的,因此我们需要稍微改变一下方法。
Instead of having one array of points (the path array), we’ll create a pathsarray
and we are going to store all the paths
inside it. Basically, we’ll have a double array with points. Also, for this, we will need to keep track of the currentPath
while the mouse is still pressed. We’ll reset this array once the mouse button is pressed again. Confusing? ? Let’s see the code and I bet that it will become clearer:
除了创建一个点数组(路径数组)以外,我们将创建一个pathsarray
,并将所有paths
存储在其中。 基本上,我们将有一个带有点的双精度数组。 同样,为此,我们将需要在仍然按下鼠标的同时跟踪currentPath
。 再次按下鼠标按钮后,我们将重置此数组。 令人困惑? ? 让我们看一下代码,我敢打赌它将变得更加清晰:
const paths = [];
let currentPath = [];function draw() {noFill();if (mouseIsPressed) {const point = {x: mouseX,y: mouseY};// Adding the point to the `currentPath` arraycurrentPath.push(point);}// Looping over all the paths and drawing all the points inside thempaths.forEach(path => {beginShape();path.forEach(point => {stroke(point.color);strokeWeight(point.weight);vertex(point.x, point.y);});endShape();});
}// When the mouse is pressed, this even will fire
function mousePressed() {// Clean up the currentPathcurrentPath = [];// Push the path inside the `paths` arraypaths.push(currentPath);
}
I also added some comments in the code above, make sure you check them out.
我还在上面的代码中添加了一些注释,请确保将它们签出。
The mousePressed function is called once after every time a mouse button is pressed — p5js stuff! ?
每次按下鼠标按钮时都会调用一次 mousePressed 函数 -p5js的东西! ?
Great! Now we can draw individual shapes in our canvas! ?
大! 现在我们可以在画布上绘制单个形状了! ?
The last thing to do is to hook up those buttons that we created in the HTML and use the values that are inside them to style the shape:
最后要做的是连接我们在HTML中创建的按钮,并使用其中的值来设置形状的样式:
const colorInput = document.getElementById('color');
const weight = document.getElementById('weight');
const clear = document.getElementById('clear');function draw() {noFill();if (mouseIsPressed) {const point = {x: mouseX,y: mouseY,// storing the color and weights provided by the inputs for each pointcolor: colorInput.value,weight: weight.value};currentPath.push(point);}paths.forEach(path => {beginShape();path.forEach(point => {// using the color and the weight to style the strokestroke(point.color);strokeWeight(point.weight);vertex(point.x, point.y);});endShape();});
}clear.addEventListener('click', () => {// Remove all the pathspaths.splice(0);// Clear the backgroundbackground(255);
});
And with this, we have finished our little application! Yay! ?
至此,我们完成了我们的小应用程序! 好极了! ?
整个JS代码 (The entire JS code)
const colorInput = document.getElementById('color');
const weight = document.getElementById('weight');
const clear = document.getElementById('clear');
const paths = [];
let currentPath = [];function setup() {createCanvas(window.innerWidth, window.innerHeight);background(255);
}function draw() {noFill();if (mouseIsPressed) {const point = {x: mouseX,y: mouseY,color: colorInput.value,weight: weight.value};currentPath.push(point);}paths.forEach(path => {beginShape();path.forEach(point => {stroke(point.color);strokeWeight(point.weight);vertex(point.x, point.y);});endShape();});
}function mousePressed() {currentPath = [];paths.push(currentPath);
}clear.addEventListener('click', () => {paths.splice(0);background(255);
});
Also, make sure that you import the p5js
file in your html too before importing this js
file.
另外,在导入此js
文件之前,请确保p5js
html中导入p5js
文件。
结论 (Conclusion)
I hope that you liked this drawing app that we’ve built. There are a bunch of functionalities that could be added to this app and I challenge you to let your creative mind to come up with new ideas! ?
希望您喜欢我们构建的此绘图应用程序。 有很多功能可以添加到此应用程序中,我挑战您让您的创意思维提出新想法! ?
What if you could save the drawing as an image (.png
or .jpg
)? ? (you can do this with the p5js library).
如果可以将图形另存为图像( .png
或.jpg
)怎么办? ? (您可以使用p5js库执行此操作)。
As of now, we are only checking the mouse
events. Maybe you could make it work on mobile, too, by figuring out the touch
events? The sky is the limit with the amount of functionalities that could be added to this app!
截至目前,我们仅检查mouse
事件。 通过弄清touch
事件,也许您也可以使其在移动设备上工作? 天空是可以添加到此应用程序的功能数量的限制!
I’d love to see what you are going to build! Tweet me @florinpop1705 with your creation!
我很想看看你要建立什么! 用您的创作给我@ florinpop1705发推文 !
You might also like one of the other challenges from the Weekly Coding Challenge program. Check them out here.
您可能还会喜欢“每周编码挑战”计划中的其他挑战之一。 在这里查看它们。
See ya next time! Happy Coding! ?
下次见! 编码愉快! ?
Originally published at www.florin-pop.com.
最初在www.florin-pop.com上发布。
翻译自: https://www.freecodecamp.org/news/how-to-build-a-drawing-app-with-p5js-9b8d16e9364a/
机械制图国家标准的绘图模板