また一つ悩みが解決しましたよ!
活字嫌いの私は、日頃から「テキスト読み上げ」機能を活用しまくっています。
だが、一つだけ深刻な問題が… それは、iOSのSafariでテキストを選択するのがストレスで嫌になっちゃうんです(分かりますよね… いくら指でグリグリやっても、全く思い通りにテキストを選択できない苦痛…)。
もう我慢の限界です!試しに「Web Speech API(Speech Synthesis API)」を使って、テキストをクリック(タップ)するだけで読み上げてくれる便利なブックマークレットを作ってみましたので、シェアします。
分かりにくいと思うので、20秒ほどの動画を撮りました。
ブックマークレットの使い方
以下のコードを全選択して、コピー。
javascript:!function(){function e(e){return document.querySelectorAll(e)}function n(e,n){Array.prototype.forEach.call(e,function(e,t,c){n.apply(this,[e,t,c])})}function t(e){for(var n,t=[],c=document.createTreeWalker(e,NodeFilter.SHOW_TEXT,null,!1);n=c.nextNode();)t.push(n);return t.filter(function(e){return null===e.nodeValue.match(/^\s+$/)})}function c(e){var n=["SCRIPT","P","H1","H2","H3","H4","H5","H6","DT","A","ABBR","ACRONYM","B","BASEFONT","BDO","BIG","BR","CITE","CODE","DFN","EM","FONT","I","IMG","INPUT","KBD","LABEL","Q","S","SAMP","SELECT","SMALL","SPAN","STRIKE","STRONG","SUB","SUP","TEXTAREA","TT","U","VAR","TIME"];e.forEach(function(e){var t=document.createElement("span"),c=e.parentNode;n.indexOf(c.tagName)>-1||(t.className="______span______",t.style.cssText="display: inline !important;",t.appendChild(document.createTextNode(e.nodeValue)),e.parentNode.replaceChild(t,e))})}function o(e){var n=new SpeechSynthesisUtterance;n.volume=1,n.rate=1.4,n.pitch=1,n.text=e,n.lang="ja-JP",window.speechSynthesis.cancel(),window.speechSynthesis.speak(n)}function a(){c(t(document.body));var a=document.createElement("style");a.innerHTML=".__speeching__{ color: #2B2B2B; background-color: rgba(255,245,157,0.90); }",document.querySelector("head").appendChild(a);var r=e("body *:not(script)"),i=document.createElement("span"),s=i;n(r,function(e){e.addEventListener("click",function(e){return e.stopPropagation(),this===s?(window.speechSynthesis.cancel(),s.classList.remove("__speeching__"),void(s=i)):(o(this.innerText),s.classList.remove("__speeching__"),s=this,void s.classList.add("__speeching__"))})})}a()}();
そして、ブックマークとして登録して下さい。
あとは動画のように、使いたいサイトで、先ほど登録したブックマークを呼び出し後、読み上げて欲しいところをタップして下さい。
同じところを再度タップすると止まります。
ちなみに、iOSのSafariでは、たまに止まらない場合があります。数回タップすると止まることも…
原因は分からないがデスクトップでは、ChromeもSafariも正常ですけどね。ブラウザのバグですかね?
Chrome 45、Safari 9.1、iOS Safari 8.4 から使えるはずです。それ以下のバージョンでは「Speech Synthesis API」をサポートしていないので、使えません。
minify前のコード
minify前のコードもご参考に載せておきます。「速さ」と「言語」は変えられます。
(function () { function $(selector) { return document.querySelectorAll(selector); } function each(array, callback) { Array.prototype.forEach.call(array, function (value, index, self) { callback.apply(this, [value, index, self]); }) } function textNodesUnder(el) { var n, a = [], walk = document.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false); while (n = walk.nextNode()) a.push(n); return a.filter(function (node) { return node.nodeValue.match(/^\s+$/) === null; }); } function wrapTextNodes(textNodes) { var excludedElements = ['SCRIPT', 'P', 'H1', 'H2', 'H3', 'H4', 'H5', 'H6', 'DT', 'A', 'ABBR', 'ACRONYM', 'B', 'BASEFONT', 'BDO', 'BIG', 'BR', 'CITE', 'CODE', 'DFN', 'EM', 'FONT', 'I', 'IMG', 'INPUT', 'KBD', 'LABEL', 'Q', 'S', 'SAMP', 'SELECT', 'SMALL', 'SPAN', 'STRIKE', 'STRONG', 'SUB', 'SUP', 'TEXTAREA', 'TT', 'U', 'VAR', 'TIME']; textNodes.forEach(function (textNode) { var span = document.createElement('span'), parentNode = textNode.parentNode; if (excludedElements.indexOf(parentNode.tagName) > -1) { return; } span.className = '______span______'; span.style.cssText = "display: inline !important;"; span.appendChild(document.createTextNode(textNode.nodeValue)); textNode.parentNode.replaceChild(span, textNode); }); } function speach(text) { var msg = new SpeechSynthesisUtterance(); msg.rate = 1.9; // 速さ msg.lang = 'ja-JP'; // 言語 msg.volume = 1; msg.pitch = 1; msg.text = text; window.speechSynthesis.cancel(); window.speechSynthesis.speak(msg); } function main() { wrapTextNodes(textNodesUnder(document.body)); var style = document.createElement('style'); style.innerHTML = ".__speeching__{ color: #2B2B2B; background-color: rgba(255,245,157,0.90); }"; document.querySelector('head').appendChild(style); var elements = $('body *:not(script)'), dummyElem = document.createElement('span'), speechingElem = dummyElem; each(elements, function (element) { element.addEventListener('click', function (e) { e.stopPropagation(); if (this === speechingElem) { window.speechSynthesis.cancel(); speechingElem.classList.remove('__speeching__'); speechingElem = dummyElem; return; } speach(this.innerText); speechingElem.classList.remove('__speeching__'); speechingElem = this; speechingElem.classList.add('__speeching__'); }); }); } main(); })();