adjustColor2

convert colors to eye-friendly - webページの配色を目に優しく変更します (Flash対応)

目前為 2015-06-08 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name        adjustColor2
// @namespace   http://chiebukuro.yahoo.co.jp/my/gbjyn273
// @author Syakku
// @description	convert colors to eye-friendly - webページの配色を目に優しく変更します (Flash対応)
// @include     *
// @version     1.1
// @run-at     document-start  
// ==/UserScript==

//	================≪ OPTION ≫================

	//	----------------< white" & "black" color >----------------
	var FILTER_COLOR_W = "rgb(234, 229, 227)";
	var FILTER_COLOR_B = "rgb(41, 34, 29)";
	var INNER_COLOR_W = "rgb(211, 203, 198)";
	var INNER_COLOR_B = "rgb(41, 34, 29)";	//	gb is disabled
	
	//	OPTION : apply to Flash object
	var FLASH = true;
	
	//	OPTION : skip <a> tag (link anchor)
	//	OPTION : <a> タグ、つまりリンク文字列を処理から除外します
	//	ex: [] or ["google.co.jp", "youtube", "&link=important"] or [*]
	var _A_SKIP_URL = [""];
	
	
// ================≪ 初期化 ≫================
	var _win = document.defaultView;	
	
	var fCw = rgbSplit(FILTER_COLOR_W);
	var fCb = rgbSplit(FILTER_COLOR_B);
	var iCw = rgbSplit(INNER_COLOR_W);
	var iCb = rgbSplit(INNER_COLOR_B);
	
	// ----------------< インナーがフィルターを超えていたら修正 >----------------
	for (var i=0; i<3; i++){
		if (iCw[i] > fCw[i]){iCw[i] = fCw[i];}
		if (iCb[i] < fCb[i]){iCb[i] = fCb[i];}
	}
	
	// ----------------< フィルタ関連の初期化 >----------------
	var fColor = createFilter(fCw, fCb);
	var filterR = fColor[0], filterG = fColor[1], filterB = fColor[2],	filterA = fColor[3], filterAa = 1-filterA;
	
	//	色変換で使うので先に計算
	var filterRA = filterR * filterA, filterGA = filterG * filterA, filterBA = filterB * filterA;
	var _pr = (iCw[0] - iCb[0]) / 255, _pg = (iCw[1] - iCb[1]) / 255, _pb = (iCw[2] - iCb[2]) / 255;
	var _pr2 = iCb[0], _pg2 = iCb[1], _pb2 = iCb[2];
	
	// ----------------< 色変換の結果保持配列 >----------------
	var list = [];
	var lFg = [];
	var lCount = 0;


	// ----------------< 背景画像処理 >----------------
	var bgFilter = createBgFilter();
	var bgfCount = bgFilter.substring(0, 30);
	var bgfcLength = bgfCount.length;
	
	function createBgFilter(){
		var tw=[], tb=[];
		tw[0] = Math.floor((iCw[0] - filterRA) / filterAa);
		tw[1] = Math.floor((iCw[1] - filterGA) / filterAa);
		tw[2] = Math.floor((iCw[2] - filterBA) / filterAa);
		tb[0] = Math.floor((iCb[0] - filterRA) / filterAa);
		var bfColor = createFilter(tw, tb);
		var _rgba = bfColor[4];
		return("linear-gradient(" + _rgba + ',' + _rgba + "),");
	}

	// ----------------< URLフィルタ >----------------
	var _skip = false;
	for (var i=0; i<_A_SKIP_URL.length; i++){
		if (location.href.indexOf(_A_SKIP_URL[i]) !== -1 || _A_SKIP_URL[i] === "*"){_skip = true;}
	}
	
	
		
// ################################################ //
// ################### メイン処理部 ################### //
// ################################################ //


// ================≪ 起動処理 ≫================
	var FAST = true;
	 if (window === window.parent){
		if (FAST === true){loadFilter();}
		else {_win.addEventListener("DOMContentLoaded", loadFilter, false)}
	}
	_win.addEventListener("DOMContentLoaded", afterTouch, false);
	_win.addEventListener("load", afterTouch, false);
	
	if (FLASH === true){_win.addEventListener("DOMContentLoaded", flashMode, false);}

	
// ================≪ フィルタの適用 ≫================
function loadFilter(_fast){
	var _filter = document.createElement("ac_filter"); 
	_filter.id = "adjustColor"; 
	_filter.style.backgroundColor = fColor[4];
	_filter.style.pointerEvents = "none";
	_filter.style.height = "100%";
	_filter.style.width = "100%";
	_filter.style.position = "fixed";
	_filter.style.zIndex = 9999;

	var _nodes = document.getElementsByTagName("html")[0].childNodes;
	for (var i=0; i<_nodes.length; i++){
		var _node = _nodes[i];
		if (_node.tagName === "BODY"){
			var _style = _node.style;
			_style.position = "absolute";
			//	absolute にすると中央揃えでなくなってしまう
			_style.left = 0;
			_style.right =  0;
			_style.top = 0;
			_style.bottom = 0;
			// unset なのはブラウザ標準スタイルシートでマージンが存在するため
			_style.margin = "unset auto";
			break;
		} else if (_node.tagName === "FRAMESET"){
			document.getElementsByTagName("html")[0].insertBefore(_filter, _node);
			return;
		}
	}
	document.getElementsByTagName("html")[0].appendChild(_filter);
}


// ================≪ 追加処理 ≫================
function afterTouch(){
    var elm = document.getElementsByTagName("*");
	var elm_length = elm.length;

	for (var i = 0; i < elm_length; i++) {

		var tElm = elm[i];
		// <A>タグ
		if (tElm.tagName === "A" && _skip === true) {continue;}
        var style = _win.getComputedStyle(tElm, null);
		var fgColor = style.getPropertyValue("color");
		
		// ----------------< 背景 >----------------
		fg:{
			
			//	処理する必要のないカラーは省く
			for (var n=0; n<lCount; n++){
				if (fgColor === list[n]){break fg;}
			}
						
			//	既存のカラーは省エネ
			for (var n=0; n<lCount; n++){
				if (fgColor === lFg[n]){
					tElm.style.color = list[n];
					break fg;
				}
			}

			var _tColorF = convColor(fgColor);
			lFg[lCount] = fgColor;
			list[lCount] = _tColorF;
			lCount++;
			tElm.style.color = list[n];
		}
	}
}


//	================ <背景色レンジ縮小 ≫================
function convColor(_bg) {

	var _col = rgbSplit(_bg);
	
    var _colR = _col[0] * _pr + _pr2*1;
    var _colG = _col[1] * _pg + _pg2*1;
    var _colB = _col[2] * _pb + _pb2*1;
	
	_colR = Math.floor((_colR - filterRA) / filterAa);
	_colG = Math.floor((_colG - filterGA) / filterAa);
	_colB = Math.floor((_colB - filterBA) / filterAa);

    if (typeof _col[3] === "undefined") {
        return ("rgb(" + _colR + ", " + _colG + ", " + _colB + ")");
    }
    return ("rgb(" + _colR + ", " + _colG + ", " + _colB + ", " + _col[3] + ")"); //	rgba
}


// ================≪ RGB値の分割 ≫================
function rgbSplit(_col){
	if (_col.substring(0, 4) === "rgb("){_col = _col.slice(4, -1)}
	else {_col = _col.slice(5, -1)}
	var _ret = _col.split(", ");
	return (_ret);
}


// ================≪ 白・黒の範囲を与えてフィルタを作成 ≫================
function createFilter(_w, _b){
	var br = _b[0], wr = _w[0], wg = _w[1], wb = _w[2];
	var tr = wr - br;
	var r = tr / (255 - tr) * br + br*1;
	var a = br/ r;	// 中心値 r が気をつけないと 0 や 255 になって 0 除算になる
	if (isNaN(a) === true){a = (wr-255) / (r-255);}

	var g = r - (wr - wg) / a;
	var b = r - (wr - wb) / a;
	
	// r, g, b, a, rgba の値を配列で返す
	return ([r, g, b, a, "rgba(" + Math.floor(r) + ", " + Math.floor(g) + ", " + Math.floor(b) + ", " + a + ")"]);
}


// ================≪ フラッシュにもフィルタを適用 ≫================
function flashMode(){
	 for (var objs = document.getElementsByTagName("object"), i = 0, obj; obj = objs[i]; i++){
	 
        if (obj.type === "application/x-shockwave-flash"){
            var skip = false;

            for (var params = obj.getElementsByTagName("param"), j = 0, param; param = params[j]; j++){
			
                if (param.getAttribute("name") == "wmode"){
                    skip = true;
                    param.setAttribute("value", "transparent");
					obj.parentNode.appendChild(obj);
                    break;
                }
            }
            if(skip) {continue;}
			
            var param = document.createElement("param");
            param.setAttribute("name", "wmode");
            param.setAttribute("value", "transparent");
            obj.appendChild(param);
			obj.parentNode.appendChild(obj);
        }
	}
}