楕円グラデーション
応用すれば、集合の描画が可能に。
function ggbOnInit() { // オリジナルキャンバスusicanvasを作成 insertCanvas(); console.log(document.getElementsByClassName('usicanvas')[0].className + ' is loaded.'); // グラデーションを描画 Drawer(); // フルスクリーンボタンは不要なので、出るときは消すようにしています。 var fullButton = document.getElementsByClassName('zoomPanelBtn zoomPanelBtn-up')[0]; if(typeof fullButton !== 'undefined'){ fullButton.parentNode.removeChild(fullButton); console.log('fullscreen button is removed.'); } else{ console.log('fullscreen button is undefined.'); } } // オリジナルキャンバスusicanvasを作成 function insertCanvas(){ // 既存のcanvas要素を取得 var preCanvas = document.getElementsByTagName('canvas')[0]; // 既存のcanvasのサイズとcssスタイルを取得 var canvasWidth = preCanvas.width; var canvasHeight = preCanvas.height; var canvasCss = preCanvas.style.cssText; // objListの要素をHTMLリスト化 preCanvas.insertAdjacentHTML('afterend','<div style="position: absolute; right: 0px; bottom: -4px;"><canvas height=\"'+canvasHeight+'\" width=\"'+canvasWidth+'\" dir=\"ltr\" tabindex=\"10000\" class=\"usicanvas\">UsiCanvas</canvas></div>'); // usicanvasのスタイルを設定 document.getElementsByClassName('usicanvas')[0].style.cssText = canvasCss; } // グラデーションを描画 function Drawer(){ // オリジナルキャンバス(usicanvas)を取得 var canvas = document.getElementsByClassName('usicanvas')[0]; // コンテクストを取得 var context = canvas.getContext('2d'); // クリア context.clearRect(0, 0, canvas.width, canvas.height); // スケール調整 var transformText = document.getElementsByClassName('applet_scaler')[0]; if(typeof transformText === 'undefined'){ transformText = 'none'; } // applet_scalerがundefinedの場合には、縮尺1として対応 else{ if(transformText = 'none'){transformText = '(1,1)';} else{ transformText = transformText.style.transform; transformText = transformText.slice(5); } } // console.log('transformText = '+transformText); var ratioX = Number(transformText.slice(1,transformText.length-1).split(',')[0]); var ratioY = Number(transformText.slice(1,transformText.length-1).split(',')[1]); var canvasRatioX = document.getElementsByTagName('canvas')[1].width / document.getElementsByTagName('canvas')[0].width; // ウインドウ変形時のキャンバス同士の縮尺のズレ var canvasRatioY = document.getElementsByTagName('canvas')[1].height / document.getElementsByTagName('canvas')[0].height; var touch = window.ontouchstart===null?2:1; // console.log('ratioX = '+ratioX); // console.log('ratioY = '+ratioY); // console.log('canvasRatioX = '+canvasRatioX); // console.log('canvasRatioY = '+canvasRatioY); // console.log('touch = '+touch); // キャンバス全体のピクセル情報を取得 var imageData = context.getImageData(0, 0, canvas.width, canvas.height); var width = imageData.width, height = imageData.height; var pixels = imageData.data; // ピクセル配列:RGBA4要素で1ピクセル var xA = touch * ggbApplet.getValue('floor(x(PixelCoords[A]))') * ratioX * canvasRatioX; var yA = touch * ggbApplet.getValue('floor(y(PixelCoords[A]))') * ratioY * canvasRatioY; var xB = touch * ggbApplet.getValue('floor(x(PixelCoords[B]))') * ratioX * canvasRatioX; var yB = touch * ggbApplet.getValue('floor(y(PixelCoords[B]))') * ratioY * canvasRatioY; // ピクセル単位で操作 for (var y = 0; y < height; ++y) { for (var x = 0; x < width; ++x) { var base = (y * width + x) * 4; // ピクセルに書き込む pixels[base + 0] = HSLtoRGB((Math.sqrt(Math.pow(xA-x,2) +Math.pow(yA-y,2)) + Math.sqrt(Math.pow(xB-x,2) +Math.pow(yB-y,2))),100,50)[0]; // Red pixels[base + 1] = HSLtoRGB((Math.sqrt(Math.pow(xA-x,2) +Math.pow(yA-y,2)) + Math.sqrt(Math.pow(xB-x,2) +Math.pow(yB-y,2))),100,50)[1]; // Green pixels[base + 2] = HSLtoRGB((Math.sqrt(Math.pow(xA-x,2) +Math.pow(yA-y,2)) + Math.sqrt(Math.pow(xB-x,2) +Math.pow(yB-y,2))),100,50)[2]; // Blue pixels[base + 3] = 130; // Alpha } } // 変更した内容をキャンバスに書き戻す context.putImageData(imageData, 0, 0); } //H(0〜360),S(0〜100),L(0〜100)から[r,g,b]を0〜255で返す function HSLtoRGB(H,S,L){ H = H % 360; var arr = []; if(L <= 49){ var MAX = 2.55 * (L + L * (S / 100)); var MIN = 2.55 * (L - L * (S / 100)); } if(L >= 50){ var MAX = 2.55 * (L + (100 - L) * (S / 100)); var MIN = 2.55 * (L - (100 -L) * (S / 100)); } if(H < 60){ arr[0] = MAX; arr[1] = (H / 60) * (MAX - MIN) + MIN; arr[2] = MIN; } if(60 <= H && H < 120){ arr[0] = ((120 - H) / 60) * (MAX - MIN) + MIN; arr[1] = MAX; arr[2] = MIN; } if(120 <= H && H < 180){ arr[0] = MIN; arr[1] = MAX; arr[2] = ((H - 120) / 60) * (MAX - MIN) + MIN; } if(180 <= H && H < 240){ arr[0] = MIN; arr[1] = ((240 - H) / 60) * (MAX - MIN) + MIN; arr[2] = MAX; } if(240 <= H && H < 300){ arr[0] = ((H - 240) / 60) * (MAX - MIN) + MIN; arr[1] = MIN; arr[2] = MAX; } if(300 <= H && H < 360){ arr[0] = MAX; arr[1] = MIN; arr[2] = ((360 - H) / 60) * (MAX - MIN) + MIN; } return arr; }