nw.js 调用驱动程序_使用NW.js创建照片发现应用程序(第1部分)

nw.js 调用驱动程序

NW.js (formerly known as Node Webkit) is a framework for creating cross-platform desktop applications using HTML, CSS, and JavaScript. In this tutorial, we're going to a desktop application using NW.js, and through the tutorial give you a good understanding of how NW.js works under the hood.

NW.js (以前称为Node Webkit)是用于使用HTML,CSS和JavaScript创建跨平台桌面应用程序的框架。 在本教程中,我们将使用NW.js进入桌面应用程序,并且通过本教程,您可以很好地了解NW.js的工作原理。

This tutorial is aimed at anyone who knows HTML, CSS, and JavaScript. Experience with Node.js is not required.. We're going to split this tutorial into 2 parts! Here's part 1.

本教程面向任何了解HTML,CSS和JavaScript的人。 不需要具有Node.js经验。 。 我们将本教程分为两部分! 这是第1部分。

我们将要建立的 (What we're going to build)

Step 15 Window Toolbar

We're going to make a photo browsing app called Lens. It will allow you to browse photos that exist inside a folder on your computer, take a closer look at one photo at a time, apply colour filters, and save the altered photo to your computer.

我们将制作一个名为Lens的照片浏览应用程序。 它将允许您浏览计算机文件夹中存在的照片,一次仔细查看一张照片,应用滤色器,然后将更改后的照片保存到计算机中。

先决条件 (Prerequisites)

If you want to follow the tutorial and build the desktop app, you'll need the following:

如果要遵循本教程并构建桌面应用程序,则需要满足以下条件:

  • Any computer running either Mac OS X, Windows, or Linux

    任何运行Mac OS X,Windows或Linux的计算机
  • Node.js (see installing Node.js)

    Node.js(请参阅安装Node.js)

安装Node.js (Installing Node.js)

在Mac OS X或Linux上 (On Mac OS X or Linux)

I would recommend installing Node.js via a tool called NVM (Node.js version manager). It allows you to install different versions of Node.js, and switch between them easily. You can find the installation instructions at https://github.com/creationix/nvm.

我建议通过称为NVM (Node.js版本管理器)的工具安装Node.js。 它允许您安装不同版本的Node.js ,并在它们之间轻松切换。 您可以在https://github.com/creationix/nvm上找到安装说明。

在Windows上 (On Windows)

The setup.exe file from the Node.js website is fine. There is a version of NVM for Windows, but I haven't been successful in getting that to work off the bat.

来自Node.js网站的setup.exe文件很好。 有适用于Windows的NVM版本,但我无法成功地将其付诸实践。

入门 (Getting started)

Assuming that you have Node.js installed, we can start by installing the NW.js module. Type the following command into your command line terminal:

假设您已安装Node.js,我们可以从安装NW.js模块开始。 在命令行终端中键入以下命令:

npm install -g nw

For those new to Node.js, npm is Node's package manager, and allows you to install modules to use in your projects. The -g flag tells NPM to install nw.js as a global module, meaning that it will be available to all of the Node.js projects on your computer, and allow you to use the "nw" command on the terminal to execute loading a project as a desktop app.

对于Node.js的新用户来说,npm是Node的软件包管理器,它允许您安装要在项目中使用的模块。 -g标志告诉NPM将nw.js作为全局模块安装,这意味着它将对您计算机上的所有Node.js项目可用,并允许您在终端上使用“ nw”命令执行加载作为桌面应用程序的项目。

You'll see logging information output to the terminal showing the process of installing the module. If it was successful, you should see something like this

您将看到输出到终端的日志信息,显示安装模块的过程。 如果成功,您应该会看到类似这样的信息

Pre Install NW.js

If however there is an error, please let me know in the comments, or alternatively search for the error message on Google to see related Stack Overflow posts or Github issues that might offer a way to resolve the issue.

但是,如果有错误,请在评论中让我知道,或者在Google上搜索错误消息,以查看相关的Stack Overflow帖子或Github问题,这些问题可能会提供解决问题的方法。

Once we have NW.js installed on our computer, the next thing we want to do is to create the initial skeleton for our application. Using the terminal command prompt, let's create a folder for our application's files called "lens", and change the current working directory to that folder:

一旦我们在计算机上安装了NW.js,接下来要做的就是为我们的应用程序创建初始框架。 使用终端命令提示符,让我们为应用程序的文件创建一个名为“ lens”的文件夹,并将当前工作目录更改为该文件夹:

mkdir lens
cd lens

Inside of the folder, we need just 2 files to create a bare skeleton NW.js app; an index.html file, and a package.json file. The package.json file is a manifest file that contains configuration information about the app, such as its name, version, and what file it loads when starting the application. It looks something like this:

在该文件夹内,我们只需要2个文件即可创建一个裸露的骨架NW.js应用程序; 一个index.html文件和一个package.json文件。 package.json文件是一个清单文件,其中包含有关应用程序的配置信息,例如其名称,版本以及启动应用程序时加载的文件。 看起来像这样:

{
    "name": "Lens",
    "version": "1.0.0",
    "main": "index.html"
}

Save this file inside of the lens folder, under the filename package.json. Next, we will create the index.html file that will be displayed then the app runs. Create a file called index.html in the lens folder, and type in the following HTML:

将此文件保存在lens文件夹内,文件名package.json 。 接下来,我们将创建index.html文件,该文件将在应用程序运行时显示。 在lens文件夹中创建一个名为index.html的文件,然后键入以下HTML:

<html>
    <head>
        <title>Lens</title>
    </head>
    <body>
        <h1>Lens, the photo app</h1>
    </body>
</html>

Once you have saved this file to the computer, we can now run this code as a desktop application.

将文件保存到计算机后,我们现在可以将此代码作为桌面应用程序运行。

Going back to the command line terminal, make sure that you are in the lens folder, and run the following command:

返回命令行终端,确保您位于lens文件夹中,然后运行以下命令:

nw

When you do this, you should expect to see an application boot, and the screen should look something like this:

执行此操作时,您应该期望看到应用程序启动,并且屏幕应该看起来像这样:

Step 1 Screenshot

Some of you may be looking at this and thinking "this looks like a web page in a browser, embedded in a desktop app", and to some extent that is correct - NW.js is a combination of Google Chrome's Blink web browser rendering engine and IO.js*, along with some Operating System bindings. The combination of these technologies is very powerful, which we will explore later on in the tutorial.

你们中的某些人可能正在考虑这个问题,并认为“ 这看起来像是浏览器中的网页,已嵌入桌面应用程序中 ”,并且在某种程度上是正确的-NW.js是Google Chrome浏览器的Blink网络浏览器呈现引擎的组合和IO.js *,以及一些操作系统绑定。 这些技术的组合非常强大,我们将在本教程的后面部分中进行探讨。

充实用户旅程 (Fleshing out the user journey)

Now is a good time to look at the user journey of the desktop application:

现在是查看桌面应用程序的用户历程的好时机:

NW.js wireframes

We start by asking the user to select a folder containing their photos. This is because even though we could detect their OS and infer what the path to their photos folder is, we can't guarantee that it is where they keep their photos. When the user clicks on the button and selects a folder, the app will display the photos inside of that folder in a grid fashion.

我们首先要求用户选择一个包含他们照片的文件夹。 这是因为即使我们可以检测到他们的操作系统并推断出他们的照片文件夹的路径是什么,我们也不能保证它是存放照片的位置。 当用户单击按钮并选择一个文件夹时,该应用程序将以网格方式显示该文件夹内的照片。

Let's start by fleshing out the initial app screen's user interface first. We will want to add some HTML for the button and label, some CSS to adjust the layout and style of the screen, and some JavaScript to handle events like clicking on a button and loading a folder's photos.

首先让我们充实初始应用程序屏幕的用户界面。 我们将要为按钮和标签添加一些HTML,为调整屏幕的布局和样式添加一些CSS,并为处理诸如单击按钮和加载文件夹的照片之类的事件添加一些JavaScript。

We'll start by adding some HTML for the "select Folder" button in the middle of the 1st app screen. Inside of the body tag, remove the h1 tag, and replace it with the following HTML:

我们将在第一个应用程序屏幕的中间,为“选择文件夹”按钮添加一些HTML。 在body标签内部,删除h1标签,然后将其替换为以下HTML:

<div id="select_folder">
    <span>Select a folder containing photos</span>
</div>

With this in place, we now need to modify the layout and styling the HTML with CSS. To do this, add the following link tag inside of the head section of the index.html file, after the title tag:

完成此操作后,我们现在需要修改布局并使用CSS设置HTML样式。 为此,请在title标签之后的index.html文件的头部内添加以下链接标签:

<link rel="stylesheet" href="app.css" />

We can now add some CSS to the app.css, and review the results. In the app.css file, add the following code:

现在,我们可以将一些CSS添加到app.css ,并查看结果。 在app.css文件中,添加以下代码:

body {
    background-color: #222;
    font-family: Arial, "Helvetica Neue"
}

/* 1st screen */

#select_folder {
    text-shadow: 1px 1px 1px rgba(0,0,0,0.3);
    text-align: center;
    margin: 0 auto;
    position: relative;
    width: 16em;
    top: 40%;
    padding: 1em;
    background: #FF582E;
    border-radius: 2em;
    border: solid 1px #FF582E;
    color: white;
}

#select_folder:hover {
    box-shadow: 0px 0px 20px #FF582E;
    cursor: pointer;
}

The app is now beginning to look a bit nicer:

该应用程序现在开始看起来更好一些:

Lens Screen 1 with Styling

The next step is to make clicking the button bring up a dialog box to select a folder. For this, we're going to add a bit of HTML, and some JavaScript to achieve the right behaviour. Below the body tag, add the following snippet of HTML:

下一步是单击按钮,弹出对话框选择文件夹。 为此,我们将添加一些HTML和一些JavaScript以实现正确的行为。 在body标签下面,添加以下HTML代码段:

<input type="file" nwdirectory id="folderSelector"/>

The input tag is one that you use for selecting files, with the exception that the 'nwdirectory' attribute tells the input file dialog to accept folders instead of files. We insert this into the HTML so that we can programmatically trigger it when the button is clicked, and bring up the folder select dialog. Next, we'll want to add some CSS to hide the input field out of sight:

输入标签是用于选择文件的标签,但'nwdirectory'属性告诉输入文件对话框接受文件夹而不是文件。 我们将其插入HTML,以便我们可以在单击按钮时以编程方式触发它,并弹出文件夹选择对话框。 接下来,我们要添加一些CSS以隐藏输入字段:

#folderSelector {
    display: none;
}

Now, we'll want to add some JavaScript to the app. We'll want to add a script tag to the HTML. Under the link tag in the head section of the index.html file, add the following HTML:

现在,我们要向该应用程序添加一些JavaScript。 我们将要向HTML添加脚本标签。 在index.html文件的头部的链接标签下,添加以下HTML:

<script src="app.js"></script>

Next, let's create an empty app.js file inside of the lens folder. In here, we will add some JavaScript that does the following:

接下来,让我们在lens文件夹中创建一个空的app.js文件。 在这里,我们将添加一些执行以下操作JavaScript:

  1. Intercepts any clicks on the div element with the id of "select_folder".

    拦截ID为“ select_folder”的div元素上的所有单击。
  2. When a click occurs, it will programmatically trigger the click event on the input tag, which will load the open folder dialog.

    发生单击时,它将以编程方式触发输入标签上的click事件,这将加载打开的文件夹对话框。
  3. If the user cancels selecting a folder, we take no further action.

    如果用户取消选择文件夹,我们将不采取进一步行动。
  4. If the user selects a folder, we pass the folder path onto a function that will later on load all of the photos in that folder, and display them in the grid view.

    如果用户选择一个文件夹,我们会将文件夹路径传递到一个函数上,该函数稍后将在该文件夹中加载所有照片,并在网格视图中显示它们。

Let's start by writing some code to ask the user for the folder containing their photos. In the lens folder, create an empty file called app.js, and insert the following script tag in the index.html file, in the head section of the html:

让我们从编写一些代码开始,向用户询问包含其照片的文件夹。 在lens文件夹中,创建一个名为app.js的空文件,并将以下脚本标记插入html头部的index.html文件中:

<script src="app.js"></script>

This will load the app.js file when the application loads. Next, we want to add some code in the app.js file that handles asking the user for the folder containing their photos. In the app.js file, add the following code:

当应用程序加载时,这将加载app.js文件。 接下来,我们要在app.js文件中添加一些代码,以处理向用户询问包含其照片的文件夹的问题。 在app.js文件中,添加以下代码:

'use strict';

function bindSelectFolderClick () {
    var button = document.querySelector('#select_folder');
    button.addEventListener('click', function () {
        alert('clicked on the button');
    });
}

// Runs when the browser has loaded the page
window.onload = function () {
    bindSelectFolderClick();
};

This initial JavaScript takes care of listening for clicks on the "select folder" button, and for now emits an alert with a message when the button is clicked. Save the file, give it a quick try to check that it works, and now we can bind on opening the folder dialog.

此初始JavaScript负责侦听“选择文件夹”按钮上的单击,现在单击该按钮时会发出带有消息的警报。 保存文件,尝试快速检查它是否可以正常工作,现在我们可以在打开文件夹对话框时进行绑定了。

Add this JavaScript above the bindSelectFolderClick function:

将此JavaScript添加到bindSelectFolderClick函数上方:

function openFolderDialog () {
    var inputField = document.querySelector('#folderSelector');
    inputField.addEventListener('change', function () {
        var folderPath = this.value;
        alert('Folder path is ' + folderPath);
    }, false);
    inputField.click();
}

And in the bindSelectFolderClick function, replace this line:

然后在bindSelectFolderClick函数中,替换以下行:

alert('clicked on the button');

With this:

有了这个:

openFolderDialog();

Save the file, reload the app, and you'll see that when you click on the button, the select folder dialog will appear. Once you've selected a folder, it will display the folder path in an alert dialog. Getting to this stage means that we are in a position to start finding out what photos exist in that folder, and start to display the photos.

保存文件,重新加载应用程序,然后单击按钮,将显示“选择文件夹”对话框。 选择文件夹后,它将在警报对话框中显示文件夹路径。 进入此阶段意味着我们可以开始查找该文件夹中存在的照片,并开始显示照片。

查找照片 (Finding the photos)

Now that we have a folder path, we can begin the process of finding all of the photos inside of that folder, and displaying them in the application. Taking a quick look bak at the user journey, we see that the select folder disappears when we select a folder, and a grid view of the photos in the folder appears in the app. We'll need to do the following:

现在我们有了文件夹路径,我们可以开始查找该文件夹内的所有照片并将其显示在应用程序中的过程。 快速浏览一下用户旅程,我们发现选择文件夹时选择文件夹消失了,并且文件夹中照片的网格视图出现在应用程序中。 我们需要执行以下操作:

  1. Hide the select folder button

    隐藏选择文件夹按钮
  2. Get a list of all the files that are in the folder.

    获取该文件夹中所有文件的列表。
  3. Filter out non-images files and directories from the list

    从列表中过滤掉非图像文件和目录
  4. Show the photo grid view, with each grid item displaying a photo

    显示照片网格视图,每个网格项目都显示一张照片

Before we focus on hiding the select folder button, we'll adjust the existing functions first. Now that we have a folder path, we're going to want to pass that variable onto another function that will handle finding all of the files that exist in that folder. Ideally we want to pass this value to a function that isn't necessarily defined inside of that function, but can be passed to the function when it is called. Let's modify the openFolderDialog function's code to look like this:

在专注于隐藏选择文件夹按钮之前,我们将首先调整现有功能。 现在我们有了文件夹路径,我们将要将该变量传递到另一个函数,该函数将处理查找该文件夹中存在的所有文件。 理想情况下,我们希望将此值传递给不一定在该函数内部定义的函数,但可以在调用该函数时传递给该函数。 让我们将openFolderDialog函数的代码修改为如下所示:

function openFolderDialog (cb) {
    var inputField = document.querySelector('#folderSelector');
    inputField.addEventListener('change', function () {
        var folderPath = this.value;
        cb(folderPath);
    });
    inputField.click();
}

The function now receives a variable called cb, which is a common abbreviation for callback. The "cb" variable is a function that will receive the folderPath variable. This is a good way to be able to have functions pass data onto other functions without having to hard-code function references inside a function, helping to keep function coupling low.

该函数现在接收一个名为cb的变量,这是callback的常见缩写。 “ cb”变量是将接收folderPath变量的函数。 这是使函数能够将数据传递到其他函数的一种好方法,而不必在函数内部对函数引用进行硬编码,从而有助于将函数耦合保持在较低水平。

We now need to find places in our code where the openFolderDialog function is called, and change them to receive a callback function. Inside of the bindSelectFolderClick function there is the only call to that function, so we'll need to adjust that code to look like this:

现在,我们需要在代码中找到调用openFolderDialog函数的位置,并对其进行更改以接收回调函数。 在bindSelectFolderClick函数内部,只有对该函数的调用,因此我们需要调整该代码以使其看起来像这样:

function bindSelectFolderClick (cb) {
    var button = document.querySelector('#select_folder');
    button.addEventListener('click', function () {
        openFolderDialog(cb);
    });
}

The bindSelectFolderClick function knows explicitly about the openFolderDialog function, and will pass on the callback function to it that it receives when it is called. This means that we also need to look at the code inside of the window.onload function, and get that to provide a callback function to the bindSelectFolderClick function. We adjust the window.onload function to look like this:

bindSelectFolderClick函数明确了解openFolderDialog函数,并将回调函数传递给调用它时收到的回调函数。 这意味着我们还需要查看window.onload函数内部的代码,并获取该代码以为bindSelectFolderClick函数提供回调函数。 我们将window.onload函数调整为如下所示:

// Runs when the browser has loaded the page
window.onload = function () {
    bindSelectFolderClick(function (folderPath) {
        console.log(folderPath);
    });
};

For now we simply log the folder path in the console, but we will later pass a new function that will find all of the files and identify just the ones that are images. Now, we can add a function that will hide the "select folder" button once we've selected a folder. Add the following function before the window.onload function:

现在,我们仅在控制台中记录文件夹路径,但是稍后我们将传递一个新功能,该功能将查找所有文件并仅识别图像文件。 现在,我们可以添加一个函数,一旦选择了文件夹,该函数将隐藏“选择文件夹”按钮。 在window.onload函数之前添加以下函数:

function hideSelectFolderButton () {
    var button = document.querySelector('#select_folder');
    button.style.display = 'none';
}

This function will find the div element for the "select folder" button, and hide it via modifying the element's display property. Let's modify the window.onload function so that it calls this function when a folder is selected:

此函数将为“选择文件夹”按钮找到div元素,并通过修改元素的display属性将其隐藏。 让我们修改window.onload函数,以便在选择文件夹时调用此函数:

// Runs when the browser has loaded the page
window.onload = function () {
    bindSelectFolderClick(function (folderPath) {
        hideSelectFolderButton();
        console.log(folderPath);
    });
};

If we save the file, and test it out, we can see that the "select folder" button is hidden when a folder is selected, and that we will see the folder path logged in the developer tools of the app. Here, we can now focus on getting the files for that folder path, and start to see the power of NW.js - its ability to load Node.js modules directly in the same place as our JavaScript.

如果我们保存文件并对其进行测试,则可以看到选择文件夹后“选择文件夹”按钮处于隐藏状态,并且该文件夹的路径将记录在应用程序的开发人员工具中。 在这里,我们现在可以集中精力获取该文件夹路径的文件,并开始看到NW.js的强大功能-NW.js能够将Node.js模块直接加载到与JavaScript相同的位置。

获取文件列表 (Getting a list of files)

We want to create a function that will receive a folder path, and return a list of files. We can do this using Node.js using the File System module that is part of the Node.js' core API. We need to load the module first, and then call a public function on it called "readdir". At the top of the app.js file, add the following code after the "use strict" linting declaration:

我们想要创建一个函数,该函数将接收文件夹路径并返回文件列表。 我们可以使用Node.js核心API一部分中的文件系统模块,通过Node.js做到这一点。 我们需要先加载模块,然后在其上调用一个名为“ readdir”的公共函数。 在app.js文件的顶部,在“使用严格”的插入声明之后添加以下代码:

// Dependencies
var fs = require('fs');

This snippet of code tells the app to load Node.js' File System module. We can then use this module in a function that will find all of the image files in a given folder. In the same file but just before the window.onload function, add the following code:

此代码段告诉应用程序加载Node.js的文件系统模块。 然后,我们可以在可以在给定文件夹中找到所有图像文件的函数中使用此模块。 在同一文件中,但在window.onload函数之前,添加以下代码:

function findAllImageFiles (folderPath, cb) {
    fs.readdir(folderPath, function (err, files) {
        if (err) { return cb(err, null); }
        cb(null, files);
    });
}

The findAllImageFiles function receives a folder path, and currently finds all of the files in that folder and passes them onto the callback function, along with an error in case an error occurs finding files in that folder. If we then modify the window.onload function to pass the folder path onto the findAllImageFiles function, we can begin to see what kind of data we are dealing with. Alter the window.onload function to look like this:

findAllImageFiles函数接收一个文件夹路径,当前会找到该文件夹​​中的所有文件,并将它们连同错误一起传送到回调函数中,以防在该文件夹中找到文件时发生错误。 如果然后修改window.onload函数以将文件夹路径传递到findAllImageFiles函数,我们可以开始查看正在处理的数据类型。 更改window.onload函数,使其看起来像这样:

// Runs when the browser has loaded the page
window.onload = function () {
    bindSelectFolderClick(function (folderPath) {
        hideSelectFolderButton();
        findAllImageFiles(folderPath, function (err, files) {
            console.log(err);
            console.log(files);
        });
    });
};

With the changes saved, we can take a look at what the files list looks like. Run the app using nw on the command line, select a folder containing pictures, and if you open the console in the app's developer tools, you should expect to see something like this:

保存更改后,我们可以查看文件列表的外观。 在命令行上使用nw运行该应用程序,选择一个包含图片的文件夹,如果您在应用程序的开发人员工具中打开控制台,则应该会看到以下内容:

Step 6 List of Files

You can see here that the files in the pictures folder contains only the names of the files, and not the full path to them, nor what kind of file/folder they are. We therefore need a way to do 3 things:

您可以在此处看到图片文件夹中的文件仅包含文件名,而不包含文件的完整路径,也不包含它们是哪种文件/文件夹。 因此,我们需要一种方法来做三件事:

  1. Identify their full path

    确定他们的完整路径
  2. Determine if they are an image file or not

    确定它们是否是图像文件
  3. If the file is an image, add it to a list of files that we'll want to display

    如果文件是图像,请将其添加到我们要显示的文件列表中

We'll need to make the findAllImageFiles function a bit smarter. Thankfully there are some tools that we can bring in to assist us with this. For the 1st requirement, we're going to use another one of Node.js' core API modules to handle generating the full file path, as well as identifying image files.

我们需要使findAllImageFiles函数更加智能。 值得庆幸的是,我们可以引入一些工具来协助我们。 对于第一个要求,我们将使用Node.js的另一个核心API模块来处理生成完整的文件路径以及识别图像文件。

First off, because we're going to rename the findAllImageFiles function to just findAllFiles, as we're going to split out the filtering of the image files into a separate function, so that we can maintain code readability. Simply do a quick find and replace, and then we can move onto implementing the image filtering function. Once that's done, we want to install a node module via NPM called mime. It is a 3rd-party library that will help us to determine the mime type of the files. Run this command on your terminal:

首先,因为我们要重命名findAllImageFiles功能仅限于findAllFiles ,因为我们要的图像文件的过滤拆分为三个独立的功能,让我们可以保持代码的可读性。 只需快速查找并替换,然后我们便可以继续实现图像过滤功能。 完成后,我们想通过NPM安装一个名为mime的节点模块。 这是一个第三方库,可帮助我们确定文件的mime类型。 在终端上运行以下命令:

npm install mime --save

This will install the mime module, and save it as a dependency in the package.json manifest file. Once that is done, we want to require it along with Node.js' path module in the dependencies section of the app.js file. Alter the top section so that it looks like this:

这将安装mime模块,并将其作为依赖项保存在package.json清单文件中。 完成后,我们希望在app.js文件的dependencies部分中将其与Node.js的路径模块一起使用。 更改顶部,使其如下所示:

// Dependencies
var fs      = require('fs');
var mime    = require('mime');    
var path    = require('path');

With those modules now available in our code, we can turn to implementing the findImageFiles function. This function will take a list of files, construct the full file path to them, use the mime library to find out their mime type, and if they're an image, we can add them to a new list, which will then be passed to a callback function. Add a few blank lines after the findAllFiles function, and insert the following Array:

有了代码中现在可用的那些模块,我们可以转向实现findImageFiles函数。 此函数将获取文件列表,构建文件的完整文件路径,使用mime库查找其mime类型,如果它们是图像,我们可以将其添加到新列表中,然后将其传递回调函数。 在findAllFiles函数之后添加一些空行,并插入以下Array:

var imageMimeTypes = [
    'image/bmp',
    'image/gif',
    'image/jpeg',
    'image/png',
    'image/pjpeg',
    'image/tiff',
    'image/webp',
    'image/x-tiff',
    'image/x-windows-bmp'
];

This variable contains a list of image mime types that we can display in the app, and will be used to filter files by their mime type. After this, let's insert the following function:

此变量包含我们可以在应用程序中显示的图像mime类型的列表,并将用于按文件的mime类型过滤文件。 之后,让我们插入以下函数:

function findImageFiles (files, folderPath, cb) {
    var imageFiles = [];
    files.forEach(function (file) {
        var fullFilePath = path.resolve(folderPath,file);
        var extension = mime.lookup(fullFilePath);
        if (imageMimeTypes.indexOf(extension) !== -1) {
            imageFiles.push({name: file, path: fullFilePath});
        }
        if (files.indexOf(file) === files.length-1) {
            cb(imageFiles);
        }
    });
}

The findImageFiles function handles looking through all of the files, constructing their full path, checking if they are an image, and then collecting the ones that are. We then alter the window.onload function to use it like so:

findImageFiles函数用于浏览所有文件,构造它们的完整路径,检查它们是否为图像,然后收集它们。 然后,我们更改window.onload函数以如下方式使用它:

// Runs when the browser has loaded the page
window.onload = function () {
    bindSelectFolderClick(function (folderPath) {
        hideSelectFolderButton();
        findAllFiles(folderPath, function (err, files) {
            if (!err) {
                findImageFiles(files, folderPath, function (imageFiles) {
                    console.log(imageFiles);
                });
            }
        });
    });
};

With these changes saved, we can reload the app from the command line, and see that in the console of the developer tools, we are now returning only the image files, as opposed to all of the files in the folder:

保存这些更改后,我们可以从命令行重新加载应用程序,并看到在开发人员工具的控制台中,我们现在仅返回图像文件,而不是文件夹中的所有文件:

Step 7 Full Size Render

We're now in a position to have these files passed to a function that will display them in a grid.

现在,我们可以将这些文件传递给将在网格中显示的函数。

显示照片 (Displaying the photos)

Displaying the photos in a grid involves adding some HTML to the page for the photo template and display area, a bit of JavaScript to insert the photos into the app screen, and some CSS to apply the layout and styling of the photo items. We'll start with the HTML.

在网格中显示照片需要在页面上添加一些HTML,以用于照片模板和显示区域,一些JavaScript将照片插入应用程序屏幕,以及一些CSS以应用照片项目的布局和样式。 我们将从HTML开始。

Luckily for us, we're able to use a lot of modern HTML5 and CSS3 APIs to build the app, and so we can make use of the HTML5 template tag to contain the snippet of html that we want to use for each photo. In the index.html, add the following bit of HTML just after the opening body tag:

对我们来说幸运的是,我们能够使用许多现代HTML5和CSS3 API来构建应用程序,因此我们可以利用HTML5模板标记来包含要用于每张照片的html代码段。 在index.html中,在body标签之后添加以下HTML代码:

<template id="photo-template">
    <div class="photo">
        <img />
    </div>
</template>

The div element with a class of photo contains an image tag, and we'll set the src attribute of that image tag to the photo's file path. The div element surrounding the image tag is there to support rendering the photos in a grid view with set dimensions, and have the photos be displayed in a fashion that respects the aspect ratio of the image.

带有一类照片的div元素包含一个图像标签,我们将将该图像标签的src属性设置为照片的文件路径。 图像标签周围的div元素在那里支持以设定的尺寸在网格视图中渲染照片,并以尊重图像纵横比的方式显示照片。

We'll also need to have a place to store the list of photos in the app screen. Before the closing body tag, add the following bit of HTML:

我们还需要有一个位置来在应用程序屏幕中存储照片列表。 在结束body标签之前,添加以下HTML:

<div id="photos"></div>

With the HTML in place, we can now add some JavaScript to append the photos to the page with the template. In the app.js file, we're going to add a function that handles adding an image to the photos area. Before the "window.onload" function, add the following function:

有了HTML之后,我们现在可以添加一些JavaScript以将照片附加到带有模板的页面上。 在app.js文件中,我们将添加一个用于将图像添加到照片区域的函数。 在“ window.onload”功能之前,添加以下功能:

function addImageToPhotosArea (file) {
    var photosArea = document.getElementById('photos');
        var template = document.querySelector('#photo-template');
        template.content.querySelector('img').src = file.path;
        template.content.querySelector('img').setAttribute('data-name',file.name);
    var clone = window.document.importNode(template.content, true);
      photosArea.appendChild(clone);
}

The addImageToPhotosArea function uses JavaScript to select the photos area and the photo template, sets the src attribute of the image tag in the template to photo's file path and the name of the file as a data attribute, and appends the template item to the photos area.

addImageToPhotosArea函数使用JavaScript选择照片区域和照片模板,将模板中图像标签的src属性设置为照片的文件路径,并将文件名设置为数据属性,并将模板项附加到照片区域。

Next, we alter the window.onload function and replace the console.log function with a call to loop through the imageFiles array, and pass each file to the addImageToPhotosArea function, like so:

接下来,我们更改window.onload函数,并用一个调用来替换console.log函数以遍历imageFiles数组,然后将每个文件传递给addImageToPhotosArea函数,如下所示:

// Runs when the browser has loaded the page
window.onload = function () {
    bindSelectFolderClick(function (folderPath) {
        hideSelectFolderButton();
        findAllFiles(folderPath, function (err, files) {
            if (!err) {
                findImageFiles(files, folderPath, function (imageFiles) {
                        imageFiles.forEach(addImageToPhotosArea);
                });
            }
        });
    });
};

Finally, we can apply some layout and styling to the photos area and the photo item. In the app.css file, add the following CSS to the end of the file:

最后,我们可以对照片区域和照片项目应用一些布局和样式。 在app.css文件中,将以下CSS添加到文件末尾:

#photos {
        padding: 0;
        margin: 0;
        width: 100%;
        height: 100%;
    }

    .photo {
        text-align: center;
        float: left;
        margin: 2%;
        padding: 1% 0.5%;
        background-color: white;
        width: 20%;
        height: 18%;
        margin-bottom: 1%;
    }

    .photo img {
        max-width: 100%;
        max-height: 100%;
    }

Also, we want to nullify any of the default margin and padding applied to the body tag by the Chromium browser, so we'll add these 2 rules to the body element:

另外,我们想使Chromium浏览器应用于body标签的任何默认边距和填充无效,因此我们将这2条规则添加到body元素:

margin: 0;
    padding: 0;

With this layout and styling in place, if we save the changes, reload the app and select a folder to display photos for, we should see something that resembles this (albeit with different photos):

有了这种布局和样式后,如果我们保存更改,重新加载应用程序并选择一个文件夹来显示照片,我们应该会看到类似的东西(尽管有不同的照片):

Step 8 Photo Grid

Now the app is beginning to look a bit more than just a barebones skeleton, and we've been able to use Node.js and leverage the NPM ecosystem to install modules that assist with building the application.

现在,该应用程序的外观已不仅仅只是一个准系统骨架,而且我们已经能够使用Node.js并利用NPM生态系统安装有助于构建应用程序的模块。

From here, we can start to look at being able to click on a photo, and enter full view mode on it.

从这里开始,我们可以开始查看能够单击照片并在其上进入全视图模式。

结论 (Conclusion)

This concludes part 1. Hopefully by now you'll have a strong understanding of getting started with NW.js. In the next tutorial, we'll improve this app and cover the best things to come:

到此为止第1部分结束。希望到现在为止,您将对NW.js入门有了深刻的了解。 在下一个教程中,我们将改进此应用程序,并介绍以后最好的东西:

  • Displaying a photo in full-view

    全屏显示照片
  • Applying visual filters to photos

    将视觉滤镜应用于照片
  • Saving altered photos

    保存修改过的照片
  • Packaging the application into a native application that can run on Windows, Mac, and Linux

    将应用程序打包为可在Windows,Mac和Linux上运行的本机应用程序

If you really like NW.js and this tutorial so far, feel free to check-out my book where I cover many of these topics in depth. Scotch.io readers can get 40% off of the book with discount code: scotch

到目前为止,如果您真的很喜欢NW.js和本教程,请随时阅读我的​​书,我在其中详细介绍了许多这些主题。 Scotch.io读者可以使用折扣码scotch享受40%的折扣。

NW.JS In Action

翻译自: https://scotch.io/tutorials/creating-a-photo-discovery-app-with-nw-js-part-1

nw.js 调用驱动程序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值