背景
功能要求:在项目的当前页面截图并对页面进行一些标注等操作,在按下确定按钮后将图片保存数据库
html2canvas
- 通过html2canvas进行截图然后编辑保存----kscreenshot
- kscreenshot使用html2canvas 升级版本到1.0.0-rc.7
缺点:
- 作者不建议在生产环境使用
- 对css3的动画样式不兼容(对动画进行替换如transition: left 2s;不适用all)
- 对iframe标签不支持出现空白(可以采用ngxin进行代理或是在截图前将iframe标签进行使用html2canavs先转化---但还是有出现iframe标签里的一些图片截不到空白情况)
- 对svg图标,视频等不兼容
- kscreenshot在线上不可以直接使用源码(会出现报错找不到此对象),修改源码后需要再次build后才可以使用build后的包或是再次发布npm通过下载引用
rasterizeHTML
缺点:
- 不支持canvas,video等
- 项目中使用比较多的canvas
\
google插件截图
思路
从当前页面点击后通过页面通知google插件进行截图,google插件的content脚本(此脚本不能直接条用一些google的方法如tabs对象下的)收到页面的消息后再通知google插件的background或是popup调用google的方法chrome.tabs.captureVisibleTab()进行截图,截完图后将图片返回和通知content脚本,由content脚本通知页面已经截完图,通过触发自定义事件,页面自定义的事件中监听收到后将图片放回kscreenshot进行截图
目录
├── background.js //事件页面(backgrund)
├── myscript.js //内容脚本(content)
├── popup.html //用户界面网页(popup不是必须的)
├── manifest.json //扩展程序的各种信息必须的,且是核心
├── static // 扩展的图标
│ ├── 48.png
manifest.json --核心文件
{
"name": "SmallScreenshot",// 插件名称
"description": "Quickly take screenshot of current tab",
"version": "0.1.5",
"manifest_version": 2,// 固定
"background": {//后台页面/事件页面(backgrund)
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [//内容脚本(content)
{
"js": ["myscript.js"],
"matches": ["http://*/*", "https://*/*","<all_urls>"]
}
],
"browser_action": { //用户界面网页(popup)
"default_icon": "static/128.png",
"default_title": "my Take Screenshot",
"default_popup": "popup.html" // 不允许内联JavaScript。
},
"icons": {
"48": "static/48.png",
"128": "static/128.png"
},
"permissions": ["downloads","alarms","<all_urls>"]
}
项目开发
Chrome插件可以分为三部分,分别运行在不同的环境。
后台页面/事件页面(background)
- 定义:顾名思义,后台网页是运行在浏览器后台的,随着浏览器的启动开始运行,浏览器关闭结束运行。 事件页面则是需要调用时加载,脚本空闲时被卸载,两者都是运行在后台。
- 调试backgrund:在扩展管理页面,在安装的扩展上有背景页按钮点击会弹出background页面的DevTools。
"background": {//后台页面/事件页面(backgrund)
"persistent": false,
"scripts": ["background.js"]
},
工具栏popup界面(popup)
- 定义:点击工具栏/地址栏(具体位置取决于配置文件)插件图标出来的弹窗其实就是一个html页面,弹窗要显示的文件,和工具栏小图标在manifest.json文件中配置。
调试popup:在工具栏的扩展小图标上右击选择审查弹出内容 会弹出Chrome的DevTools,调试方式和普通页面一样。
"browser_action": { //用户界面网页(popup)
"default_icon": "static/128.png",
"default_title": "my Take Screenshot",
"default_popup": "popup.html" // 不允许内联JavaScript。
},
内容脚本(content)
- 定义:安装插件后每打开一个网页可以将content脚本注入到页面中,内容脚本可以读取浏览器访问的网页的细节,并且可以修改页面。
- 调试content:content脚本是直接注入到页面中的所有直接在页面打开Devtools就能调试了。
"content_scripts": [//内容脚本(content)
{
"js": ["myscript.js"],
"matches": ["http://*/*", "https://*/*","<all_urls>"]
}
],
web页面与content,popup,background之间的通信
\
安装扩展
首先需要打开Chrome扩展管理页面打开开发者模式,普通模式下Chrome是禁止安装非商店下载的扩展的。
打开开发者模式后直接将crx/zip文件拖入浏览器即可安装。
也可以通过导航栏的加载已解压扩展程序来安装(需要解压zip文件)
1.如果使用zip包,打包要在manifest.json 的同一级别中压缩所有文件。
yourappfolder
|_manifest.json
|_popup.html
遇到的问题
- 报错:Unchecked runtime.lastError: The message port closed before a response was received.
Unchecked runtime.lastError:消息端口在收到响应之前关闭。
造成报错原因:chrome.runtime.sendMessage给background.js或是其他页面发送消息是,接收消息方即是chrome.runtime.onMessage.addListener的回调函数没有对发送消息这回复确认信息sendResponse()
解决方案通过接收方的chrome.runtime.onMessage.addListener的回调函数回复信息
// 发送方
chrome.runtime.sendMessage(null,JSON.stringify({ greeting: '你好,我是content-script呀,我主动发消息给后台!' }), function (response) {
// 收到浏览器后台的消息
console.log('截图完成', response);
});
//接收方
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
// 回复信息
sendResponse({ status: true });
});
- 截图到的图片不是当前窗口的或是截不到图
如果从popup或者background发送消息到content中需要先确认当前的content,使用chrome.tabs.query可以找到当前激活的窗口
/** * 获取具有指定属性的所有标签页,如果没有指定任何属性的话则获取所有标签页。
* @params {object} queryInfo
* @params {function} callback ( tab: []) => {}
*/
chrome.tabs.query(object queryInfo, function callback)
queryInfo = {
active: boolean, // 标签页在窗口中是否为活动标签页。
pinned: boolean, // 标签页是否固定。
highlighted: boolean, // 标签页是否高亮突出。
currentWindow: boolean, // 标签页是否在当前窗口中。
lastFocusedWindow: boolean, // 标签页是否在前一个具有焦点的窗口中。
status: enum['loading','complete'], // 标签页是否已经加载完成。
title: string, // 匹配页面标题的表达式。
url: string, // 匹配标签页的 URL 表达式。注意:片段标识符不会匹配
windowId: integer, // 父窗口标识符,或者为 windows.WINDOW_ID_CURRENT,表示当前窗口。
windowType: enum['normal','popup','panel','app'], // 标签页所在窗口的类型。
index: integer, // 标签页在窗口中的位置
}
// 通过window的id查找截图
chrome.tabs.query({}, function (tabs) {
if (!tabs.length || !t_sender) return;
//t_sender代码接收到请求的窗口信息
const curTab = tabs.find((item) => item.windowId === t_sender.tab.windowId);
chrome.tabs.captureVisibleTab(curTab.windowId, { format: 'png', quality: 100 }, function (image) {
chrome.tabs.sendMessage(t_sender.tab.id, { canvas: image }, function (response) {
console.log(response);
});
});
});