1
0
mirror of https://gitee.com/bitdance-team/chrome-extension synced 2025-10-07 16:35:15 +08:00
Code Issues Projects Releases Wiki Activity GitHub Gitee

合并网页截图功能(张君秋的代码)

This commit is contained in:
2022-02-06 00:37:31 +08:00
parent 4f2a2acf81
commit 82304cc5a8
18 changed files with 476 additions and 33 deletions

View File

@@ -24,8 +24,6 @@ let timer = null;
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => { chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
const { status, content } = message; const { status, content } = message;
console.log(message);
if (status === "start") { if (status === "start") {
// sendResponse({ // sendResponse({
// status:message.status // status:message.status

View 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
}

View 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;
}

View 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;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 68 B

View 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
})

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View 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"
]
}

View File

@@ -1,30 +1,34 @@
chrome.contextMenus.create({ chrome.contextMenus.create({
id: 'bitdance', id: 'bitdance',
title: '学生助手' title: '学生助手'
}) })
// chrome.contextMenus.onClicked.addListener(function (info) { // chrome.contextMenus.onClicked.addListener(function (info) {
// alert('当前菜单信息:'+ JSON.stringify(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 //refer: https://github.com/GoogleChrome/chrome-extensions-samples/blob/main/mv2-archive/api/notifications/background.js
function showNotification() { function showNotification() {
var time = /(..)(:..)/.exec(new Date()); // The prettyprinted time. var time = /(..)(:..)/.exec(new Date()); // The prettyprinted time.
var hour = time[1] % 12 || 12; // The prettyprinted hour. var hour = time[1] % 12 || 12; // The prettyprinted hour.
var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day. var period = time[1] < 12 ? 'a.m.' : 'p.m.'; // The period of the day.
new Notification(hour + time[2] + ' ' + period, { new Notification(hour + time[2] + ' ' + period, {
icon: '48.png', icon: '48.png',
body: 'Time to make the toast.' body: 'Time to make the toast.'
}); });
} }
chrome.contextMenus.create({ chrome.contextMenus.create({
id: 'bitdance-advanced-search-notification', id: 'bitdance-advanced-search-notification',
title: 'Notification', title: 'Notification',
parentId: 'bitdance', parentId: 'bitdance',
onclick: function (info) { onclick: function (info) {
showNotification() showNotification()
} }
}) })

View File

@@ -1 +1 @@
console.log("[BitDance extension] 学生助手插件已启用") console.log("[BitDance extension] 学生助手插件已启用")

View File

@@ -7,9 +7,10 @@ $(function() {
// 每次改变开关状态时刷新页面使功能及时生效 // 每次改变开关状态时刷新页面使功能及时生效
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('click'); // TODO: 这里不能这么写,否则会导致其他模块发送消息时触发页面刷新
location.reload(); // console.log('click');
sendResponse('Reload page'); // location.reload();
// sendResponse('Reload page');
}) })
// 控制功能是否开启 // 控制功能是否开启
@@ -92,4 +93,4 @@ $(function() {
} }
} }
}); });
}) })

View File

@@ -6,9 +6,10 @@ $(function() {
console.log("[BitDance extension] 学生助手插件 - 鼠标样式模块加载成功"); console.log("[BitDance extension] 学生助手插件 - 鼠标样式模块加载成功");
// 每次改变开关状态时刷新页面使功能及时生效 // 每次改变开关状态时刷新页面使功能及时生效
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => { chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('mouse'); // TODO: 这里不能这么写,否则会导致其他模块发送消息时触发页面刷新
location.reload(); // console.log('mouse');
sendResponse('Reload page'); // location.reload();
// sendResponse('Reload page');
}) })
// 控制功能是否开启 // 控制功能是否开启
@@ -24,4 +25,4 @@ $(function() {
}); });
} }
}) })
}) })

View File

@@ -71,4 +71,11 @@ $(function() {
btnDirectUrl.addEventListener("change", () => { btnDirectUrl.addEventListener("change", () => {
chrome.storage.sync.set({ linkOpen: !btnDirectUrl.checked }); 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]);
})
});
}) })

View File

@@ -16,7 +16,8 @@
"assets/js/lib/jquery.min.js", "assets/js/lib/jquery.min.js",
"assets/js/background.js", "assets/js/background.js",
"assets/html/pomodoro/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": [ "content_scripts": [
@@ -91,7 +92,7 @@
"browser_action": { "browser_action": {
"default_icon": "assets/image/logo.png", "default_icon": "assets/image/logo.png",
"default_popup": "popup.html", "default_popup": "popup.html",
"default_title": "学生助手" "default_title": "召唤“学生助手” (Alt+,)"
}, },
"commands": { "commands": {
"_execute_browser_action": { "_execute_browser_action": {
@@ -103,17 +104,15 @@
} }
}, },
"web_accessible_resources": [ "web_accessible_resources": [
"/assets/image/*" "/assets/image/*",
"/assets/html/screenshot/images/*"
], ],
"permissions": [ "permissions": [
"background", "background",
"contextMenus", "contextMenus",
"storage", "storage",
"unlimitedStorage",
"webRequest", "webRequest",
"webRequestBlocking",
"tabs", "tabs",
"storage",
"activeTab", "activeTab",
"notifications" "notifications"
] ]

View File

@@ -50,6 +50,7 @@
</li> </li>
</ul> </ul>
</div> </div>
<button id="btnScreenshot">截图</button>
<iframe src="assets/html/pomodoro/popup.html" id="pomodoro" style="border: 0; height: 400px;"></iframe> <iframe src="assets/html/pomodoro/popup.html" id="pomodoro" style="border: 0; height: 400px;"></iframe>
</div> </div>
<script src="assets/js/lib/jquery.min.js"></script> <script src="assets/js/lib/jquery.min.js"></script>