mirror of
https://gitee.com/bitdance-team/chrome-extension
synced 2025-10-07 16:35:15 +08:00
合并网页截图功能(张君秋的代码)
This commit is contained in:
@@ -24,8 +24,6 @@ let timer = null;
|
||||
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
||||
const { status, content } = message;
|
||||
|
||||
console.log(message);
|
||||
|
||||
if (status === "start") {
|
||||
// sendResponse({
|
||||
// status:message.status
|
||||
|
98
packages/shell-chrome/assets/html/screenshot/background.js
Normal file
98
packages/shell-chrome/assets/html/screenshot/background.js
Normal file
@@ -0,0 +1,98 @@
|
||||
// 设置截图方法和存储方法。
|
||||
chrome.storage.sync.get((config) => {
|
||||
chrome.storage.sync.set({ method: 'crop' });
|
||||
chrome.storage.sync.set({ format: 'png' });
|
||||
chrome.storage.sync.set({ save: 'file' });
|
||||
chrome.storage.sync.set({ dpr: true });
|
||||
if (config.save === 'clipboard') {
|
||||
config.save = 'url'
|
||||
chrome.storage.sync.set({ save: 'url' })
|
||||
}
|
||||
})
|
||||
// 定义inject函数,(点击图标就执行)
|
||||
function inject(tab) {
|
||||
|
||||
chrome.tabs.sendMessage(tab.id, { message: 'init' }, (res) => {
|
||||
if (res) {
|
||||
// 停止植入css和js文件。
|
||||
clearTimeout(timeout)
|
||||
}
|
||||
})
|
||||
|
||||
// 植入css和js文件
|
||||
var timeout = setTimeout(() => {
|
||||
var relativePath = 'assets/html/screenshot/'
|
||||
chrome.tabs.insertCSS(tab.id, { file: relativePath + 'css/jquery.Jcrop.min.css', runAt: 'document_start' })
|
||||
chrome.tabs.insertCSS(tab.id, { file: relativePath + 'css/content.css', runAt: 'document_start' })
|
||||
chrome.tabs.executeScript(tab.id, { file: relativePath + 'js/jquery.min.js', runAt: 'document_start' })
|
||||
chrome.tabs.executeScript(tab.id, { file: relativePath + 'js/jquery.Jcrop.min.js', runAt: 'document_start' })
|
||||
chrome.tabs.executeScript(tab.id, { file: relativePath + 'js/content.js', runAt: 'document_start' })
|
||||
// 间隔发送"init"message
|
||||
setTimeout(() => {
|
||||
chrome.tabs.sendMessage(tab.id, { message: 'init' })
|
||||
}, 100)
|
||||
}, 100)
|
||||
}
|
||||
|
||||
var takeScreenshot = inject
|
||||
|
||||
chrome.runtime.onMessage.addListener((req, sender, res) => {
|
||||
if (req.message === 'capture') {
|
||||
chrome.storage.sync.get((config) => {
|
||||
chrome.tabs.getSelected(null, (tab) => {
|
||||
chrome.tabs.captureVisibleTab(tab.windowId, { format: config.format }, (image) => {
|
||||
// 整个网页截图
|
||||
// console.log("image", image);
|
||||
crop(image, req.area, req.dpr, config.dpr, config.format, (cropped) => {
|
||||
// 裁剪后
|
||||
// console.log("cropped", cropped)
|
||||
res({ message: 'image', image: cropped })
|
||||
})
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
else if (req.message === 'active') {
|
||||
if (req.active) {
|
||||
chrome.browserAction.setTitle({ tabId: sender.tab.id, title: 'Crop and Save' })
|
||||
// chrome.browserAction.setBadgeText({tabId: sender.tab.id, text: '◩'})
|
||||
}
|
||||
else {
|
||||
chrome.browserAction.setTitle({ tabId: sender.tab.id, title: 'Screenshot Capture' })
|
||||
// chrome.browserAction.setBadgeText({tabId: sender.tab.id, text: ''})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
function crop(image, area, dpr, preserve, format, done) {
|
||||
var top = area.y * dpr
|
||||
var left = area.x * dpr
|
||||
var width = area.w * dpr
|
||||
var height = area.h * dpr
|
||||
var w = (dpr !== 1 && preserve) ? width : area.w
|
||||
var h = (dpr !== 1 && preserve) ? height : area.h
|
||||
|
||||
var canvas = null
|
||||
if (!canvas) {
|
||||
canvas = document.createElement('canvas')
|
||||
document.body.appendChild(canvas)
|
||||
}
|
||||
canvas.width = w
|
||||
canvas.height = h
|
||||
|
||||
var img = new Image()
|
||||
img.onload = () => {
|
||||
var context = canvas.getContext('2d')
|
||||
context.drawImage(img,
|
||||
left, top,
|
||||
width, height,
|
||||
0, 0,
|
||||
w, h
|
||||
)
|
||||
|
||||
var cropped = canvas.toDataURL(`image/${format}`)
|
||||
done(cropped)
|
||||
}
|
||||
img.src = image
|
||||
}
|
18
packages/shell-chrome/assets/html/screenshot/css/content.css
Normal file
18
packages/shell-chrome/assets/html/screenshot/css/content.css
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
img#fake-image,
|
||||
.jcrop-holder,
|
||||
.jcrop-holder img,
|
||||
.jcrop-tracker {
|
||||
width: 100% !important; height: 100% !important;
|
||||
max-width: 100% !important; max-height: 100% !important;
|
||||
min-width: 100% !important; min-height: 100% !important;
|
||||
}
|
||||
|
||||
img#fake-image {
|
||||
position: fixed; top: 0; left: 0; z-index: 1;
|
||||
}
|
||||
|
||||
.jcrop-holder {
|
||||
position: fixed !important; top: 0 !important; left: 0 !important;
|
||||
z-index: 2147483647 !important;
|
||||
}
|
BIN
packages/shell-chrome/assets/html/screenshot/css/icons.ttf
Normal file
BIN
packages/shell-chrome/assets/html/screenshot/css/icons.ttf
Normal file
Binary file not shown.
146
packages/shell-chrome/assets/html/screenshot/css/jquery.Jcrop.min.css
vendored
Normal file
146
packages/shell-chrome/assets/html/screenshot/css/jquery.Jcrop.min.css
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
/* jquery.Jcrop.min.css v0.9.12 (build:20140524) */
|
||||
.jcrop-holder {
|
||||
direction: ltr;
|
||||
text-align: left;
|
||||
-ms-touch-action: none;
|
||||
}
|
||||
.jcrop-hline,
|
||||
.jcrop-vline {
|
||||
background-color: #fff;
|
||||
font-size: 0;
|
||||
position: absolute;
|
||||
}
|
||||
.jcrop-vline {
|
||||
height: 100%;
|
||||
width: 1px !important;
|
||||
}
|
||||
.jcrop-vline.right {
|
||||
right: 0;
|
||||
}
|
||||
.jcrop-hline {
|
||||
height: 1px !important;
|
||||
width: 100%;
|
||||
}
|
||||
.jcrop-hline.bottom {
|
||||
bottom: 0;
|
||||
}
|
||||
.jcrop-tracker {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
-webkit-tap-highlight-color: transparent;
|
||||
-webkit-touch-callout: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
.jcrop-handle {
|
||||
background-color: #333;
|
||||
border: 1px #eee solid;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
font-size: 1px;
|
||||
}
|
||||
.jcrop-handle.ord-n {
|
||||
left: 50%;
|
||||
margin-left: -4px;
|
||||
margin-top: -4px;
|
||||
top: 0;
|
||||
}
|
||||
.jcrop-handle.ord-s {
|
||||
bottom: 0;
|
||||
left: 50%;
|
||||
margin-bottom: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
.jcrop-handle.ord-e {
|
||||
margin-right: -4px;
|
||||
margin-top: -4px;
|
||||
right: 0;
|
||||
top: 50%;
|
||||
}
|
||||
.jcrop-handle.ord-w {
|
||||
left: 0;
|
||||
margin-left: -4px;
|
||||
margin-top: -4px;
|
||||
top: 50%;
|
||||
}
|
||||
.jcrop-handle.ord-nw {
|
||||
left: 0;
|
||||
margin-left: -4px;
|
||||
margin-top: -4px;
|
||||
top: 0;
|
||||
}
|
||||
.jcrop-handle.ord-ne {
|
||||
margin-right: -4px;
|
||||
margin-top: -4px;
|
||||
right: 0;
|
||||
top: 0;
|
||||
}
|
||||
.jcrop-handle.ord-se {
|
||||
bottom: 0;
|
||||
margin-bottom: -4px;
|
||||
margin-right: -4px;
|
||||
right: 0;
|
||||
}
|
||||
.jcrop-handle.ord-sw {
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
margin-bottom: -4px;
|
||||
margin-left: -4px;
|
||||
}
|
||||
.jcrop-dragbar.ord-n,
|
||||
.jcrop-dragbar.ord-s {
|
||||
height: 7px;
|
||||
width: 100%;
|
||||
}
|
||||
.jcrop-dragbar.ord-e,
|
||||
.jcrop-dragbar.ord-w {
|
||||
height: 100%;
|
||||
width: 7px;
|
||||
}
|
||||
.jcrop-dragbar.ord-n {
|
||||
margin-top: -4px;
|
||||
}
|
||||
.jcrop-dragbar.ord-s {
|
||||
bottom: 0;
|
||||
margin-bottom: -4px;
|
||||
}
|
||||
.jcrop-dragbar.ord-e {
|
||||
margin-right: -4px;
|
||||
right: 0;
|
||||
}
|
||||
.jcrop-dragbar.ord-w {
|
||||
margin-left: -4px;
|
||||
}
|
||||
.jcrop-light .jcrop-hline,
|
||||
.jcrop-light .jcrop-vline {
|
||||
background: #fff;
|
||||
filter: alpha(opacity=70) !important;
|
||||
opacity: 0.7 !important;
|
||||
}
|
||||
.jcrop-light .jcrop-handle {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
background-color: #000;
|
||||
border-color: #fff;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.jcrop-dark .jcrop-hline,
|
||||
.jcrop-dark .jcrop-vline {
|
||||
background: #000;
|
||||
filter: alpha(opacity=70) !important;
|
||||
opacity: 0.7 !important;
|
||||
}
|
||||
.jcrop-dark .jcrop-handle {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
background-color: #fff;
|
||||
border-color: #000;
|
||||
border-radius: 3px;
|
||||
}
|
||||
.solid-line .jcrop-hline,
|
||||
.solid-line .jcrop-vline {
|
||||
background: #fff;
|
||||
}
|
||||
.jcrop-holder img,
|
||||
img.jcrop-preview {
|
||||
max-width: none;
|
||||
}
|
BIN
packages/shell-chrome/assets/html/screenshot/images/Jcrop.gif
Normal file
BIN
packages/shell-chrome/assets/html/screenshot/images/Jcrop.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 329 B |
BIN
packages/shell-chrome/assets/html/screenshot/images/pixel.png
Normal file
BIN
packages/shell-chrome/assets/html/screenshot/images/pixel.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 68 B |
123
packages/shell-chrome/assets/html/screenshot/js/content.js
Normal file
123
packages/shell-chrome/assets/html/screenshot/js/content.js
Normal file
@@ -0,0 +1,123 @@
|
||||
|
||||
var jcrop,selection
|
||||
var relativePath = 'assets/html/screenshot'
|
||||
|
||||
var overlay = ((active) => (state) => {
|
||||
active = typeof state === 'boolean' ? state : state === null ? active : !active
|
||||
$('.jcrop-holder')[active ? 'show' : 'hide']()
|
||||
chrome.runtime.sendMessage({message: 'active', active})
|
||||
})(false)
|
||||
|
||||
var image = (done) => {
|
||||
var image = new Image()
|
||||
image.id = 'fake-image'
|
||||
image.src = chrome.runtime.getURL(relativePath + '/images/pixel.png')
|
||||
image.onload = () => {
|
||||
$('body').append(image)
|
||||
done()
|
||||
}
|
||||
}
|
||||
|
||||
var init = (done) => {
|
||||
$('#fake-image').Jcrop({
|
||||
bgColor: 'none',
|
||||
onSelect: (e) => {
|
||||
selection = e
|
||||
capture()
|
||||
},
|
||||
onChange: (e) => {
|
||||
selection = e
|
||||
},
|
||||
onRelease: (e) => {
|
||||
setTimeout(() => {
|
||||
selection = null
|
||||
}, 100)
|
||||
}
|
||||
}, function ready () {
|
||||
jcrop = this
|
||||
|
||||
$('.jcrop-hline, .jcrop-vline').css({
|
||||
backgroundImage: `url(${chrome.runtime.getURL(relativePath + '/images/Jcrop.gif')})`
|
||||
})
|
||||
|
||||
if (selection) {
|
||||
jcrop.setSelect([
|
||||
selection.x, selection.y,
|
||||
selection.x2, selection.y2
|
||||
])
|
||||
}
|
||||
|
||||
done && done()
|
||||
})
|
||||
}
|
||||
|
||||
var capture = (force) => {
|
||||
chrome.storage.sync.get((config) => {
|
||||
if (selection && (config.method === 'crop' || (config.method === 'wait' && force))) {
|
||||
jcrop.release()
|
||||
setTimeout(() => {
|
||||
chrome.runtime.sendMessage({
|
||||
message: 'capture', area: selection, dpr: devicePixelRatio
|
||||
}, (res) => {
|
||||
console.log("res: ", res)
|
||||
overlay(false)
|
||||
selection = null
|
||||
save(res.image, config.format, config.save)
|
||||
})
|
||||
}, 50)
|
||||
}
|
||||
else if (config.method === 'view') {
|
||||
chrome.runtime.sendMessage({
|
||||
message: 'capture',
|
||||
area: {x: 0, y: 0, w: innerWidth, h: innerHeight}, dpr: devicePixelRatio
|
||||
}, (res) => {
|
||||
overlay(false)
|
||||
save(res.image, config.format, config.save)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var filename = (format) => {
|
||||
var pad = (n) => (n = n + '', n.length >= 2 ? n : `0${n}`)
|
||||
var ext = (format) => format === 'jpeg' ? 'jpg' : format === 'png' ? 'png' : 'png'
|
||||
var timestamp = (now) =>
|
||||
[pad(now.getFullYear()), pad(now.getMonth() + 1), pad(now.getDate())].join('-')
|
||||
+ ' - ' +
|
||||
[pad(now.getHours()), pad(now.getMinutes()), pad(now.getSeconds())].join('-')
|
||||
return `Screenshot Capture - ${timestamp(new Date())}.${ext(format)}`
|
||||
}
|
||||
|
||||
var save = (image, format, save) => {
|
||||
var link = document.createElement('a')
|
||||
link.download = filename(format)
|
||||
link.href = image
|
||||
link.click()
|
||||
|
||||
}
|
||||
|
||||
window.addEventListener('resize', ((timeout) => () => {
|
||||
clearTimeout(timeout)
|
||||
timeout = setTimeout(() => {
|
||||
jcrop.destroy()
|
||||
init(() => overlay(null))
|
||||
}, 100)
|
||||
})())
|
||||
|
||||
chrome.runtime.onMessage.addListener((req, sender, res) => {
|
||||
if (req.message === 'init') {
|
||||
res({}) // prevent re-injecting
|
||||
|
||||
if (!jcrop) {
|
||||
image(() => init(() => {
|
||||
overlay()
|
||||
capture()
|
||||
}))
|
||||
}
|
||||
else {
|
||||
overlay()
|
||||
capture(true)
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
7
packages/shell-chrome/assets/html/screenshot/js/jquery.Jcrop.min.js
vendored
Normal file
7
packages/shell-chrome/assets/html/screenshot/js/jquery.Jcrop.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
4
packages/shell-chrome/assets/html/screenshot/js/jquery.min.js
vendored
Normal file
4
packages/shell-chrome/assets/html/screenshot/js/jquery.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
36
packages/shell-chrome/assets/html/screenshot/manifest.json
Normal file
36
packages/shell-chrome/assets/html/screenshot/manifest.json
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
"manifest_version": 2,
|
||||
"name" : "Screenshot Capture",
|
||||
"version" : "2.0",
|
||||
"description" : "Screenshot Capture",
|
||||
|
||||
"browser_action": {
|
||||
|
||||
"default_title": "Screenshot Capture"
|
||||
},
|
||||
|
||||
"background" : {
|
||||
"scripts": [
|
||||
"background.js"
|
||||
],
|
||||
"persistent": false
|
||||
},
|
||||
|
||||
"web_accessible_resources": [
|
||||
"/images/Jcrop.gif",
|
||||
"/images/pixel.png"
|
||||
],
|
||||
|
||||
"commands": {
|
||||
"take-screenshot": {
|
||||
"suggested_key": {
|
||||
"default": "Alt+S"
|
||||
},
|
||||
"description": "Take Screenshot"
|
||||
}
|
||||
},
|
||||
"permissions": [
|
||||
"storage",
|
||||
"activeTab"
|
||||
]
|
||||
}
|
@@ -1,30 +1,34 @@
|
||||
chrome.contextMenus.create({
|
||||
id: 'bitdance',
|
||||
title: '学生助手'
|
||||
id: 'bitdance',
|
||||
title: '学生助手'
|
||||
})
|
||||
|
||||
// chrome.contextMenus.onClicked.addListener(function (info) {
|
||||
// alert('当前菜单信息:'+ JSON.stringify(info))
|
||||
// })
|
||||
|
||||
// 打印消息日志
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
console.log("request", request, "path", sender.url.replace(sender.origin, ""), "sender", sender, "sendResponse", sendResponse);
|
||||
})
|
||||
|
||||
|
||||
//refer: https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/mv2-archive/api/notifications/background.js
|
||||
function showNotification() {
|
||||
var time = /(..)(:..)/.exec(new Date()); // The prettyprinted time.
|
||||
var hour = time[1] % 12 || 12; // The prettyprinted hour.
|
||||
var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day.
|
||||
new Notification(hour + time[2] + ' ' + period, {
|
||||
icon: '48.png',
|
||||
body: 'Time to make the toast.'
|
||||
});
|
||||
var time = /(..)(:..)/.exec(new Date()); // The prettyprinted time.
|
||||
var hour = time[1] % 12 || 12; // The prettyprinted hour.
|
||||
var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day.
|
||||
new Notification(hour + time[2] + ' ' + period, {
|
||||
icon: '48.png',
|
||||
body: 'Time to make the toast.'
|
||||
});
|
||||
}
|
||||
|
||||
chrome.contextMenus.create({
|
||||
id: 'bitdance-advanced-search-notification',
|
||||
title: 'Notification',
|
||||
parentId: 'bitdance',
|
||||
onclick: function (info) {
|
||||
showNotification()
|
||||
}
|
||||
id: 'bitdance-advanced-search-notification',
|
||||
title: 'Notification',
|
||||
parentId: 'bitdance',
|
||||
onclick: function (info) {
|
||||
showNotification()
|
||||
}
|
||||
})
|
@@ -7,9 +7,10 @@ $(function() {
|
||||
|
||||
// 每次改变开关状态时刷新页面使功能及时生效
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
console.log('click');
|
||||
location.reload();
|
||||
sendResponse('Reload page');
|
||||
// TODO: 这里不能这么写,否则会导致其他模块发送消息时触发页面刷新
|
||||
// console.log('click');
|
||||
// location.reload();
|
||||
// sendResponse('Reload page');
|
||||
})
|
||||
|
||||
// 控制功能是否开启
|
||||
|
@@ -6,9 +6,10 @@ $(function() {
|
||||
console.log("[BitDance extension] 学生助手插件 - 鼠标样式模块加载成功");
|
||||
// 每次改变开关状态时刷新页面使功能及时生效
|
||||
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
||||
console.log('mouse');
|
||||
location.reload();
|
||||
sendResponse('Reload page');
|
||||
// TODO: 这里不能这么写,否则会导致其他模块发送消息时触发页面刷新
|
||||
// console.log('mouse');
|
||||
// location.reload();
|
||||
// sendResponse('Reload page');
|
||||
})
|
||||
|
||||
// 控制功能是否开启
|
||||
|
@@ -71,4 +71,11 @@ $(function() {
|
||||
btnDirectUrl.addEventListener("change", () => {
|
||||
chrome.storage.sync.set({ linkOpen: !btnDirectUrl.checked });
|
||||
});
|
||||
|
||||
// 截图
|
||||
document.getElementById("btnScreenshot").addEventListener("click", () => {
|
||||
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
|
||||
chrome.extension.getBackgroundPage().takeScreenshot(tabs[0]);
|
||||
})
|
||||
});
|
||||
})
|
||||
|
@@ -16,7 +16,8 @@
|
||||
"assets/js/lib/jquery.min.js",
|
||||
"assets/js/background.js",
|
||||
"assets/html/pomodoro/background.js",
|
||||
"assets/js/advanced-search/background.js"
|
||||
"assets/js/advanced-search/background.js",
|
||||
"assets/html/screenshot/background.js"
|
||||
]
|
||||
},
|
||||
"content_scripts": [
|
||||
@@ -91,7 +92,7 @@
|
||||
"browser_action": {
|
||||
"default_icon": "assets/image/logo.png",
|
||||
"default_popup": "popup.html",
|
||||
"default_title": "学生助手"
|
||||
"default_title": "召唤“学生助手” (Alt+,)"
|
||||
},
|
||||
"commands": {
|
||||
"_execute_browser_action": {
|
||||
@@ -103,17 +104,15 @@
|
||||
}
|
||||
},
|
||||
"web_accessible_resources": [
|
||||
"/assets/image/*"
|
||||
"/assets/image/*",
|
||||
"/assets/html/screenshot/images/*"
|
||||
],
|
||||
"permissions": [
|
||||
"background",
|
||||
"contextMenus",
|
||||
"storage",
|
||||
"unlimitedStorage",
|
||||
"webRequest",
|
||||
"webRequestBlocking",
|
||||
"tabs",
|
||||
"storage",
|
||||
"activeTab",
|
||||
"notifications"
|
||||
]
|
||||
|
@@ -50,6 +50,7 @@
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<button id="btnScreenshot">截图</button>
|
||||
<iframe src="assets/html/pomodoro/popup.html" id="pomodoro" style="border: 0; height: 400px;"></iframe>
|
||||
</div>
|
||||
<script src="assets/js/lib/jquery.min.js"></script>
|
||||
|
Reference in New Issue
Block a user