mirror of
https://github.com/fofolee/uTools-quickcommand.git
synced 2025-06-30 13:02:46 +08:00
增强截图功能:新增DOM元素选择器支持,优化截图参数配置
This commit is contained in:
parent
4805cf6716
commit
f4245a5744
@ -202,8 +202,8 @@ const initCDP = async (targetId) => {
|
|||||||
if (!clients.has(targetId)) {
|
if (!clients.has(targetId)) {
|
||||||
try {
|
try {
|
||||||
const client = await CDP({ target: targetId });
|
const client = await CDP({ target: targetId });
|
||||||
const { Page, Runtime, Target, Network, Emulation } = client;
|
const { Page, Runtime, Target, Network, Emulation, DOM } = client;
|
||||||
await Promise.all([Page.enable(), Runtime.enable()]);
|
await Promise.all([Page.enable(), Runtime.enable(), DOM.enable()]);
|
||||||
clients.set(targetId, {
|
clients.set(targetId, {
|
||||||
client,
|
client,
|
||||||
Page,
|
Page,
|
||||||
@ -211,6 +211,7 @@ const initCDP = async (targetId) => {
|
|||||||
Target,
|
Target,
|
||||||
Network,
|
Network,
|
||||||
Emulation,
|
Emulation,
|
||||||
|
DOM,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
@ -381,42 +382,75 @@ const getCookie = async (tab, name) => {
|
|||||||
// 捕获标签页截图
|
// 捕获标签页截图
|
||||||
const captureScreenshot = async (tab, options = {}) => {
|
const captureScreenshot = async (tab, options = {}) => {
|
||||||
const target = await searchTarget(tab);
|
const target = await searchTarget(tab);
|
||||||
const { format = "png", quality = 100, fullPage = false, savePath } = options;
|
const {
|
||||||
|
format = "png",
|
||||||
|
quality = 100,
|
||||||
|
savePath,
|
||||||
|
selector = null,
|
||||||
|
} = options;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const { Page, Emulation } = await initCDP(target.id);
|
const { Page, Emulation, DOM } = await initCDP(target.id);
|
||||||
|
await DOM.enable();
|
||||||
|
|
||||||
if (fullPage) {
|
let clip = null;
|
||||||
const metrics = await Page.getLayoutMetrics();
|
if (selector) {
|
||||||
const width = Math.max(
|
// 获取DOM节点
|
||||||
metrics.contentSize.width,
|
const { root } = await DOM.getDocument();
|
||||||
metrics.layoutViewport.clientWidth,
|
const { nodeId } = await DOM.querySelector({
|
||||||
metrics.visualViewport.clientWidth
|
nodeId: root.nodeId,
|
||||||
);
|
selector: selector,
|
||||||
const height = Math.max(
|
|
||||||
metrics.contentSize.height,
|
|
||||||
metrics.layoutViewport.clientHeight,
|
|
||||||
metrics.visualViewport.clientHeight
|
|
||||||
);
|
|
||||||
await Emulation.setDeviceMetricsOverride({
|
|
||||||
width,
|
|
||||||
height,
|
|
||||||
deviceScaleFactor: 1,
|
|
||||||
mobile: false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (!nodeId) {
|
||||||
|
throw new Error(`未找到元素: ${selector}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const { data } = await Page.captureScreenshot({
|
// 获取元素的精确四边形坐标
|
||||||
|
const { quads } = await DOM.getContentQuads({ nodeId });
|
||||||
|
if (!quads || quads.length === 0) {
|
||||||
|
throw new Error("无法获取元素位置信息");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取布局指标
|
||||||
|
const { visualViewport } = await Page.getLayoutMetrics();
|
||||||
|
const { pageX, pageY } = visualViewport;
|
||||||
|
|
||||||
|
// 计算边界框
|
||||||
|
const quad = quads[0];
|
||||||
|
const x = Math.min(quad[0], quad[2], quad[4], quad[6]);
|
||||||
|
const y = Math.min(quad[1], quad[3], quad[5], quad[7]);
|
||||||
|
const width = Math.max(quad[0], quad[2], quad[4], quad[6]) - x;
|
||||||
|
const height = Math.max(quad[1], quad[3], quad[5], quad[7]) - y;
|
||||||
|
|
||||||
|
clip = {
|
||||||
|
x: Math.round(x - pageX),
|
||||||
|
y: Math.round(y - pageY),
|
||||||
|
width: Math.round(width),
|
||||||
|
height: Math.round(height),
|
||||||
|
scale: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
// 确保尺寸不为0
|
||||||
|
if (clip.width === 0) clip.width = 1;
|
||||||
|
if (clip.height === 0) clip.height = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const screenshotParams = {
|
||||||
format,
|
format,
|
||||||
quality: format === "jpeg" ? quality : undefined,
|
quality: format === "jpeg" ? quality : undefined,
|
||||||
fromSurface: true,
|
fromSurface: true,
|
||||||
captureBeyondViewport: fullPage,
|
captureBeyondViewport: !!selector,
|
||||||
});
|
};
|
||||||
|
|
||||||
if (fullPage) {
|
if (clip) {
|
||||||
await Emulation.clearDeviceMetricsOverride();
|
screenshotParams.clip = clip;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { data } = await Page.captureScreenshot(screenshotParams);
|
||||||
|
|
||||||
|
await DOM.disable();
|
||||||
|
|
||||||
if (savePath) {
|
if (savePath) {
|
||||||
fs.writeFileSync(savePath, data, "base64");
|
fs.writeFileSync(savePath, data, "base64");
|
||||||
}
|
}
|
||||||
|
@ -183,6 +183,7 @@ export const browserCommands = {
|
|||||||
value: "quickcomposer.browser.captureScreenshot",
|
value: "quickcomposer.browser.captureScreenshot",
|
||||||
label: "捕获截图",
|
label: "捕获截图",
|
||||||
icon: "screenshot",
|
icon: "screenshot",
|
||||||
|
isAsync: true,
|
||||||
config: [
|
config: [
|
||||||
tabConfig,
|
tabConfig,
|
||||||
{
|
{
|
||||||
@ -191,37 +192,39 @@ export const browserCommands = {
|
|||||||
icon: "settings",
|
icon: "settings",
|
||||||
width: 12,
|
width: 12,
|
||||||
options: {
|
options: {
|
||||||
|
quality: {
|
||||||
|
label: "质量",
|
||||||
|
component: "NumberInput",
|
||||||
|
width: 2,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
},
|
||||||
|
selector: {
|
||||||
|
label: "指定元素(CSS选择器)",
|
||||||
|
component: "VariableInput",
|
||||||
|
icon: "code",
|
||||||
|
width: 10,
|
||||||
|
placeholder: "留空截取可视区域,截取整个页面可填body",
|
||||||
|
options: {
|
||||||
|
cssSelector: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
format: {
|
format: {
|
||||||
label: "格式",
|
label: "格式",
|
||||||
component: "QSelect",
|
component: "QSelect",
|
||||||
icon: "format",
|
width: 2,
|
||||||
width: 4,
|
|
||||||
options: [
|
options: [
|
||||||
{ label: "PNG", value: "png" },
|
{ label: "PNG", value: "png" },
|
||||||
{ label: "JPEG", value: "jpeg" },
|
{ label: "JPEG", value: "jpeg" },
|
||||||
{ label: "WebP", value: "webp" },
|
{ label: "WebP", value: "webp" },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
quality: {
|
|
||||||
label: "质量",
|
|
||||||
component: "NumberInput",
|
|
||||||
icon: "quality",
|
|
||||||
width: 4,
|
|
||||||
min: 0,
|
|
||||||
max: 100,
|
|
||||||
},
|
|
||||||
fullPage: {
|
|
||||||
label: "全屏截图",
|
|
||||||
component: "CheckButton",
|
|
||||||
icon: "fullscreen",
|
|
||||||
width: 4,
|
|
||||||
},
|
|
||||||
savePath: {
|
savePath: {
|
||||||
label: "保存路径",
|
label: "保存路径",
|
||||||
component: "VariableInput",
|
component: "VariableInput",
|
||||||
icon: "folder",
|
icon: "folder",
|
||||||
placeholder: "留空则不保存",
|
placeholder: "留空则不保存",
|
||||||
width: 12,
|
width: 10,
|
||||||
options: {
|
options: {
|
||||||
dialog: {
|
dialog: {
|
||||||
type: "save",
|
type: "save",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user