// ==UserScript==
// @name 划词翻译
// @namespace http://tampermonkey.net/
// @version 2.0
// @description 单击页面单词,详细中文释义,适配移动端,百度翻译+有道发音服务。
// @author ChatGPT
// @match *://*/*
// @grant GM_xmlhttpRequest
// @run-at document-end
// @downloadURL none
// ==/UserScript==
(function () {
'use strict';
const popup = document.createElement('div');
popup.style.position = 'absolute';
popup.style.backgroundColor = '#fdfdfd';
popup.style.border = '1px solid #ccc';
popup.style.borderRadius = '8px';
popup.style.padding = '15px';
popup.style.fontSize = '16px';
popup.style.boxShadow = '0 4px 8px rgba(0,0,0,0.2)';
popup.style.zIndex = '9999';
popup.style.display = 'none';
popup.style.width = '90%';
popup.style.maxWidth = '600px';
popup.style.wordWrap = 'break-word';
popup.style.lineHeight = '1.5';
popup.style.whiteSpace = 'normal';
popup.style.wordBreak = 'break-word';
popup.style.left = '50%';
popup.style.transform = 'translateX(-50%)';
document.body.appendChild(popup);
function hidePopup() {
popup.style.display = 'none';
}
function showPopup(word, content, x, y) {
const phonetic = content.phonetic ? `
音标: [${content.phonetic}]
` : '';
const meanings = content.meanings.map(meaning => `${meaning}`).join('');
popup.innerHTML = `
单词: ${word}
${phonetic}
`;
popup.style.top = `${y + 10}px`;
popup.style.display = 'block';
}
function fetchTranslation(word) {
const apiURL = `https://fanyi.baidu.com/sug`;
return new Promise((resolve, reject) => {
GM_xmlhttpRequest({
method: 'POST',
url: apiURL,
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
data: `kw=${encodeURIComponent(word)}`,
onload: function (response) {
try {
const data = JSON.parse(response.responseText);
if (data && data.data && data.data.length > 0) {
const result = data.data[0];
resolve({
phonetic: result.k || null,
meanings: data.data.map(item => item.v)
});
} else {
reject(new Error('翻译结果为空'));
}
} catch (error) {
reject(error);
}
},
onerror: function () {
reject(new Error('查询失败'));
}
});
});
}
function playAudio(word) {
const audio = new Audio(`https://dict.youdao.com/dictvoice?type=0&audio=${encodeURIComponent(word)}`);
audio.play();
}
function getWordAtPoint(x, y) {
const range = document.caretRangeFromPoint(x, y);
if (range && range.startContainer.nodeType === Node.TEXT_NODE) {
const textNode = range.startContainer;
const offset = range.startOffset;
const text = textNode.nodeValue;
const before = text.substring(0, offset).match(/[\w\u4e00-\u9fa5]+$/);
const after = text.substring(offset).match(/^[\w\u4e00-\u9fa5]+/);
return (before ? before[0] : '') + (after ? after[0] : '');
}
return null;
}
document.addEventListener('click', (event) => {
const word = getWordAtPoint(event.clientX, event.clientY);
if (word) {
const x = event.pageX;
const y = event.pageY;
showPopup(word, { meanings: ['加载中...'] }, x, y);
fetchTranslation(word).then(content => {
showPopup(word, content, x, y);
playAudio(word);
}).catch(() => {
showPopup(word, { meanings: ['查询失败'] }, x, y);
});
} else {
hidePopup();
}
});
document.addEventListener('click', (e) => {
if (!popup.contains(e.target)) {
hidePopup();
}
});
})();