如何利用node.js开发一个生成逐帧动画的小工具_node.js

来源:脚本之家  责任编辑:小易  

那么到底是如何实现服务端调用解耦的呢?在实现方案中,我们采用了(Node.js+Protocol Buffers+Zookeeper+RabbitMQ)的组合,从而实现配置集中化管理:1.Node.js,主要用于开发业务逻辑。作为天生的异步脚本语言,Node.js 使用事件驱动、非阻塞I/O模型大大提升了研发效率,非常适合在分布式设备上运行的数据密集型的实时应用。我们通过 Fibers库采用协程的方式来解决Node.js 异步编程匿名回调问题,将异步回调逻辑转化为同步,同时也满足了程序员使用同步方法编写异步程序的情怀。可参考官方介绍:https://nodejs.org/https://github.com/laverdet/node-fibers2.Protocol Buffers,用于强约束消息定义。Protocol Buffers一种数据交换的格式,它独立于语言,独立于平台。由于它是一种二进制的格式,相比XML和JSON,传输效率会更高,可以将它用于分布式应用之间的数据通信或者异构环境下的数据交换。我们主要将Protocol Buffers用来模版化定义消息结构。可参考:https://github.com/google/protobuf3.Zookeeper,实现配置集中管理。Zookeeper分布式服务框架是Apache Hadoop 的一个子项目,简单的说,Zookeeper=文件系统+通知机制。它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。我们使用ZooKeeper看重的是它不仅支持集群高可用,还支持持久化节点、临时节点存储和节点变更监控的特点,主要使用了它提供的命名服务、配置管理和集群管理服务。其中,临时节点特性用以实现名字服务注册,节点变更监控实现配置集中管理。参考:https://zookeeper.apache.org/4.RabbitMQ,实现异构通讯服务间的解耦。Rabbitmq是一种应用程序对应用程序的通信方法,选择RabbitMQ的原因在于它可以支持集群高可用、简单易用、性能出色和完善的管理工具(如:Web ui/Rest API)的特点。使用Rabbitmq中间件服务端实现解耦,其中主要是利用(Work Queue+Topics Exchange)来实现后端的无缝扩容,并采用Publish/Subscribe+RPC 实现调用解耦,并利用MQ 统一输入输出。参考:https://www.rabbitmq.com/走过的一些坑最后,总结经验避免犯同样的错,是非常重要的,还有一些技术遗留问题,需要我们自行避开这些坑。以下是我们在构建RPC框架过程中遇到的一些坑:异步编程效率问题(Fibers)&Node.js 内存泄漏问题在复杂在构建复杂应用的时候,很多地方都可能发生内存泄露,也需要考虑异步编程效率问题。为解决这两个问题,我们目前主要采取以下三个手段来解决:a)框架封装所有网络通信,业务方只关注业务逻辑、提高研发效率;b)通过Fibers 封装所有异步函数调用转换为同步方法;c)谨慎选择第三方库。异步框架中日志跟踪异步程序记录日志乱序不利于跟踪业务逻辑调用路径。为解决这个问题,我们通过包装 Fibers 对每一个 Fiber 实例进行编号,在所有日志输出中打印 Fiber id 记录异步调用路径,并配合跨模块会话编号实现请求调用跟踪,以此解决日志纪录的无序问题。RabbitMQ HA 高可用问题如果需要实现RabbitMQ HA 高可用特性,有两种途径可以实现:Server 端 HA 和 Client HA。Server 端的高可用性可使用 LVS 或 HAProxy来实现,Client 端的高可用性也是一种选择,这样可以减少架构复杂度和层次依赖。值得注意的是,实现高可用特性时,要记得开启Queue 高可用配置。(https://www.rabbitmq.com/ha.html)RabbitMQ HA 网络闪断导致节点分区问题网络不稳定导致RabbitMQ HA 网络闪断,进而导致节点分区问题。针对这个问题,需要添加对/api/nodes 进行监控,并及时处理分区问题。具体的解决方法可参考:https://www.rabbitmq.com/partitions.htmlZooKeeper Session Expired针对ZooKeeper 会话过期问题,需要大家特别关注处理Zookeeper 集群断开后的重连处理,因为如果重连逻辑没有处理好的话,所有依赖ZooKeeper的特性都将不可用。具体解决方法可参考:http://wiki.apache.org/hadoop/ZooKeeper/FAQ结 语经过应用实践,目前看来 Node.js几乎可以做到其他后端语言所能做到所有的事情,ES6特性正式发布如今有人已经开始高喊“javascript:The World's Best Programming Language”,但我也并不认为整个后端完全用Node.js来实现会是一个很好的方案。本文中提到了Node.js的诸多优点,如异步、非阻塞和事件驱动等,但其也存在一些缺点,如默认单进程单线程不能利用多核,脚本弱类型容易出现运行时BUG,同时因为它简单易用,也导致了代码质量不易控制,对开发人员也提出了更高的要求。所以,就个人经验来看,建议偏复杂业务逻辑控制使用Node.js,如果是偏极致性能的业务建议和C++等其他方案结合使用www.zgxue.com防采集请勿采集本网。

前言

在实际工作中我们已经下下来不下于一万个npm包了,像我们熟悉的 vue-cli,react-native-cli 等,只需要输入简单的命令 vue init webpack project,即可快速帮我们生成一个初始项目。在实际开发项目中,我们也可以定制一个属于自己的npm包,来提高自己的工作效率。

任何一种后台开发语言都是可以的,只要它能够接收到小程序发出的请求,并且能够按照小程序指定的格式(通常就是json)返回数据给小程序就行。但是,小程序官方专门为node.js和php制作了sdk,利用

为什么要开发一个工具包? 减少重复性的工作,不再需要复制其他项目再删除无关代码,或者从零创建一个项目和文件。 根据交互动态生成项目结构和所需要的文件等。 减少人工检查的成本。 提高工作效率,解放生产力。

建立一个WebSocket连接,客户端浏览器首先要向服务器发起一个HTTP请求,这个请求和通常的HTTP请求不同,包含了一些附加头信 息,其中附加头信息”Upgrade:WebSocket”表明这是一个申请协议升级的

这次以帧动画工具为例,来一步一步解析如何开发一个npm包。

主要是用来写服务器,流行之后现在开始有用nodejs写管理脚本的了。

开始前的准备

在此之后,我们可以利用之前创建的该对象的.Wrap()方法(继承自node:ObjectWrap)来将它分配给this变量: obj->Wrap(args.This());最后,我们可以返回这个新创建的对象: return args.This();如果该函数

以我们这次为例。由于目前在做一些活动页相关的工作,其中动画部分全都采用CSS3中的animation来完成,但是这样每次开发都要计算百分比,手动判断动画的一些属性值,十分耗时又很容易出错,就想能不能写个脚本,直接一行命令就可以搞定了呢?!答案当然是肯定的。

Node.js的应用程序都是单线程的。这就意味着即使计算机是多核或多处理器的,node.js的应用程序也只能利用其中一个,大大限制了系统性能。随着堆栈变大,Node.js的垃圾收集器变得非常低效。随着

理清思路

我们要做一个可以通过读取图片就可以自动生成包含CSS animation的HTML页面,以后需要生成相应的CSS片段,直接执行命令就可以了。

初始化

既然是npm包,那我们就需要在npmjs上注册一个账号,注册完成之后回到本地新建一个文件目录fbf,进入fbf目录下执行npm init -y。

{ "name": "fbf", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "bin": { "test": "index.js" }, "keywords": [], "author": "", "license": "ISC"}

  这样,你的package.json就建好了。

依赖的库

来看看会用到哪些库。 commander.js,可以自动的解析命令和参数,用于处理用户输入的命令。 chalk,可以给终端的字体加上颜色。 create-html,创建HTML模版,用于生成HTML。 image-size,获取图片大小。

npm install commander chalk create-html image-size -S

命令行操作

node.js 内置了对命令行操作的支持,在 package.json 中的 bin 字段可以定义命令名和关联的执行文件。所以现在 package.json 中加上 bin 的内容:

{ "name": "fbf", "version": "1.0.0", "description": "", "bin": { "fbf": "index.js" }, ...}

然后在 index.js 中来定义 start 命令:

#!/usr/bin/env nodeconst program = require('commander'); program.version('1.0.0', '-v, --version') .command('start <name>') .action((name) => { console.log(name); });program.parse(process.argv);

调用 version('1.0.0', '-v, --version') 会将 -v 和 --version 添加到命令中,可以通过这些选项打印出版本号。

调用 command('start <name>') 定义 start 命令,name 则是必传的参数,为文件名。

action() 则是执行 start 命令会发生的行为,要生成项目的过程就是在这里面执行的,这里暂时只打印出 name。

其实到这里,已经可以执行 start 命令了。我们来测试一下,在 fbf 的同级目录下执行:

node ./test/index.js start HelloWorld

可以看到命令行工具也打印出了 HelloWorld,那么很清楚, action((name) => {}) 这里的参数 name,就是我们执行 start 命令时输入的项目名称。

命令已经完成,接下来就要针对图片的操作了。

获取图片信息

这里我们默认根据第一张图片的尺寸信息作为外层DIV的默认尺寸。

#!/usr/bin/env node const program = require('commander'); const fs = require('fs'); const path = require('path'); const createHTML = require('create-html'); const sizeOf = require('image-size'); const chalk = require('chalk'); program.version('1.0.0', '-v, --version') .command('start <dir>') .action((dir) => { //获取图片路径 const imgPath = path.resolve(dir) let imgSize = null; fs.readdir(imgPath, (err, file) => { imgSize = sizeOf(dir + '/' +file[0]); //取第一个图片的尺寸作为框尺寸 let cssString = ` .fbf-animation{ width: ${imgSize.width}px; height: ${imgSize.height}px; margin:auto; background-image: url(./${dir}/${file[0]}); background-size: ${imgSize.width}px ${imgSize.height}px; background-repeat: no-repeat; animation-name: keyframes-img; animation-duration: 0.36s; animation-delay: 0s; animation-iteration-count: infinite; animation-fill-mode: forwards; animation-timing-function: steps(1); } ` }) })

生成CSS代码

然后根据图片数量生成相应的keyframes代码

function toCss(dir, fileList){ let _css = ''; let start = 0; const per = Math.floor(100/fileList.length); fileList.map((path, i) => { if(i === fileList.length - 1){ _css += ` ${start + i*per}%, 100% { background:url(./${dir}/${path}) center center no-repeat; background-size:100% auto; } ` }else{ _css += ` ${start + i*per}% { background:url(./${dir}/${path}) center center no-repeat; background-size:100% auto; } ` } }) return _css; } let frameCss = toCss(dir, newFile) //取第一个图片的尺寸作为框尺寸 let cssString = ` .fbf-animation{ width: ${imgSize.width}px; height: ${imgSize.height}px; margin:auto; background-image: url(./${dir}/${file[0]}); background-size: ${imgSize.width}px ${imgSize.height}px; background-repeat: no-repeat; animation-name: keyframes-img; animation-duration: 0.36s; animation-delay: 0s; animation-iteration-count: infinite; animation-fill-mode: forwards; animation-timing-function: steps(1); } @keyframes keyframes-img { ${frameCss} }

生成html文件

最后我们把生成的CSS放到HTML里。

//生成htmllet html = createHTML({ title: '逐帧动画', scriptAsync: true, lang: 'en', dir: 'rtl', head: '<meta name="description" content="example">', body: '<div class="fbf-animation"></div>' + css, favicon: 'favicon.png'})fs.writeFile('fbf.html', html, function (err) { if (err) console.log(err)})

视觉美化

通过 chalk 来为打印信息加上样式,比如成功信息为绿色,失败信息为红色,这样子会让用户更加容易分辨,同时也让终端的显示更加的好看。

const chalk = require('chalk'); console.log(chalk.green('生成代码成功!')); console.log(chalk.red('生成代码失败'));

完整示例

#!/usr/bin/env nodeconst program = require('commander');const fs = require('fs');const path = require('path');const createHTML = require('create-html');const sizeOf = require('image-size');const chalk = require('chalk'); //排序const sortByFileName = files => { const reg = /[0-9]+/g; return files.sort((a, b) => { let imga = (a.match(reg) || []).slice(-1), imgb = (b.match(reg) || []).slice(-1) return imga - imgb });} //删除.DS_Storefunction deleteDS(file) { file.map((v, i) => { if(v === '.DS_Store'){ fs.unlink('img/.DS_Store', err => {}) } })} // 生成keyframefunction toCss(dir, fileList){ let _css = ''; let start = 0; const per = Math.floor(100/fileList.length); fileList.map((path, i) => { if(i === fileList.length - 1){ _css += ` ${start + i*per}%, 100% { background:url(./${dir}/${path}) center center no-repeat; background-size:100% auto; } ` }else{ _css += ` ${start + i*per}% { background:url(./${dir}/${path}) center center no-repeat; background-size:100% auto; } ` } }) console.log(chalk.green('css successed!')) return _css;} program.version('1.0.0', '-v, --version') .command('start <dir>') .action((dir) => { const imgPath = path.resolve(dir) let imgSize = null; fs.readdir(imgPath, (err, file) => { const newFile = sortByFileName(file) deleteDS(newFile) imgSize = sizeOf(dir + '/' +file[0]); let frameCss = toCss(dir, newFile) //取第一个图片的尺寸作为框尺寸 let cssString = ` .fbf-animation{ width: ${imgSize.width}px; height: ${imgSize.height}px; margin:auto; background-image: url(./${dir}/${file[0]}); background-size: ${imgSize.width}px ${imgSize.height}px; background-repeat: no-repeat; animation-name: keyframes-img; animation-duration: 0.36s; animation-delay: 0s; animation-iteration-count: infinite; animation-fill-mode: forwards; animation-timing-function: steps(1); } @keyframes keyframes-img { ${frameCss} } ` let css = ` <style>${cssString}</style> ` //生成html let html = createHTML({ title: '逐帧动画', scriptAsync: true, lang: 'en', dir: 'rtl', head: '<meta name="description" content="example">', body: '<div class="fbf-animation"></div>' + css, favicon: 'favicon.png' }) fs.writeFile('fbf.html', html, function (err) { console.log(chalk.green('html successed!')) if (err) console.log(err) }) }) });program.parse(process.argv);

代码一共100行左右,可以说非常简单明了,有兴趣的同学可以试试。

最后

完成之后,使用npm publish fbf就可以把脚手架发布到 npm 上面,通过 -g 进行全局安装,就可以在自己本机上执行 fbf start [dir]来生成一个fbf.html文件,这样便完成了一个简单的node工具了。

好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对真格学网的支持。

[nodejs]使用神器webstorm调试nodejs 还在终端敲命令,定位到文件夹然后node xxx.js?你out了。现在我们有更好的调试nodejs方式为什么不去使用呢,只需要一个快捷键而已。ws本身对nodejs有良好的支持,利用ws开发调试nodejs生活将变得很轻松内容来自www.zgxue.com请勿采集。


  • 本文相关:
  • 调试node.js的辅助工具(nodewatcher)
  • node.js开发中使用node supervisor实现监测文件修改并自动重启应用
  • 我用的一些node.js开发工具、开发包、框架等总结
  • windows8下搭建node.js开发环境教程
  • 在linux系统中搭建node.js开发环境的简单步骤讲解
  • windows8.1+iis8.5下安装node.js开发环境
  • 详解windows下运用docker部署node.js开发环境
  • node.js开发之访问redis数据库教程
  • node.js开发指南中的简单实例(mysql版)
  • ubuntu 16.04 64位中搭建node.js开发环境教程
  • node.js开发第三方微信公众平台
  • 详解node.js开发中的express-session
  • linux环境安装node.js开发环境搭建图文教程
  • node.js开发者必须了解的4个js要点
  • node.js开发教程之基于onceio框架实现文件上传和验证功能
  • node.js开发之套接字(socket)编程入门示例
  • node.js开发辅助工具nodemon安装与配置详解
  • 使用socket.io实现简单聊天室案例
  • nodejs加密crypto的实例代码
  • 详解wondows下node.js使用mongodb的环境配置
  • node.js实现简单的爬取的示例代码
  • node.js+es6+dropload.js实现移动端下拉加载实例
  • 用nodejs搭建websocket服务器
  • node.js中的console.log方法使用说明
  • nodejs中实现用户注册路由功能
  • nodejs使用socket5进行代理请求的实现
  • node解析修改nginx配置文件操作实例分析
  • 如何在VPS上设置一个团队的Node.js开发环境
  • 如何利用Node.js 构建分布式集群
  • 如何利用Node.js 构建分布式集群
  • 用node.js必须使用命令行吗?能给一个不使用命令行的应用例子吗?
  • 利用小程序进行云开发必须安装node.js吗
  • 如何利用node.js做前端服务器
  • node js 可以用来干什么
  • 如何编写 Node.js 扩展
  • 如何更好的利用Node.js的性能极限
  • 学习Node.js 有怎样的好处
  • 网站首页网页制作脚本下载服务器操作系统网站运营平面设计媒体动画电脑基础硬件教程网络安全基础知识javascript类库表单特效广告代码网页特效黑客性质javascript技巧domnode.jsjs其它首页javascript调试node.js的辅助工具(nodewatcher)node.js开发中使用node supervisor实现监测文件修改并自动重启应用我用的一些node.js开发工具、开发包、框架等总结windows8下搭建node.js开发环境教程在linux系统中搭建node.js开发环境的简单步骤讲解windows8.1+iis8.5下安装node.js开发环境详解windows下运用docker部署node.js开发环境node.js开发之访问redis数据库教程node.js开发指南中的简单实例(mysql版)ubuntu 16.04 64位中搭建node.js开发环境教程node.js开发第三方微信公众平台详解node.js开发中的express-sessionlinux环境安装node.js开发环境搭建图文教程node.js开发者必须了解的4个js要点node.js开发教程之基于onceio框架实现文件上传和验证功能node.js开发之套接字(socket)编程入门示例node.js开发辅助工具nodemon安装与配置详解使用socket.io实现简单聊天室案例nodejs加密crypto的实例代码详解wondows下node.js使用mongodb的环境配置node.js实现简单的爬取的示例代码node.js+es6+dropload.js实现移动端下拉加载实例用nodejs搭建websocket服务器node.js中的console.log方法使用说明nodejs中实现用户注册路由功能nodejs使用socket5进行代理请求的实现node解析修改nginx配置文件操作实例分析一行命令搞定node.js 版本升级卸载安装node.js与npm过程详解node.js(安装,启动,测试)yarn的安装与使用详细介绍node.js+ajax实现获取http服务器nodejs中调用系统命令、shell脚本nodejs npm install全局安装和本nodejs基本语法和类型nodejs学习笔记之fs文件模块node.js中的fs.writefilesync方法使用jasmine和karma对angularjs页面程序进express使用html模板的详细代码如何自动化部署项目?折腾服务器之旅~node.js环境下koa2添加travis ci持续集成详解nodejs 文本操作模块-fs模块(五)我的node.js学习之路(三)--node.js作用利用nginx + node在阿里云部署https的步骤nodejs实现邮件发送服务实例分享node.js文件操作系统实例详解node.js中的http.response.getheader方法
    免责声明 - 关于我们 - 联系我们 - 广告联系 - 友情链接 - 帮助中心 - 频道导航
    Copyright © 2017 www.zgxue.com All Rights Reserved