Quantcast
Channel: CNode:Node.js专业中文社区
Viewing all 14821 articles
Browse latest View live

使用egg.js过程中遇到的问题:curl请求到nginx服务器,但目标的反向代理无法生效

$
0
0

Node Version: v8.9.3 Egg Version: v2.0.0

在使用eggjs框架时遇到如下的问题, 我的测试环境 /etc/hosts 10.200.33.33 haha.ttt.com映射到测试服务器

在代码中controller层向该地址请求数据 ctx.curl('http://haha.ttt.com', opts);这里url是nginx服务器的域名,因为是测试环境,所以配置了hosts映射,但此时发出的请求,会返回404, 感觉像是nginx反向代理无法生效

直接在环境中使用curl命令去请求域名是可以代理成功的, 但在代码中使用域名就会返回404,和curl直接请求IP是一样的情况,很困惑。。。


node爬虫如何保持登录并且监听网站推送消息呢?

$
0
0

正常的爬取网页内容只要request拿到body解析就可以了,那么如何登录一个网页并且监听网站给用户推送的消息呢?

如何解决访问稍微一多 内存就暴涨!!

$
0
0

1.jpg平常内存是这样的。

然后测试每一秒 100个人请求首页

const request = require('request');
setInterval(() => {
    for (let i = 0; i < 100; i++) {
        request('http://我的网址首页.com', (err, res, body) => {
            if (!err && res.statusCode == 200) {
                console.log(1)
            } else {
                console.log(‘n’)
            }
        })
    }

}, 1000)

然后变这样了。。 2.jpg

/*首页路由如下。。*/
route.get('/', (req, res) => {
    let pageInfo = req.query
    let searchW = { category: 'article' }
    let seo_title = pageInfo.search ? pageInfo.search + "_" : '';
    let seo_tag = pageInfo.tag ? pageInfo.tag + "_" : '';
    pageInfo.page = pageInfo.page && parseInt(pageInfo.page) >= 1 && parseInt(pageInfo.page) <= 200 ? pageInfo.page : 1
    let seo_page = pageInfo.page > 1 ? `第${pageInfo.page}页_` : '';
    let shownum = pageInfo.shownum && pageInfo.shownum < 50 ? parseInt(pageInfo.shownum) : 30;
    if (pageInfo.search) {
        searchW.title = new RegExp(`.*${pageInfo.search}.*`, 'i')
    }
    if (pageInfo.tag) {
        searchW.tags = new RegExp(pageInfo.tag, 'i')
    };

    (async() => {
        try {
            let [count, article] = await Promise.all([
                db.articleModel.count(searchW).exec(),
                db.articleModel.find(searchW, { content: 0 })
                .skip(pageInfo.page * shownum - shownum)
                .limit(shownum).sort({ recommend: -1, _id: -1 })
                .exec()
            ])
            let allPage = Math.ceil(count / shownum)
            res.render('index', {
                data: article,
                page: allPage,
                headInfo: {
                    title: seo_tag + seo_page + config_seo.index.title,
                    keywords: config_seo.index.keywords,
                    description: config_seo.index.description
                }
            })
        } catch (e) {
            res.render('err')
        }

    })()

})

有时候访问页面就 3.jpg还是我的 服务器是 配置是 CPU: 1核 内存:1 GB (I/O优化) 1Mbps

请问express中i18n大家都怎么搞

nodejs称霸一切 :)

$
0
0

什么 Java Python… 未来是nodejs的!

What? Why? << Simple !!!

Only Simple? << It’s enough.

vue2封装的table联动组件

$
0
0

vue-table-pagination

vue2封装的table联动组件

NPM

npm versionBuild StatusCoverage Statusnpm Downloadgziptested with jest

Live Demo

vue-table-pagination-demo Site

Install with npm

Installing

npm install --save vue-table-pagination

Import

import Vue from 'vue';
import VueTablePagination from 'vue-table-pagination';
Vue.use(VueTablePagination);

西门互联分页组件

可自定义配置和分页可fork自行修改

<vue-table-pagination
                    @gmChangePageButton="gmChangePageButton"
                    @gmChagePageSize="gmChagePageSize"
                    :gmCurrentPage="page"
                    :gmTotalPage="totalPage"
                    :gmCanJump="true"
                    :gmCanChoose="true"
                    :gmTableLists="gmTableLists"
                    :gmTableThLists="gmTableThLists"
                    :gmIsIndex="true"
                    @gmPerEmitClick="gmPerEmitClick"
                    :gmTableWidth="0"
                    :gmTimeStampType="63"
            ></vue-table-pagination>
gmChangePageButton -- 按钮改变分页
gmChagePageSize --每页显示多少条
page -- 当前高亮锚点
totalPage -- 总页数
gmCanJump --是否跳转
gmCanChoose -- 是否改变分页条数
gmTableLists --tbody数据
gmTableThLists --theader数据
gmIsIndex --开启索引
gmPerEmitClick --table中的按钮操作
gmTableWidth --table宽度
gmTimeStampType --时间参数

效果图截图

vue2封装的table联动组件vue2封装的table联动组件配色

演示test.vue

<template>

    <div class="page-view">
        <div class="page-content">
          <!-- 通用table组件 -->
          <!--用法 -->
          <vue-table-pagination
                  @gmChangePageButton="gmChangePageButton"
                  @gmChagePageSize="gmChagePageSize"
                  :gmCurrentPage="page"
                  :gmTotalPage="totalPage"
                  :gmCanJump="true"
                  :gmCanChoose="true"
                  :gmTableLists="gmTableLists"
                  :gmTableThLists="gmTableThLists"
                  :gmIsIndex="true"
                  @gmPerEmitClick="gmPerEmitClick"
                  :gmTableWidth="0"
                  :gmTimeStampType="63"
          ></vue-table-pagination>
        </div>
      </div>

</template>

<script>

  export default {
    name: 'test',
    data(){
      return {
          page:1,
          pageSize:10,
          totalPage:100,
          //修改为value对象下面值取
          gmTableLists:[
              {
                "game_uuid": {
                  "value": 14
                },
                "title": {
                  "value": "标题1"
                },
                "content": {
                  "value": "这是标题1的所有内容内容这是标题1的所有内容内容"
                },
                "attachment": {
                  "value": [
                    {
                      "props": "晶能id",
                      "number": "10"
                    }, {
                      "props": "皮肤id",
                      "number": "10"
                    }
                  ]
                },
                "receiver": {
                  "value": ["张三", "李四", "王麻子", "小红"]
                },
                "sendtime": {
                  "value": 1515772800
                },
                "create_user": {
                  "value": "超级管理员1"
                },
                "create_time": {
                  "value": 1515828493
                },
                "update_user": {
                  "value": "admin"
                },
                "update_time": {
                  "value": '1515828493'
                },
                "operate": {
                  "value": [
                    {
                      "game_uuid": 14,
                      "action": "pk_id"
                    }, {
                      "button_name": "编辑",
                      "action": "edit"
                    }, {
                      "button_name": "删除",
                      "action": "delte"
                    }
                  ]
                }
              },
              {
                "game_uuid": {
                  "value": 15
                },
                "title": {
                  "value": "标题2"
                },
                "content": {
                  "value": "这是标题2的所有内容内容这是标题1的所有内容内容"
                },
                "attachment": {
                  "value": [{
                    "props": "晶能id",
                    "number": "11"
                  }, {
                    "props": "皮肤id",
                    "number": "12"
                  }]
                },
                "receiver": {
                  "value": ["小米", "小明"]
                },
                "sendtime": {
                  "value": 1515772800
                },
                "create_user": {
                  "value": "超级管理员2"
                },
                "create_time": {
                  "value": 1515828093
                },
                "update_user": {
                  "value": "jackieli"
                },
                "update_time": {
                  "value": ''
                },
                "operate": {
                  "value": [
                    {
                      "game_uuid": 15,
                      "action": "pk_id"
                    }, {
                      "button_name": "编辑",
                      "action": "edit"
                    }, {
                      "button_name": "删除",
                      "action": "delte"
                    }
                  ]
                }
              }
          ],
          //接口先获取这个表头字段对应    "fields"://表单字段列表  button 操作
          //然后在获取gmTableLists
          //每个用户看到的字段格式都不一样(权限可设置)
          gmTableThLists:{
              "game_uuid":"流水号",
              "title":"标题",
              "content":"内容预览",
              "attachment":"邮件奖励",
              "receiver":"收件人/人数",
              "sendtime":"发送时间",
              "create_user":"创建者",
              "create_time":"创建时间",
              "update_user":"审核人",
              "update_time":"审核时间"
          }
      }
    },
    methods: {
      //循环事件派发
      gmPerEmitClick(list,index,type){
        console.log("格式化后的当前列数据",list);
        let game_uuid = list.game_uuid.value
        //通过this.gmTableLists[index]的数据来判断每列操作的button的事件
        console.log("通过index参数获取原始数据的操作当前列",this.gmTableLists[index])
        // console.log("商品id:"+id+"---事件:"+type)
        console.log("流水号:"+game_uuid+"---对外index:"+index+"--对外事件类型"+type)
        //this.$router.replace('/')
      },
      gmChagePageSize(data){
        this.page = 1
        this.pageSize = data
        console.log(data)
      },
      //分页组件传递事件ajax
      gmChangePageButton(page){
         this.page = page
         console.log(page)
      }
    }
  };
</script>

<style lang="css">
  #app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  color: #2c3e50;
}

* {
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}


* > input:-webkit-autofill {
    -webkit-box-shadow: 0 0 0px 1000px #fff inset !important; /*关于解决输入框背景颜色*/
    -webkit-text-fill-color: #000000!important;
}
html,
body {
    font-family: "Microsoft YaHei";
    font-size: 14px;
    color: rgba(0, 0, 0, 0.85);
    background: #fff;
    padding: 0 10px;
    overflow-x: hidden;
    -webkit-font-smoothing: antialiased;
}

ol,
ul,
li {
    list-style: none;
}

img {
    border: 0 none;
}

a {
    text-decoration: none;
}

a,
input,
textarea {
    outline: none;
}

input::-ms-clear,
input::-ms-reveal {
    display: none;
}

table {
    border-collapse: collapse;
    border-spacing: 0;
}

caption,
th,
td {
    text-align: left;
    font-weight: normal;
    vertical-align: middle;
}

.clearfix {
    *zoom: 1;
}

.clearfix:after {
    clear: both;
    content: '';
    display: block;
    height: 0;
    visibility: hidden;
}

.hide {
    display: none !important;
}

.show {
    display: block;
}

.fl {
    float: left;
}

.fr {
    float: right
}
</style>

cnode客户端一个小问题

$
0
0

想在帖子列表中插入作者头像

结果发现列表中作者是author_id, 个人信息是username, 这两个api有什么关联的办法吗?

北京频果招聘nodejs后端 h5前端工程师

$
0
0

h5前端工程师 职位描述 深入了解公司业务应用系统的框架,切身参与到公司实际系统的需求分析及设计等工作中,按照要求完成对前端架构、技术的开发及优化,并协助完成相关配合,为其他伙伴提供专业的技术支持。

技术需要:

熟悉掌握前端技术: Html5,CSS3,Jquery 和 responsive design 熟练掌握Git

有过Vue.js实际项目经验优先; 有微信小程序开发经验者优先 ”钻研过“JavaScript,熟悉H5、css和布局所用的技术,能够独立完成前端页面的开发、打包、联调及发布工作。 有良好的沟通能力和团队合作能力,做过一个完整的项目,而不是某个模块。 以敏捷开发形式(Agile development)小团队协作开发基于零售终端数据集成与深度处理的数字营销应用平台;

加分项: nodejs 开发经验 微信小程序

nodejs 后端工程师 任职要求 1.熟练掌握Nodejs异步运行原理 ; 2.精通B/S系统主流的开发技术如:koa2、Express等相关技术; 3.熟练使用mysql、momgodb redis ,pm2、nginx服务器; 4.具备较强的学习能力、技术研究能力和表达能力以及故障诊断能力; 5、具有良好的表达和沟通能力,具备解决方案的编写能力,熟练掌握软件开发流程,熟练掌握软件的需求、设计、编码和测试工作; 6.有小程序研发经验者优先。

工作地点:北京大望路地铁站 请投简历mac@niefengjun.cn QQ:357403651


后端返回Buffer的二进制数据,前端接收到就变了数据格式?

$
0
0

后端返回Buffer的二进制数据,前端接收到就变了数据格式? 是编码问题?还是什么原因? 图1:node输出的1516254279(1).png图2:客户端输出的。1516254253(1).png node是返回Buffer类型的给前端了!!!求大神们解答?

哎呀妈呀,这ES6语法,害我想了大半个钟头!

$
0
0

TIM截图20180118150428.png

来自这里

看到这个直接懵了,这是啥。。。。。

用babel处理了下才算能明白TIM图片20180118143855.png

微信运动数据抓取发布第4版啦!!(2018.1.15)

$
0
0

微信运动数据抓取发布第4版啦!!(2018.1.15)

wxSportCrawler V4

一套抓取微信运动真实数据、并将微信运动数据用于活动/场景的程序

关键字:微信运动、微信步数、运动步数、wechat sport、wechat step、微信硬件

Demo: http://wxsportdemo.grplpl.com/

最近更新:

一、欢天喜地的V4版本发布啦,API支持脱离微信公众平台的纯H5调用!本Demo即为纯H5的演示。还有大量示例代码可以下载试用。

二、我们开放小心心啦!朋友们在微信运动里给你点的赞,也能显示在这里了!

本API比好色派等官方API最大的优点在于:

1、可以脱离微信公众号等微信体系运行,自成一体。

2、主动抓取所有用户的数据。而官方的只能获取登录了公众号的用户的数据。例如一个实时步数排行榜,官方的就很不准确。

3、有另一维度的社交数据 —— 微信运动点赞数。

4、可以方便的和公众平台、小程序、Android和iOS的APP等集成。

有关纯H5调用

您可以留心注意到,打开本页面的过程中并没有弹出微信公众平台的授权提示,但是也能正常获取您的昵称、头像、步数信息和排行榜了,说明本API已经支持纯H5的调用,脱离微信公众号了。

这个特性将帮助开发者:

1、快速开发出微信运动相关的程序。更多的示例代码请在“帮助”下获取和下载。

2、不再需要架设和维护服务器和VPS等,只需要一个HTML页面即可完成一个项目。

3、不再需要开发后端程序,只需要一个HTML页面即可完成一个项目。

4、脱离微信公众号,保障您的APP的稳定和可控。

商务合作

这里已经实现了一个可用的API,可提供有限的试用。

具体请联系我,QQ 14707685,注明“微信运动数据”。

请关注这个项目,https://github.com/klausgao/wxSportCrawler/

微信扫码体验

部分截图

咨询一个关于js中内存泄漏的问题

$
0
0

我目前在使用Koa 1.0,自己做了一些简单的封装,最近项目上线后发现内存一直在上升,没有下降,怀疑有内存泄漏,随之进行了一次排查,经过反复的断点测试之后目前初步怀疑是数据库模块产生的问题,最后定位到这段代码

ActiveQuery.prototype.afterQueryRecord = function(datas, one){
	var self = this;
	if( this.AR.related && datas.length > 0 ){
		console.log('beginning search related : ' + self.id);
		for( k in self.AR.related ){
			var query = self.AR.related[k];
			if( query.relate_status && query.relate_status == 'pending' ){
				self.pending.push(k);
			}
		}
		if( self.pending.length == 0 ){
			return self.getQueryRecord(datas, one)
		}
		return self.findRelationData(datas, one);
	}else{
		return this.getQueryRecord(datas, one);
	}
};
ActiveQuery.prototype.findRelationData = function(datas, one){
	var self = this;
	return new Promise(function(resolve, reject){
		if( self.pending.length <= 0 ){
			resolve(self.getQueryRecord(datas, one));
		}else{
			var name = self.pending[0];
			var related = self.AR.related[name];
			related.query.findRelation(datas).then(function(rows){
				console.log('finded relation ' + related.name);
				self.AR._related[name] = rows;
				self.pending.splice(0, 1);
				resolve(self.findRelationData(datas, one));
			});
		}
	});
};
ActiveQuery.prototype.getQueryRecord = function(datas, one){
	if( one ){
		datas = datas[0] ? datas[0] : {};
	}
	var attributes = clone(datas);

	function QueryRecord(){
	};
	QueryRecord.prototype = clone(Object.getPrototypeOf(this.AR));
	QueryRecord.prototype._attributes = attributes;
	if( this.options.security ){
		datas = this.securityDatas(datas);
	}
	QueryRecord.prototype._datas = datas;
	QueryRecord.prototype.setting = this.AR.setting;
	QueryRecord.prototype.tableName = this.AR.tableName;
	QueryRecord.prototype.one = one;
	QueryRecord.prototype.isSecurity = this.options.security ? 1 : 0;
	QueryRecord.prototype.toString = function(){
		return '[QueryRecord Object]';
	};
	var record = new QueryRecord();
	if( one ){
		if( datas ){
			for( k in datas ){
				record[k] = datas[k];
			}
		}
	}else{
		for( var i = 0; i < datas.length; i++ ){
			record[i] = datas[i];
		}
	}
	var result = record;
	if( this.options.asArray ){
		result = record.parsed().toArray();
	}
	return result;
	// return this.options.asArray ? record.toArray() : record;
};

self.AR.related里有预设好的其他表的类 这段代码是在执行完mysql query后根据related去查找关联关系,然后绑定到当前的类中,想咨询一下各位大神请问这样的话会不会导致内存泄漏,原理是什么,非常感谢

求推荐个基于redux的状态管理库,除了dva之外

$
0
0

早起写的博客,使用redux硬刚,现在要重构了.

看到那么多redux的文件都怕…

求推荐一个,既能复用redux的中间件,又不那么啰嗦的

angular仿cnode

$
0
0

angular-cli 搭建环境 根据cnode的api仿写cnode 效果图如下: 20180118180243.gif20180118180402.gif20180118180405.gif20180118180410.gif20180118180419.gif1 (2).gif

由于api未提供登陆接口,只是做了token验证,所以用自己账号登陆 其中肯定存在很多问题,欢迎各位大佬指点,谢谢。 GitHub地址:https://github.com/TadBO/Angular2_CNode

[北京] 美团点评 - 前端工程师 - 15 ~ 30k

$
0
0

人才缺口很大,有意者发送简历到邮箱:xiaomaolin@meituan.com

「基本要求」大学本科或以上学历,计算机相关专业 熟悉 W3C 标准与 ES 规范,熟悉 Web 语义化 熟练掌握盒模型、常用布局以及浏览器和移动设备兼容性 熟练掌握 HTML5 、 CSS3 、 JavaScript 开发,熟练使用至少一种 JS 框架,掌握其原理,能独立开发常用组件 熟练使用各种调试、抓包工具,能独立分析、解决和归纳问题 踏实、勤恳、好学,较强的沟通能力,良好的团队协作精神

「加分项」极强的责任心,追求完美的习惯,刨根问底的精神 具有至少一门服务器端编程的实战经验 具有移动设备调试经验 具有性能优化经验 熟悉各种常用设计模式和常用 MV*框架


采用Vue+nodejs实现的在线Js编辑器

$
0
0

可以在线编辑运行js代码,并且可以文件的形式存储到后台服务器。

深色风格界面(装逼专用(〃‘▽’〃))

1.png

2.png

为了防止重复提交,搞了个简单的验证码–诗歌验证

3.png

项目地址:https://github.com/zycfj/JsBox

[杭州] 有赞零售诚招前端工程师

$
0
0

公司及团队简介 有赞,是一个商家服务公司,我们通过产品和服务,帮助互联网时代的生意人管店、管货、管客、管钱,让生意更好做。

我们致力于成为商家服务领域里最被信任的引领者,希望持续作为一个"开心"( enjoy )的组织。

在有赞,所有人都是“自我驱动”的,这是一群“聪明”、“皮实”、也很有“要性”的年轻人。我们用最直接的表达方式进行沟通与协作,每天像家人一样相处,吃遍杭州文三路的每家小店。我们每个月都有团建,另外有年度 outing,这个月初我们团队刚从“人生必去的五十分之一”越南-美溪海滩回来。

再来介绍下我们的团队:

我们团队是一支新组建的团队,抬头叫『新零售特工队』,虽然名头听起来很牛逼,但出发点和目标却很简单。我们对新零售的理解仍然是以『如何更好地服务商家』为出发点,打通线上线下,构建全渠道一体化的管理方案来帮助商家提升效率和降低成本,并通过数据化工具和互联网营销插件帮助商家管理好新老顾客、提升单客经济。我们非常欢迎对业务有想法、对技术有追求、对未来充满希望的同学加入我们这个大家庭。

岗位职责 参与 PC、APP Hybrid、微信端 等前端开发; 参与 Node 项目开发(前后端分离、服务编排); 参与改进开发、构建、发布等前端工程化体系; 参与 Web 性能优化、体验优化(跨端性能指标搜集、性能数据分析); 参与推动 UI 规范制定和落地(基础组件库、业务组件库); 参与新技术探索、推进系统架构的演化; 参与每周的技术圆桌,推销自己的学习和思想

岗位要求 本科及以上学历; 扎实的计算机以及网络基础; 阅读英文技术文档和书籍无障碍; HTML、CSS、JavaScript 基础扎实,了解 HTTP 协议以及浏览器原理; 参与开源项目并贡献过代码 加分; 有 Hybrid APP、大型 Node 项目实施经验 加分;

有以下特质会如鱼得水 热爱业务,把产品当做自己的孩子,主动优化交互体验; 重视规范和质量,对破窗户式的代码绝不妥协,敢于修正; 积极响应,对线上问题、用户反馈闪电般响应,急用户之所急; 技术驱动,对重复的人肉操作说不,怀着“自动化一切”的梦想; 此外我们还渴望你:成熟、聪明、不玻璃心…

简历直达 欢迎感兴趣和对自己将来 3 年的成长有追求的伙伴勾搭——zhengxin@youzan.com

此外 我们也需要大量设计师、产品、运营、JAVA 开发等有志之士,跪求简历

egg-socket.io里怎么监听connect event啊

$
0
0

egg-socket.io里怎么监听connect event啊

分享一款基于electron开发专为web app使用的浏览器

$
0
0

electron本来就是个浏览器壳,所以用来做浏览器容易不过了。

因为产品需要在电脑开机启动时全屏启动web app应用,加上app是vue做的,布局采用了css3的一些东西,所以对浏览器要求也高。 之前试过chrome的kiosk模式,但是还是不够好,会带有标题栏。想来想去就拿electron来用用;然后就有了下文的Electron Browser。经过了两次版本更新,决定分享出来;喜欢的朋友可以下载玩玩。

**Electron Browser **

一个基于Electron开发的应用浏览器,主要用于网页APP全屏模式运行,使WEB应用看起来更像一个原生应用 浏览器主题可定制,配置简单,实现了简单的网页浏览器功能。

传送门Electron-browser

截图20171218164524.png

基于electron 的一个截图插件工具

$
0
0

electron 的一个截图插件工具

01.png

测试案例

下载之后

$ npm i electron -g

启动

$ npm run dev

github

文件结构

├── screen  // 插件主要文件
│   ├── mainProcess
│   │   └── screenshot.js  // 主进程引入的文件 主要是俩个渲染进程中相互通信的桥梁
│   └── renderProcess // 渲染进程引入的文件
│       ├── asset  // 资源文件
│       ├── index.html // 创建截图渲染进程的文件
│       ├── index.js //  与外界交互的操作
│       └── main-process.js //  创建截图渲染进程中 对图片剪切操作的文件 主要就是canvas的操作
├── test  // 示例文件
│   ├── index.html 
│   └── main.js
├── README.md
└── package.json

使用方式

下载文件之后 主进程中引入 文件

 var screenShot = require('./screen/mainProcess');
 //主进程执行完毕之后 然后执行并传入win 实例及配置
 app.on('ready', () => {
    var url = '/index.html';
    win = createWindow(url);
    win.webContents.openDevTools();
    screenShot(win.webContents,{quit:'ctrl+shift+q',shotKey:'ctrl+alt+d'});
})
quit:退出快捷键 shotKey:截图快捷键

渲染进程使用方式示例

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
        .box {
            width: 500px;
            height: 200px;
            margin: 0 auto;
        }
        
        .box button {
            width: 100px;
            height: 30px;
            margin: 50px;
        }
    </style>
</head>

<body>
    <div class="box">
        <button data-clipScreen='clipBtn'>截图</button> //在截图按钮中给与属性 data-clipScreen='clipBtn';或者在指定按钮绑定screen()方法
        <button data-cancelclipScreen='clipBtn'>取消</button> //在截图按钮中给与属性 data-cancelclipScreen='clipBtn';或者在指定按钮绑定screenShot()方法
    </div>
</body>
<script>
    var screen = require('./screen/renderProcess');  // 引入文件

</script>

</html>

插件主进程文件

渲染进程中我们也能使用主进程中的api,在这个文件中,主要的用途就是渲染进程之间的通讯桥梁

const { ipcMain, dialog,globalShortcut } = require('electron');
module.exports = function(winContent,obj) {
    // 接收截图工具信号
    ipcMain.on('screenshot-page', function(sender, message) {
        switch (message.type) {
            case 'close':
                winContent.send('quit-cut')
                break;
            default:
                break;
        }
    });
    // 退出快捷键
    var quitShot = (obj&& obj.quit) || 'ctrl+shift+q';
    var shotKey = (obj&& obj.shotKey) || 'ctrl+alt+d';

    globalShortcut.register(quitShot, function() {
        winContent.send('quit-cut', 1);
    });
    // 截图快捷键
    globalShortcut.register('ctrl+alt+d', function() {
        winContent.send('global-shortcut-capture', 1);
    });
};

外部渲染进程引入的index.js

1. 截图按钮与取消绑定方法
// 点击事件绑定
document.body.addEventListener('click', function(event) {
    if (event.target.dataset.clipscreen) {
        screenShot ();
        return false;
    }
})

// 去除默认选择
document.onselectstart = function() {
    return false;
}
// 点击事件方法
function screenShot(){
    if (!win) {
        capturer().then(function(data) {
            win = createChildWin('/index.html', { fullscreen: true, alwaysOnTop: true, skipTaskbar: false, autoHideMenuBar: true, });
            // win.webContents.openDevTools()
        });
    }
    return win;
} 
2.在点击之后 对屏幕进行截屏
/**
 * 截取屏幕资源到本地
 */
function capturer() {
    return new Promise(function(resolve, reject) {
        desktopCapturer.getSources({ types: ['window', 'screen'], thumbnailSize: { width: w, height: h } }, (error, sources) => {
            if (error) console.error(error);
            localStorage['image'] = sources[0].thumbnail.toDataURL();
            resolve(sources[0].thumbnail.toDataURL())
        })
    })
}
3.创建渲染进程。

a.创建一个无边框全屏的渲染进程

var opts = { 
    fullscreen: true, 
    alwaysOnTop: true, 
    skipTaskbar: false, 
    autoHideMenuBar: true 
}
/**
 * 创建截屏窗口
 */
function createChildWin(_url, opts) {
    var config = {
        fullscreen: true,
        frame: false
    }
    config = Object.assign(config, opts)
    var _win = new BrowserWindow(config);
    _win.loadURL(url.format({
        pathname: path.join(__dirname + _url),
        protocol: 'file',
        slashes: true
    }))

    _win.on('closed', () => {
        _win = null;
    })
    _win.on('close', () => {
        _win = null;
    })
    return _win;
}

b.将第二步骤中截取的屏幕资源 加载到该渲染进程中的canvas中 剩下的都是canvas截图的操作

/*
 *
 *原理运用遮罩层,俩个canvas,底下为背景原图产生一个黑色背景画布,上层选区,将选中像素绘制到选区
 *鼠标按下移动鼠标产生一个矩形框,
 *
 */
 // 创建一个类
 class Screen {
    constructor(cas, casMask, src) {
        this.canvas = document.getElementById(cas);
        this.canvasMask = document.getElementById(casMask);

        this.context = this.canvas.getContext("2d");
        this.contextMask = this.canvasMask.getContext("2d");

        this.width = screen.width;
        this.height = screen.height;
        this.canvas.width = this.width;
        this.canvas.height = this.height;
        
        this.image = new Image();
        this.image.src = src;

        this.cuted = false;
        this.isShowTool = false;

        this.tool = document.querySelectorAll('.tool')[0];
        this.tip = document.querySelectorAll('.tipNum')[0];

        this.leftTopCursor = document.querySelectorAll('.left_top')[0];
        this.rightTopCursor = document.querySelectorAll('.right_top')[0];
        this.leftBottomCursor = document.querySelectorAll('.left_bottom')[0];
        this.rightBottomCursor = document.querySelectorAll('.right_bottom')[0];
        // 原本是将屏幕截图image画到this.context画布上的 
        //  不知道为何画出来的是空白的
        // 取而代之的方式是全屏一张图片
        document.getElementsByTagName('body')[0].appendChild(this.image);
        // this.drawImg(this.image); 
        this.createMask();
        this.getMouse();
        // 绑定this到原型链上
        this.drawImg = this.drawImg.bind(this)
        this.getMouse = this.getMouse.bind(this)
        this.clearCtx = this.clearCtx.bind(this)
        this.createRect = this.createRect.bind(this)
        this.createMask = this.createMask.bind(this)
        this.createReatImage = this.createReatImage.bind(this)
        this.tipShow = this.tipShow.bind(this)
        this.showTool = this.showTool.bind(this)
        this.hideTool = this.hideTool.bind(this)
        this.close = this.close.bind(this)
        this.sendMsg = this.sendMsg.bind(this)
        this.RGBA2ImageData = this.RGBA2ImageData.bind(this)
        this.dragEvent = this.dragEvent.bind(this)
    }
Viewing all 14821 articles
Browse latest View live