Greasy Fork

划词翻译

选中文字按住左键一会儿后放开,自动翻译。

目前为 2017-04-06 提交的版本。查看 最新版本

// ==UserScript==
// @name        划词翻译
// @namespace   http://www.icycat.com
// @description 选中文字按住左键一会儿后放开,自动翻译。
// @author      冻猫
// @include     *
// @version     1.7
// @grant 		GM_xmlhttpRequest
// @grant 		GM_addStyle
// @run-at      document-end
// ==/UserScript==

(function() {

	'use strict';

	function init() {
		var timer, holdTime, text, soundUrl, postData;

		document.addEventListener('mousedown', mouseStart, false);
		document.addEventListener('mouseup', mouseEnd, false);

		function mouseStart(e) {
			if (!document.getElementById('catTipBox')) {
				createTipBox();
			}
			if (!/catTranslate/i.test(e.target.className) && document.getElementById('catTipBox').style.display == 'block') {
				document.getElementById('catTipBox').style.display = '';
				document.getElementById('catContentBox').innerHTML = '翻译中...';
				try {
					window.catSource.stop();
				} catch (e) {};
			}
			document.addEventListener('mousemove', moveCheck, false);
			if (e.target.id == 'catPlaySound') {
				document.getElementById('catPlaySound').classList.add('catPlaySoundClick');
				getRequest(soundUrl);
			}
		}

		function moveCheck() {
			clearTimeout(timer);
			holdTime = false;
			timer = setTimeout(function() {
				holdTime = true;
			}, 700);
		}

		function mouseEnd(e) {
			document.removeEventListener('mousemove', moveCheck, false);
			clearTimeout(timer);
			if (holdTime && window.getSelection().toString()) {
				holdTime = false;
				console.log('开始翻译');
				showTipBox(e.clientX, e.clientY);
				text = window.getSelection().toString();
				if (/[\u0800-\u4e00]+/.test(text)) {
					postData = `from=jp&to=zh&query=${encodeURIComponent(text)}&source=txt`;
					soundUrl = `http://fanyi.baidu.com/gettts?lan=jp&text=${encodeURIComponent(text)}&spd=3&source=web`;
				} else if (/[\u4e00-\u9fa5]+/.test(text)) {
					postData = `from=zh&to=en&query=${encodeURIComponent(text)}&source=txt`;
					soundUrl = `http://fanyi.baidu.com/gettts?lan=zh&text=${encodeURIComponent(text)}&spd=5&source=web`;
				} else {
					postData = `from=en&to=zh&query=${encodeURIComponent(text)}&source=txt`;
					soundUrl = `http://fanyi.baidu.com/gettts?lan=en&text=${encodeURIComponent(text)}&spd=3&source=web`;
				}
				postRequest('http://fanyi.baidu.com/transapi', postData);
			}
			if (document.querySelector('.catPlaySoundClick')) {
				document.getElementById('catPlaySound').classList.remove('catPlaySoundClick');
			}
		}
	}

	function createTipBox() {
		GM_addStyle([
			'#catTipBox {max-width:360px;font:normal 12px/24px Helvetica, Tahoma, Arial, sans-serif;text-align: left;position: absolute;z-index: 2147483647;top: 22px;left: -35px;background: #fff;border: 1px solid #dcdcdc;border: 1px solid rgba(0,0,0,.2);-webkit-transition: opacity .218s;transition: opacity .218s;-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.2);box-shadow: 0 2px 4px rgba(0,0,0,.2);padding: 5px 0;display: none;font-size: 12px;line-height: 20px;}',
			'#catContentBox {margin:0 8px;color:#333;}',
			'#catContentBox .catTextBox{margin: 2px 0 1px 0;}',
			'#catContentBox .catText{font-size:14px;margin: 3px 0 3px;font-weight: bold;color:#333;}',
			'#catContentBox span{margin-left: 5px;color:#333;font-weight: normal;font-size:12px;}',
			'#catPlaySound {cursor:pointer;display: inline-block;vertical-align: middle;width: 14px;height: 11px;overflow: hidden;background: url("data:image/gif;base64,R0lGODlhDgAZAIAAABy3/f///yH5BAAAAAAALAAAAAAOABkAAAI1jA+nC7ncXmg0RlTvndnt7jlcxkmjqWzotLbui4qxqBpUmoDl2Nk5GOKRSsCfDyer7ZYMSQEAOw==") no-repeat;text-decoration: none;}',
			'#catPlaySound.catPlaySoundClick {background-position:0 -14px;}',
			'.catTipArrow {width: 0;height: 0;font-size: 0;line-height: 0;display: block;position: absolute;top: -16px;left: 10px;}',
			'.catTipArrow em, .catTipArrow ins {width: 0;height: 0;font-size: 0;line-height: 0;display: block;position: absolute;border: 8px solid transparent;border-style: dashed dashed solid;}',
			'.catTipArrow em {border-bottom-color: #d8d8d8;font-style: normal;color: #c00;}',
			'.catTipArrow ins {border-bottom-color: #fff;top: 2px;text-decoration: underline;background:none !important}'
		].join('\n'));
		var catTipBox = document.createElement('div');
		catTipBox.id = 'catTipBox';
		catTipBox.className = 'catTranslate';
		var catContentBox = document.createElement('div');
		catContentBox.id = 'catContentBox';
		catContentBox.className = 'catTranslate';
		catContentBox.innerHTML = '翻译中...';
		var catTipArrow = document.createElement('div');
		catTipArrow.className = 'catTipArrow';
		catTipArrow.appendChild(document.createElement('em'));
		catTipArrow.appendChild(document.createElement('ins'));
		catTipBox.appendChild(catContentBox);
		catTipBox.appendChild(catTipArrow);
		document.body.appendChild(catTipBox);
	}

	function showTipBox(mouseX, mouseY) {
		var catTipBox = document.getElementById('catTipBox');
		var selectedRect = window.getSelection().getRangeAt(0).getBoundingClientRect();
		var scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
		if (selectedRect.width) {
			if (/Firefox/i.test(navigator.userAgent)) {
				catTipBox.style.top = scrollTop + selectedRect.y + selectedRect.height + 8 + 'px';
				catTipBox.style.left = selectedRect.x + selectedRect.width / 2 - 18 + 'px';
			} else {
				catTipBox.style.top = scrollTop + selectedRect.top + selectedRect.height + 8 + 'px';
				catTipBox.style.left = selectedRect.left + selectedRect.width / 2 - 18 + 'px';
			}
		} else {
			catTipBox.style.top = scrollTop + mouseY + selectedRect.height + 8 + 'px';
			catTipBox.style.left = mouseX + selectedRect.width / 2 - 18 + 'px';
		}

		catTipBox.style.display = 'block';
	}

	function parseRes(jsonRes) {

		var phonic;
		var explains = '';
		var obj = JSON.parse(jsonRes);
		var result;

		if (obj.type == 1) {
			result = JSON.parse(obj.result);
		} else if (obj.type == 2) {
			result = obj.data[0];
		}

		var catContentBox = document.getElementById('catContentBox');
		catContentBox.innerHTML = '';
		//上排盒子
		var catTextBox = document.createElement('div');
		catTextBox.className = 'catTextBox catTranslate';
		//选择的文本
		var catText = document.createElement('span');
		catText.className = 'catText catTranslate';
		catText.innerHTML = result.src;
		catTextBox.appendChild(catText);
		//音标
		if (result.voice) {
			var catPhonetic = document.createElement('span');
			catPhonetic.className = 'catTranslate';
			if (obj.from == 'zh') {
				phonic = result.voice[0].phonic;
			} else {
				phonic = result.voice[1].us_phonic;
			}
			catPhonetic.innerHTML = phonic;
			catTextBox.appendChild(catPhonetic);
		}
		//图标
		var catPlaySound = document.createElement('span');
		catPlaySound.id = 'catPlaySound';
		catPlaySound.className = 'catTranslate';
		catTextBox.appendChild(catPlaySound);
		//翻译
		if (result.content) {
			for (var i = 0; i < result.content[0].mean.length; i++) {
				if (result.content[0].mean[i].pre) {
					explains = explains + result.content[0].mean[i].pre + ' ';
				}
				for (var mean in result.content[0].mean[i].cont) {
					explains = explains + mean + '; ';
				}
				if (i < result.content[0].mean.length - 1) {
					explains = explains + '<br />';
				}
			}
		}
		if (result.dst) {
			explains = result.dst;
		}
		var catExplains = document.createElement('div');
		catExplains.className = 'catExplains catTranslate';
		catExplains.innerHTML = explains;

		catContentBox.appendChild(catTextBox);
		catContentBox.appendChild(catExplains);
	}

	function playSound(arraybuffer) {
		if (!window.audioCtx) {
			window.audioCtx = new AudioContext();
		}
		audioCtx.decodeAudioData(arraybuffer).then(function(buffer) {
			window.catSource = audioCtx.createBufferSource();
			window.catSource.buffer = buffer;
			window.catSource.connect(audioCtx.destination);
			window.catSource.start();
		});
	}

	function postRequest(url, data) {
		GM_xmlhttpRequest({
			method: 'POST',
			url: url,
			data: data,
			headers: {
				'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8',
				'Referer': 'http://fanyi.baidu.com/'
			},
			onload: function(res) {
				parseRes(res.responseText);
			},
		});
	}

	function getRequest(url) {
		GM_xmlhttpRequest({
			method: 'GET',
			url: url,
			headers: {
				'Referer': 'http://fanyi.baidu.com/'
			},
			responseType: 'arraybuffer',
			onload: function(res) {
				playSound(res.response);
			},
		});
	}

	init();

})();