xw-devtool-cli 1.0.27 → 1.0.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -0
- package/README_EN.md +2 -0
- package/package.json +4 -2
- package/src/commands/pixelDistance.js +167 -0
- package/src/commands/screenMark.js +169 -0
- package/src/index.js +10 -0
- package/src/locales/en.js +10 -0
- package/src/locales/zh.js +6 -0
package/README.md
CHANGED
|
@@ -22,6 +22,8 @@
|
|
|
22
22
|
> 3. 取色模式下会显示全屏十字辅助线,按 **回车键** 退出模式。
|
|
23
23
|
- **占位图生成**:快速生成指定尺寸、颜色、文字的占位图片 (Placeholder Image)。
|
|
24
24
|
- **全屏十字辅助线**:显示跟随鼠标的全屏红色十字线,用于屏幕对齐和定位。
|
|
25
|
+
- **屏幕测距**:点击屏幕上任意两点,测量其像素距离。
|
|
26
|
+
- **屏幕文字标注**:在屏幕上点击并输入文字,进行临时标注。右键撤销,Delete 清空。
|
|
25
27
|
- **Mock 数据生成**:
|
|
26
28
|
- 支持生成:英文段落 (Lorem Ipsum)、中文字符、中国居民身份证号、电子邮箱、URL、订单号、手机号、座机号。
|
|
27
29
|
- 支持批量生成。
|
package/README_EN.md
CHANGED
|
@@ -17,6 +17,8 @@ Key features include: Base64 encoding/decoding, image format conversion, image <
|
|
|
17
17
|
- **Color Picker**: Pick a single pixel color or area average from an image; supports px/% coordinates; shows preview bar and auto-copies Hex/Hex8.
|
|
18
18
|
- **Screen Picker**: Pick color directly from the screen at the mouse position; move the cursor and press Enter to sample; supports alpha preview.
|
|
19
19
|
- **Screen Crosshair**: Display a full-screen red crosshair following the mouse for alignment.
|
|
20
|
+
- **Pixel Distance**: Measure pixel distance between two points on the screen.
|
|
21
|
+
- **Screen Mark**: Click on the screen to add text annotations. Right-click to undo, Delete to clear.
|
|
20
22
|
- **Mock Data**:
|
|
21
23
|
- Generate: Lorem Ipsum, Chinese characters, ID cards, Emails, URLs, Order IDs, Phone numbers.
|
|
22
24
|
- Supports batch generation.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xw-devtool-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "基于node的开发者助手cli",
|
|
6
6
|
"main": "index.js",
|
|
@@ -49,7 +49,9 @@
|
|
|
49
49
|
"md5",
|
|
50
50
|
"color-converter",
|
|
51
51
|
"emoji",
|
|
52
|
-
"markdown"
|
|
52
|
+
"markdown",
|
|
53
|
+
"screen-mark",
|
|
54
|
+
"pixel-distance"
|
|
53
55
|
],
|
|
54
56
|
"author": "npmxw",
|
|
55
57
|
"license": "ISC",
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import i18next from '../i18n.js';
|
|
3
|
+
|
|
4
|
+
export async function pixelDistanceHandler() {
|
|
5
|
+
if (process.platform !== 'win32') {
|
|
6
|
+
console.log(i18next.t('pixelDistance.notSupported'));
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
console.log(i18next.t('pixelDistance.startPrompt'));
|
|
11
|
+
|
|
12
|
+
const overlayScript = `
|
|
13
|
+
Add-Type -AssemblyName System.Windows.Forms;
|
|
14
|
+
Add-Type -AssemblyName System.Drawing;
|
|
15
|
+
|
|
16
|
+
Add-Type -TypeDefinition @'
|
|
17
|
+
using System;
|
|
18
|
+
using System.Drawing;
|
|
19
|
+
using System.Windows.Forms;
|
|
20
|
+
using System.Runtime.InteropServices;
|
|
21
|
+
|
|
22
|
+
public class DistanceForm : Form {
|
|
23
|
+
private Point p1 = Point.Empty;
|
|
24
|
+
private Point p2 = Point.Empty;
|
|
25
|
+
private bool p1Set = false;
|
|
26
|
+
private bool p2Set = false;
|
|
27
|
+
private Bitmap screenCapture;
|
|
28
|
+
|
|
29
|
+
public DistanceForm() {
|
|
30
|
+
this.FormBorderStyle = FormBorderStyle.None;
|
|
31
|
+
this.TopMost = true;
|
|
32
|
+
this.Cursor = Cursors.Cross;
|
|
33
|
+
this.DoubleBuffered = true;
|
|
34
|
+
|
|
35
|
+
// Calculate total bounds
|
|
36
|
+
Rectangle totalBounds = Rectangle.Empty;
|
|
37
|
+
foreach(Screen s in Screen.AllScreens) {
|
|
38
|
+
totalBounds = Rectangle.Union(totalBounds, s.Bounds);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
this.StartPosition = FormStartPosition.Manual;
|
|
42
|
+
this.Bounds = totalBounds;
|
|
43
|
+
|
|
44
|
+
// Capture screen
|
|
45
|
+
screenCapture = new Bitmap(totalBounds.Width, totalBounds.Height);
|
|
46
|
+
using (Graphics g = Graphics.FromImage(screenCapture)) {
|
|
47
|
+
g.CopyFromScreen(totalBounds.Location, Point.Empty, totalBounds.Size);
|
|
48
|
+
}
|
|
49
|
+
this.BackgroundImage = screenCapture;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private Point GetSnappedPoint(Point current) {
|
|
53
|
+
if (!p1Set) return current;
|
|
54
|
+
|
|
55
|
+
Point snapped = current;
|
|
56
|
+
int threshold = 5; // Snap threshold in pixels
|
|
57
|
+
|
|
58
|
+
// Check horizontal snap (same Y)
|
|
59
|
+
if (Math.Abs(current.Y - p1.Y) < threshold) {
|
|
60
|
+
snapped.Y = p1.Y;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Check vertical snap (same X)
|
|
64
|
+
if (Math.Abs(current.X - p1.X) < threshold) {
|
|
65
|
+
snapped.X = p1.X;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return snapped;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
protected override void OnMouseDown(MouseEventArgs e) {
|
|
72
|
+
if (e.Button == MouseButtons.Right) {
|
|
73
|
+
// Reset
|
|
74
|
+
p1Set = false;
|
|
75
|
+
p2Set = false;
|
|
76
|
+
this.Invalidate();
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (e.Button == MouseButtons.Left) {
|
|
81
|
+
if (!p1Set) {
|
|
82
|
+
p1 = e.Location;
|
|
83
|
+
p1Set = true;
|
|
84
|
+
} else if (!p2Set) {
|
|
85
|
+
p2 = GetSnappedPoint(e.Location);
|
|
86
|
+
p2Set = true;
|
|
87
|
+
} else {
|
|
88
|
+
// Start over from new point
|
|
89
|
+
p1 = e.Location;
|
|
90
|
+
p1Set = true;
|
|
91
|
+
p2Set = false;
|
|
92
|
+
}
|
|
93
|
+
this.Invalidate();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
protected override void OnMouseMove(MouseEventArgs e) {
|
|
98
|
+
if (p1Set && !p2Set) {
|
|
99
|
+
this.Invalidate();
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
protected override void OnPaint(PaintEventArgs e) {
|
|
104
|
+
Graphics g = e.Graphics;
|
|
105
|
+
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
106
|
+
|
|
107
|
+
Pen pen = new Pen(Color.Red, 2);
|
|
108
|
+
Brush brush = Brushes.Red;
|
|
109
|
+
Font font = new Font("Segoe UI", 12, FontStyle.Bold);
|
|
110
|
+
Brush textBg = new SolidBrush(Color.FromArgb(180, 0, 0, 0));
|
|
111
|
+
|
|
112
|
+
if (p1Set) {
|
|
113
|
+
Point target = p2Set ? p2 : GetSnappedPoint(this.PointToClient(Cursor.Position));
|
|
114
|
+
|
|
115
|
+
// Draw line
|
|
116
|
+
g.DrawLine(pen, p1, target);
|
|
117
|
+
|
|
118
|
+
// Draw points
|
|
119
|
+
g.FillEllipse(brush, p1.X - 4, p1.Y - 4, 8, 8);
|
|
120
|
+
g.FillEllipse(brush, target.X - 4, target.Y - 4, 8, 8);
|
|
121
|
+
|
|
122
|
+
// Calculate distance
|
|
123
|
+
double dist = Math.Sqrt(Math.Pow(target.X - p1.X, 2) + Math.Pow(target.Y - p1.Y, 2));
|
|
124
|
+
string text = String.Format("{0:F2} px", dist);
|
|
125
|
+
|
|
126
|
+
// Draw text at midpoint
|
|
127
|
+
Point mid = new Point((p1.X + target.X) / 2, (p1.Y + target.Y) / 2);
|
|
128
|
+
SizeF size = g.MeasureString(text, font);
|
|
129
|
+
|
|
130
|
+
// Ensure text doesn't go off screen
|
|
131
|
+
float txtX = mid.X + 10;
|
|
132
|
+
float txtY = mid.Y + 10;
|
|
133
|
+
|
|
134
|
+
g.FillRectangle(textBg, txtX - 2, txtY - 2, size.Width + 4, size.Height + 4);
|
|
135
|
+
g.DrawString(text, font, Brushes.White, txtX, txtY);
|
|
136
|
+
|
|
137
|
+
// Also display coordinates
|
|
138
|
+
string coords = String.Format("P1: {0},{1} P2: {2},{3}", p1.X, p1.Y, target.X, target.Y);
|
|
139
|
+
g.DrawString(coords, font, Brushes.Yellow, 10, 10);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
protected override void OnKeyDown(KeyEventArgs e) {
|
|
144
|
+
if (e.KeyCode == Keys.Escape) {
|
|
145
|
+
Application.Exit();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
public static class Entry {
|
|
151
|
+
public static void Main() {
|
|
152
|
+
Application.EnableVisualStyles();
|
|
153
|
+
Application.SetCompatibleTextRenderingDefault(false);
|
|
154
|
+
Application.Run(new DistanceForm());
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
'@ -ReferencedAssemblies System.Windows.Forms,System.Drawing
|
|
158
|
+
|
|
159
|
+
[Entry]::Main()
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
const proc = spawn('powershell', ['-NoProfile', '-Command', overlayScript], { stdio: 'inherit' });
|
|
163
|
+
|
|
164
|
+
proc.on('close', (code) => {
|
|
165
|
+
// console.log('Exited');
|
|
166
|
+
});
|
|
167
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import i18next from '../i18n.js';
|
|
3
|
+
|
|
4
|
+
export async function screenMarkHandler() {
|
|
5
|
+
if (process.platform !== 'win32') {
|
|
6
|
+
console.log(i18next.t('screenMark.notSupported'));
|
|
7
|
+
return;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
console.log(i18next.t('screenMark.startPrompt'));
|
|
11
|
+
|
|
12
|
+
const overlayScript = `
|
|
13
|
+
Add-Type -AssemblyName System.Windows.Forms;
|
|
14
|
+
Add-Type -AssemblyName System.Drawing;
|
|
15
|
+
|
|
16
|
+
Add-Type -TypeDefinition @'
|
|
17
|
+
using System;
|
|
18
|
+
using System.Drawing;
|
|
19
|
+
using System.Windows.Forms;
|
|
20
|
+
using System.Collections.Generic;
|
|
21
|
+
|
|
22
|
+
public class MarkItem {
|
|
23
|
+
public Point Location;
|
|
24
|
+
public string Text;
|
|
25
|
+
public MarkItem(Point loc, string text) {
|
|
26
|
+
Location = loc;
|
|
27
|
+
Text = text;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public class InputBox : Form {
|
|
32
|
+
private TextBox textBox;
|
|
33
|
+
private Button btnOk;
|
|
34
|
+
private Button btnCancel;
|
|
35
|
+
public string InputText { get { return textBox.Text; } }
|
|
36
|
+
|
|
37
|
+
public InputBox(string title, string prompt, Point location) {
|
|
38
|
+
this.Text = title;
|
|
39
|
+
this.Size = new Size(300, 150);
|
|
40
|
+
this.FormBorderStyle = FormBorderStyle.FixedDialog;
|
|
41
|
+
this.StartPosition = FormStartPosition.Manual;
|
|
42
|
+
this.Location = location;
|
|
43
|
+
this.TopMost = true;
|
|
44
|
+
this.MinimizeBox = false;
|
|
45
|
+
this.MaximizeBox = false;
|
|
46
|
+
|
|
47
|
+
Label lbl = new Label();
|
|
48
|
+
lbl.Text = prompt;
|
|
49
|
+
lbl.Location = new Point(10, 10);
|
|
50
|
+
lbl.AutoSize = true;
|
|
51
|
+
this.Controls.Add(lbl);
|
|
52
|
+
|
|
53
|
+
textBox = new TextBox();
|
|
54
|
+
textBox.Location = new Point(10, 35);
|
|
55
|
+
textBox.Size = new Size(260, 20);
|
|
56
|
+
this.Controls.Add(textBox);
|
|
57
|
+
|
|
58
|
+
btnOk = new Button();
|
|
59
|
+
btnOk.Text = "OK";
|
|
60
|
+
btnOk.DialogResult = DialogResult.OK;
|
|
61
|
+
btnOk.Location = new Point(110, 70);
|
|
62
|
+
this.Controls.Add(btnOk);
|
|
63
|
+
|
|
64
|
+
btnCancel = new Button();
|
|
65
|
+
btnCancel.Text = "Cancel";
|
|
66
|
+
btnCancel.DialogResult = DialogResult.Cancel;
|
|
67
|
+
btnCancel.Location = new Point(190, 70);
|
|
68
|
+
this.Controls.Add(btnCancel);
|
|
69
|
+
|
|
70
|
+
this.AcceptButton = btnOk;
|
|
71
|
+
this.CancelButton = btnCancel;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public class MarkForm : Form {
|
|
76
|
+
private List<MarkItem> marks = new List<MarkItem>();
|
|
77
|
+
private Bitmap screenCapture;
|
|
78
|
+
|
|
79
|
+
public MarkForm() {
|
|
80
|
+
this.FormBorderStyle = FormBorderStyle.None;
|
|
81
|
+
this.TopMost = true;
|
|
82
|
+
this.Cursor = Cursors.IBeam;
|
|
83
|
+
this.DoubleBuffered = true;
|
|
84
|
+
|
|
85
|
+
// Calculate total bounds
|
|
86
|
+
Rectangle totalBounds = Rectangle.Empty;
|
|
87
|
+
foreach(Screen s in Screen.AllScreens) {
|
|
88
|
+
totalBounds = Rectangle.Union(totalBounds, s.Bounds);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
this.StartPosition = FormStartPosition.Manual;
|
|
92
|
+
this.Bounds = totalBounds;
|
|
93
|
+
|
|
94
|
+
// Capture screen
|
|
95
|
+
screenCapture = new Bitmap(totalBounds.Width, totalBounds.Height);
|
|
96
|
+
using (Graphics g = Graphics.FromImage(screenCapture)) {
|
|
97
|
+
g.CopyFromScreen(totalBounds.Location, Point.Empty, totalBounds.Size);
|
|
98
|
+
}
|
|
99
|
+
this.BackgroundImage = screenCapture;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
protected override void OnMouseDown(MouseEventArgs e) {
|
|
103
|
+
if (e.Button == MouseButtons.Right) {
|
|
104
|
+
// Remove last mark
|
|
105
|
+
if (marks.Count > 0) {
|
|
106
|
+
marks.RemoveAt(marks.Count - 1);
|
|
107
|
+
this.Invalidate();
|
|
108
|
+
}
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (e.Button == MouseButtons.Left) {
|
|
113
|
+
// Show input box
|
|
114
|
+
using (InputBox input = new InputBox("Add Text", "Enter text:", Cursor.Position)) {
|
|
115
|
+
if (input.ShowDialog() == DialogResult.OK && !string.IsNullOrWhiteSpace(input.InputText)) {
|
|
116
|
+
marks.Add(new MarkItem(e.Location, input.InputText));
|
|
117
|
+
this.Invalidate();
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
protected override void OnPaint(PaintEventArgs e) {
|
|
124
|
+
Graphics g = e.Graphics;
|
|
125
|
+
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
|
|
126
|
+
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
|
|
127
|
+
|
|
128
|
+
Font font = new Font("Segoe UI", 12, FontStyle.Bold);
|
|
129
|
+
Brush textBrush = Brushes.White;
|
|
130
|
+
|
|
131
|
+
foreach (var mark in marks) {
|
|
132
|
+
SizeF size = g.MeasureString(mark.Text, font);
|
|
133
|
+
// Draw text without background frame
|
|
134
|
+
g.DrawString(mark.Text, font, textBrush, mark.Location.X, mark.Location.Y - size.Height);
|
|
135
|
+
|
|
136
|
+
// Draw anchor point
|
|
137
|
+
g.FillEllipse(Brushes.Red, mark.Location.X - 3, mark.Location.Y - 3, 6, 6);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
protected override void OnKeyDown(KeyEventArgs e) {
|
|
142
|
+
if (e.KeyCode == Keys.Escape) {
|
|
143
|
+
Application.Exit();
|
|
144
|
+
}
|
|
145
|
+
if (e.KeyCode == Keys.Delete || e.KeyCode == Keys.C) {
|
|
146
|
+
marks.Clear();
|
|
147
|
+
this.Invalidate();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
public static class Entry {
|
|
153
|
+
public static void Main() {
|
|
154
|
+
Application.EnableVisualStyles();
|
|
155
|
+
Application.SetCompatibleTextRenderingDefault(false);
|
|
156
|
+
Application.Run(new MarkForm());
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
'@ -ReferencedAssemblies System.Windows.Forms,System.Drawing
|
|
160
|
+
|
|
161
|
+
[Entry]::Main()
|
|
162
|
+
`;
|
|
163
|
+
|
|
164
|
+
const proc = spawn('powershell', ['-NoProfile', '-Command', overlayScript], { stdio: 'inherit' });
|
|
165
|
+
|
|
166
|
+
proc.on('close', (code) => {
|
|
167
|
+
// console.log('Exited');
|
|
168
|
+
});
|
|
169
|
+
}
|
package/src/index.js
CHANGED
|
@@ -30,6 +30,8 @@ import { vscodeSnippetHandler } from './commands/vscodeSnippet.js';
|
|
|
30
30
|
import { dominantColorHandler } from './commands/dominantColor.js';
|
|
31
31
|
import { colorPickHandler } from './commands/colorPick.js';
|
|
32
32
|
import { crosshairHandler } from './commands/crosshair.js';
|
|
33
|
+
import { pixelDistanceHandler } from './commands/pixelDistance.js';
|
|
34
|
+
import { screenMarkHandler } from './commands/screenMark.js';
|
|
33
35
|
|
|
34
36
|
process.on('SIGINT', () => {
|
|
35
37
|
console.log(`\n${i18next.t('menu.bye')}`);
|
|
@@ -55,6 +57,8 @@ function getFeatures() {
|
|
|
55
57
|
{ name: i18next.t('menu.features.dominantColor'), value: 'dominantColor' },
|
|
56
58
|
{ name: i18next.t('menu.features.colorPick'), value: 'colorPick' },
|
|
57
59
|
{ name: i18next.t('menu.features.crosshair'), value: 'crosshair' },
|
|
60
|
+
{ name: i18next.t('menu.features.pixelDistance'), value: 'pixelDistance' },
|
|
61
|
+
{ name: i18next.t('menu.features.screenMark'), value: 'screenMark' },
|
|
58
62
|
{ name: i18next.t('menu.features.placeholderImg'), value: 'placeholderImg' },
|
|
59
63
|
{ name: i18next.t('menu.features.qrcode'), value: 'qrcode' },
|
|
60
64
|
|
|
@@ -199,6 +203,12 @@ async function handleAction(action) {
|
|
|
199
203
|
case 'crosshair':
|
|
200
204
|
await crosshairHandler();
|
|
201
205
|
break;
|
|
206
|
+
case 'pixelDistance':
|
|
207
|
+
await pixelDistanceHandler();
|
|
208
|
+
break;
|
|
209
|
+
case 'screenMark':
|
|
210
|
+
await screenMarkHandler();
|
|
211
|
+
break;
|
|
202
212
|
case 'timeFormat':
|
|
203
213
|
await timeFormatHandler();
|
|
204
214
|
break;
|
package/src/locales/en.js
CHANGED
|
@@ -2,6 +2,14 @@ export default {
|
|
|
2
2
|
common: {
|
|
3
3
|
back: 'Back to previous step'
|
|
4
4
|
},
|
|
5
|
+
pixelDistance: {
|
|
6
|
+
notSupported: 'Pixel distance tool not supported on this OS.',
|
|
7
|
+
startPrompt: 'Pixel distance tool started. Click 2 points to measure. Right-click to reset. ESC to exit.'
|
|
8
|
+
},
|
|
9
|
+
screenMark: {
|
|
10
|
+
notSupported: 'Screen mark tool not supported on this OS.',
|
|
11
|
+
startPrompt: 'Screen mark tool started. Click to add text. Right-click to undo. ESC to exit.'
|
|
12
|
+
},
|
|
5
13
|
menu: {
|
|
6
14
|
title: 'xw-devtool-cli Menu',
|
|
7
15
|
exit: 'Exit',
|
|
@@ -15,6 +23,8 @@ export default {
|
|
|
15
23
|
dominantColor: 'Image Dominant Color',
|
|
16
24
|
colorPick: 'Color Picker',
|
|
17
25
|
crosshair: 'Screen Crosshair',
|
|
26
|
+
pixelDistance: 'Pixel Distance Tool',
|
|
27
|
+
screenMark: 'Screen Mark Tool',
|
|
18
28
|
placeholderImg: 'Placeholder Image Generator',
|
|
19
29
|
qrcode: 'QR Code Generator',
|
|
20
30
|
url: 'URL Encode/Decode',
|
package/src/locales/zh.js
CHANGED
|
@@ -6,6 +6,10 @@ export default {
|
|
|
6
6
|
notSupported: '当前系统不支持屏幕辅助线。',
|
|
7
7
|
startPrompt: '屏幕十字辅助线已启动。按任意键退出...'
|
|
8
8
|
},
|
|
9
|
+
pixelDistance: {
|
|
10
|
+
notSupported: '当前系统不支持屏幕测距。',
|
|
11
|
+
startPrompt: '屏幕测距工具已启动。点击两点测量距离。右键重置。ESC 退出。'
|
|
12
|
+
},
|
|
9
13
|
menu: {
|
|
10
14
|
title: 'xw-devtool-cli 菜单',
|
|
11
15
|
exit: '退出',
|
|
@@ -19,6 +23,8 @@ export default {
|
|
|
19
23
|
dominantColor: '图片主色识别',
|
|
20
24
|
colorPick: '颜色吸取',
|
|
21
25
|
crosshair: '全屏十字辅助线',
|
|
26
|
+
pixelDistance: '屏幕测距 (像素)',
|
|
27
|
+
screenMark: '屏幕文字标注',
|
|
22
28
|
placeholderImg: '占位图生成器',
|
|
23
29
|
qrcode: '二维码生成器',
|
|
24
30
|
url: 'URL 编码/解码',
|