POPSブログ

CreateJS 透過PNG画像の中の部分に陰影処理する

324

  Category:  javascript2014/10/07 pops 

透過PNG画像の透過部分と画像の境に陰影処理(ドロップシャドウ)をしても、Chrome(Opera)では「テキストまたはグラフイック」と違い処理されません。そこで、「Blurフィルター」ぼかし処理のドロップシャドウを画像で作り配置してみました。easeljs-0.7.1 でのテストです。

 

● 最近のChrome(Opera)で透過PNG画像の中の部分の陰影処理が改善されました

最近のChrome(Opera)で透過PNG画像の中の部分の陰影処理が改善され正常になりました(段階的に修正され、2年以上かかっている)。下記より確認できます。
このページの説明などは、透過PNG画像での「Blurフィルターでのドロップシャドウ処理方法」として何らかの役に立つかも知れません。また問題が起きた場合のヒントになるかも..... 2015/03/14/追記、訂正

【確認テスト】Chrome(Opera)表示確認

 

CreateJS 透過PNG画像の中の部分に陰影処理と表示テスト

通常、透過PNG画像のドロップシャドウは画像を制作する時点で加工するのが一般的ですが、CreateJSのステージでドロップシャドウを付ける試みです。
Chrome(Opera)で、透過PNG画像には、CreateJSの「shadowフィルター」または、「Html5 Canvas」の shadowBlur() でもドロップシャドウは綺麗には処理できません。「読み込み画像」の透過部分にはBlur処理出来ないようになっています(Chromeのバグなのか釈然としないし情報も無い)。
現在の陰影表現では、細貝さんも困る「ダメよ、ダメダメ」状態な訳ですが、修理が終わり一件落着か...(2015/03/14)。


そこで、CreateJSの「Blurフィルター」でドロップシャドウを作り、画像と重ねて表示してみました。


 

DEMO

▼[ 目次 ]


CreateJS 透過PNG画像の中の部分に陰影処理表示デモ

このページはHTML5では有りませんので、デモページでご覧ください。「IE7.8」ではご覧いただけません。
/// 注意、ブラウザ、マシン性能により描画品質などに大きな差が有ります事了承下さい ///



Chrome Opera Firefox Safari(Win) IE9-11で動作確認済み。 Safari(Mac)、は未確認です。


 

HTML JS CSS


使用するライブラリ

easeljs preloadjs tweenjs

配布元 : CreateJS createjs.com


ライブラリの読み込み

ダウンロードしたJSを使用する場合。記述は一例です。(バージョン 0.7.1 使用)


<script type="text/javascript" src="js/easeljs-0.7.1.min.js"></script>
<script type="text/javascript" src="js/preloadjs-0.4.1.min.js"></script>
<script type="text/javascript" src="js/tweenjs-0.5.1.min.js"></script>

重要、バージョン違いでは動かない場合が有りますので必ず合わせて下さい。


HTML (HTML5)


<div id="demo-wrap">
	<div id="image-box" class="radius">
		<canvas id="mainCanvas" width="640" height="300"></canvas>
	</div>
	<div id="image-box2">
		<canvas id="subCanvas" width="640" height="200"></canvas>
	</div>
</div>

JS

createJS107.js、JS名は任意に変更可。注意、easeljs-0.7.1用です。



//日本語
//createJS107.js
//CompositeOperation透過画像陰影テスト
//easeljs-0.7.1用

//------------------------------------------------------

//canvasの大きさ/全てこの値を使用
var canvasWidth=640;
var canvasHeight=300;

//画像manifestリスト
var manifest=[
{src:"/main/images/textback01.jpg",id:"text"},
{src:"/main/images/textback02.jpg",id:"text"},
{src:"/main/images/textback03.jpg",id:"text"},
{src:"/main/images/textback04.jpg",id:"text"},
{src:"/main/images/textback05.jpg",id:"text"},
{src:"/main/images/textback06.jpg",id:"text"},
{src:"/main/images/textback07.jpg",id:"text"},
{src:"/main/images/textback08.jpg",id:"text"},
{src:"/main/images/textback09.jpg",id:"text"},
{src:"/main/images/textback10.png",id:"text"},
{src:"/main/images/textback11.png",id:"text"},
{src:"/main/images/textback12.png",id:"text"},
{src:"/main/images/textback13.png",id:"text"},
{src:"/main/images/textback14.jpg",id:"text"},
{src:"/main/images/textback15.png",id:"text"},
{src:"/main/images/sky_back2.jpg",id:"photo"},
{src:"/main/images/green.jpg",id:"photo"},
{src:"/main/images/textimg01.png",id:"title"},
{src:"/main/images/welcome32.png",id:"title"},
{src:"/main/images/welcome32_shadow.png",id:"title"},
{src:"/main/images/welcome32_2.png",id:"title"}
];

//------------------------------------------------------
//変数、未使用もあり

//ステージ
var stage,stage2;
//コンテナなど
var backrect;
var backImage;
//TEST
var pngImage,pngImage2,pngImage3,pngImage4,pngImage5;
var pngcontainer,pngcontainer2,pngcontainer3,pngcontainer4,pngcontainer5;//stage
var pngcontainer6,pngcontainer7;//stage2
var container;
//TEXT
var viewtext;
//読み込み画像URL保存容器
var assets=[];
var backphotos=[];
var titles=[];
var loader;
var image_max;

//click
var showflag=true;
//------------------------------------------------------
//shadowフィルター
var shadow=new createjs.Shadow("#000000",0,0,4);

//------------------------------------------------------

//ステージ周りセット
function init() {

	//STAGE
	stage=new createjs.Stage('mainCanvas');
	//MouseOver重要必要に応じ設定
	//stage.enableMouseOver(20);
	//STAGE2
	stage2=new createjs.Stage('subCanvas');

	//バックRect/最下位色背景層、無くとも良い
	backrect=new createjs.Shape();
	backrect.graphics.beginFill("#FFFFFF").drawRect(0,0,canvasWidth,canvasHeight);
	stage.addChild(backrect);

	//背景画像1
	backImage=new createjs.Bitmap();
	stage.addChild(backImage);
	backImage.visible=true;

	//クリック背景画像切り替え
	stage.addEventListener("click",function() {
		if (!showflag) {
			backImage.visible=true;
			showflag=true;
			return;
		}
		if (showflag) {
			backImage.visible=false;
			showflag=false;
		}
	});

	//表示コンテナ
	//1
	pngcontainer=new createjs.Container();
	stage.addChild(pngcontainer);

	//2
	pngcontainer2=new createjs.Container();
	stage.addChild(pngcontainer2);

	//3
	pngcontainer3=new createjs.Container();
	stage.addChild(pngcontainer3);

	//4
	pngcontainer4=new createjs.Container();
	stage.addChild(pngcontainer4);

	//5
	pngcontainer5=new createjs.Container();
	stage.addChild(pngcontainer5);

	//簡易TEXT
	viewtext=new createjs.Text("","12px Arial","#FFFFFF");
	viewtext.x=20;
	viewtext.y=15;
	viewtext.maxWidth=canvasWidth-40;
	viewtext.lineHeight=20;
	viewtext.textBaseline="bottom";
	viewtext.shadow=shadow;//SHADOW処理
	stage.addChild(viewtext);
	set_text("LOADING NOW!");

	stage.update();

	//6
	pngcontainer6=new createjs.Container();
	stage2.addChild(pngcontainer6);
	//7
	pngcontainer7=new createjs.Container();
	stage2.addChild(pngcontainer7);
	stage2.update();

	createjs.Ticker.setFPS(30);
	createjs.Ticker.addEventListener('tick',tick);

	//調整
	setTimeout(function() {

		//画像一括ロードに進む
		bulkload();

	},1000);

}

//bulk-load、画像一括ロード
function bulkload() {

	//Loader
	loader=new createjs.LoadQueue(false);

	//loader EventListener設定、この部分修正
	loader.addEventListener("fileload",fileload);
	loader.addEventListener("complete",complete);
	//Manifestを使用、manifest読み込み開始
	loader.loadManifest(manifest);

}
//各画像読み込み完了
function fileload (event) {

	var id=event.item.id;
	//エラー無しの画像をassets容器に保存
	//画像選別
	if (id == 'text') {
		//result値
		assets.push(event.result);
	}
	if (id == 'photo') {
		//result値
		backphotos.push(event.result);
	}
	if (id == 'title') {
		//result値
		titles.push(event.result);
	}

}
//全ての画像読み込み完了
function complete (event) {

	set_text("LOADING END!");
	//画像数確認、再計算
	image_max=assets.length;

	//loader Listener削除
	loader.removeEventListener("fileload",fileload);
	loader.removeEventListener("complete",complete);

	//背景画像表示
	backImage.image=new createjs.Bitmap(backphotos[1]).image;

	//画像があれば
	if (image_max) {
		setTimeout(function() {

			set_text("");

			//MAINに進む
			set_maintext();
			//SUBMAINに進む
			set_submaintext();

		},1000);
	}

}

//MAINサンプル表示
function set_maintext() {

	//---------サンプル1-----------------------------------

	//TESTコンテナ1
	pngcontainer.x=canvasWidth/2;
	pngcontainer.y=canvasHeight/2;
	var img=titles[0];

	//画像表示 340x50
	pngImage=new createjs.Bitmap(img);
	pngImage.regX=340/2;
	pngImage.regY=50/2;
	pngImage.scaleX=2;
	pngImage.scaleY=2;
	pngImage.rotation=-30;
	//add
	pngcontainer.addChild(pngImage);

	//---------サンプル2-----------------------------------

	//TESTコンテナ2
	pngcontainer2.x=0;
	pngcontainer2.y=5;
	var img=titles[1];

	//陰影用の黒画像を得る
	//幅、高さ、画像、色
	var bitmap=colorChg_image(340,80,img,"#000000");
	var shadowImage=new createjs.Bitmap(bitmap);

	//対象、幅、高さ、ぼかし強度
	set_blur(shadowImage,340,80,10);//Blur陰影画像にする
	pngImage2=new createjs.Bitmap(img);//上画像を重ねる

	//add
	pngcontainer2.addChild(shadowImage,pngImage2);

	//---------サンプル3-----------------------------------

	//TESTコンテナ3
	pngcontainer3.x=0;
	pngcontainer3.y=75;
	var img=titles[1];

	var img2=assets[1];//画像

	//ライングラデーションの例
	//var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","y",2);//グラデ1
	//var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","y",3);//グラデ2
	//var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","x",2);//グラデ3
	//var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","x",3);//グラデ4
	//var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","xy",3);//グラデ5
	//var img2=createLineGradBox (340,80,"#FF0000","#FFD700","#00FF00","x",3);//グラデ6
	//var img2=createLineGradBox (340,80,"#FFB6C1","#C71585","#FFB6C1","y",2);//グラデ7

	//クローン
	var shadowImage2=shadowImage.clone();
	//対象、幅、高さ、ぼかし強度
	set_blur (shadowImage2,340,80,5);//Blur陰影画像にする

	//画像表示
	//幅、高さ、画像、画像2
	pngImage3=new createjs.Bitmap(set_textImage(340,80,img,img2));
	//add
	pngcontainer3.addChild(shadowImage2,pngImage3);

	//---------サンプル4-----------------------------------

	//TESTコンテナ4
	pngcontainer4.x=300;
	pngcontainer4.y=150;
	var img=titles[2];
	var img2=assets[12];

	//画像表示
	//幅、高さ、画像、画像2
	pngImage4=new createjs.Bitmap(set_textImage(340,80,img,img2));
	//add
	pngcontainer4.addChild(pngImage4);

	//---------サンプル5-----------------------------------

	//TESTコンテナ5
	pngcontainer5.x=300;
	pngcontainer5.y=220;
	var img=titles[2];

	//画像表示/XOR処理、陰影つき透過画像対象
	//幅、高さ、画像
	pngImage5=new createjs.Bitmap(set_image_xor(340,80,img));
	//add
	pngcontainer5.addChild(pngImage5);

}

//SUBMAINサンプル表示
function set_submaintext() {

	//---------サンプル6-----------------------------------

	//余白のある画像
	pngcontainer6.x=20;
	pngcontainer6.y=15;
	var img=titles[1];

	//ChromeNG
	var pngImage6=new createjs.Bitmap(img);
	pngImage6.shadow=new createjs.Shadow("#000000",0,0,4);
	pngcontainer6.addChild(pngImage6);

	//---------サンプル7-----------------------------------

	//余白の無い画像
	pngcontainer7.x=20;
	pngcontainer7.y=100;
	var img=titles[3];
	//画像周囲に余白を作る
	//Box幅 高さ、画像、画像幅 高さ
	img=set_boxCenter(340,80,img,308,66);

	//ChromeNG
	var pngImage7=new createjs.Bitmap(img);
	pngImage7.shadow=new createjs.Shadow("#000000",0,0,4);
	pngcontainer7.addChild(pngImage7);

	//-----------------------------------------------------

	stage2.update();
}

//tickステージ
function tick() {
	stage.update();
}

//VIEWTEXT
function set_text(t) {
	viewtext.text=t;
}

//--------------------------------------------------------------------------------------

//幅、高さ、画像、画像2、
function set_textImage(w,h,img,img2) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.translate(w/2,h/2);

	//画像合成
	//ctx.drawImage(img2,-w/2,-h/2,w,h);//染め抜きはOK/画面あわせ伸縮
	ctx.drawImage(img2,-w/2,-h/2);//原点あわせのみ伸縮なし

	ctx.globalCompositeOperation="destination-in";//destination-in
	ctx.drawImage(img,-w/2,-h/2,w,h);

	return canvas;
}

//XOR処理、陰影つき透過画像対象
//幅、高さ、画像
function set_image_xor(w,h,img) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//原点移動translate
	ctx.translate(w/2,h/2);

	//下画像配置
	ctx.drawImage(img,-w/2,-h/2,w,h);

	ctx.globalCompositeOperation="xor";//destination-outは薄い
	//画像配置
	ctx.drawImage(img,-w/2,-h/2,w,h);

	return canvas;
}

//OUT処理、陰影無し透過画像対象
//幅、高さ、陰影画像、画像、合成
function set_shadow_out(w,h,shadow_img,img,destination) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//原点移動translate
	ctx.translate(w/2,h/2);

	//下陰影画像配置
	ctx.drawImage(shadow_img,-w/2,-h/2,w,h);

	ctx.globalCompositeOperation=destination;//destination-out destination-in xor/source-in source-out
	//画像配置
	ctx.drawImage(img,-w/2,-h/2,w,h);

	return canvas;
}

//CompositeOperationで画像の色を替える
//幅、高さ、画像、色
function colorChg_image(w,h,img,color){
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//色画像
	var img2=createColorCanvas(w,h,color);
	//画像配置
	ctx.drawImage(img2,0,0,w,h);//色画像
	ctx.globalCompositeOperation="destination-in";
	//合成
	ctx.drawImage(img,0,0,w,h);//画像

	return canvas;
}
//--------------------------------------------------------------------------------------

//色画像
//全幅、全高さ、背景色
function createColorCanvas(w,h,c) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=c;
	ctx.fillRect(0,0,w,h);

	return canvas;
}
//幅、高さ、画像
function createImgCanvas(w,h,patternimg) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.drawImage(patternimg,0,0,w,h);

	return canvas;
}

//トリミング画像、X、Y、幅、高さ、
function imageTrimmingCanvas(patternimg,sx,sy,sw,sh,dx,dy,dw,dh) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=sw;
	canvas.height=sh;
	var ctx=canvas.getContext("2d");
	ctx.drawImage(patternimg,sx,sy,sw,sh,dx,dy,dw,dh);

	return canvas;
}

//LinearGradientBox
//幅、高さ、色1、色2、色3、方向(x.y)、タイプ(2.3)
function createLineGradBox (w,h,color1,color2,color3,direction,type) {

	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");

	//LinearGradient
	var gradient;
	if(direction == 'x') {
		gradient=ctx.createLinearGradient(0,h,w,h);
	}
	if(direction == 'y') {
		gradient=ctx.createLinearGradient(w,0,w,h);
	}
	if(direction == 'xy') {
		gradient=ctx.createLinearGradient(0,0,w,h);
	}
	if(type == 2) {
		gradient.addColorStop(0,color1);
		gradient.addColorStop(1,color2);
	}
	if(type == 3) {
		gradient.addColorStop(0,color1);
		gradient.addColorStop(0.5,color2);
		gradient.addColorStop(1,color3);
	}
	ctx.fillStyle=gradient;
	//FILL
	ctx.fillRect(0,0,w,h);

	return canvas;
}
//色画像
//全幅、全高さ、背景色
function createColorCanvas(w,h,c) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=c;
	ctx.fillRect(0,0,w,h);

	return canvas;
}

//画像周囲に余白を作る/中心に配置
//Box幅 高さ、画像、画像幅 高さ
function set_boxCenter(w,h,img,w2,h2) {

	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//中心移動
	ctx.translate(w/2,h/2);
	ctx.fillStyle='rgba(0,0,0,0)';
	ctx.fillRect(-w/2,-h/2,w,h);
	ctx.drawImage(img,-w2/2,-h2/2,w2,h2);

	return canvas;
}

//--------------------------------------------------------------------------------------
//canvasで陰影をセットする
//幅、高さ、画像、陰影色、X、Y、W
function set_shadow_image (w,h,img,color,blur_x,blur_y,blur_w) {
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");

	//shadow
	ctx.shadowColor=color;//OK
	ctx.shadowOffsetX=blur_x;
	ctx.shadowOffsetY=blur_y;
	ctx.shadowBlur=blur_w;

	//画像描画
	ctx.drawImage(img,0,0,w,h);

	return canvas;
}

//canvasでblur陰影をセットする/ChromeNG
//幅、高さ、画像、陰影色、X、Y、W
function set_blur_image (w,h,img,color,blur_x,blur_y,blur_w) {
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");

	ctx.shadowColor=color;
	ctx.shadowOffsetX=blur_x;
	ctx.shadowOffsetY=blur_y;
	ctx.shadowBlur=blur_w;

	ctx.drawImage(get_base(w,h,img,color),0,0,w,h);

	//画像描画
	ctx.drawImage(img,0,0,w,h);

	return canvas;

	function get_base (w,h,img,color) {
		var canvas=document.createElement("canvas");
		//指定の大きさになる
		canvas.width=w;
		canvas.height=h;
		var ctx=canvas.getContext("2d");
		ctx.fillStyle=color;
		ctx.fillRect(0,0,w,h);
		//destination-inマスク
		ctx.globalCompositeOperation="destination-in";
		ctx.drawImage(img,0,0,w,h);
		return canvas;
	}

}

//ぼかし陰影画像キャッシュを作る
//幅、高さ、画像、陰影色、強度
function createShadowCanvas(w,h,img,scolor,strong){

	//陰影用の画像を作る
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=scolor;
	ctx.fillRect(0,0,w,h);
	//destination-inマスク
	ctx.globalCompositeOperation="destination-in";
	ctx.drawImage(img,0,0,w,h);//陰影用元画像

	//bitmapに収納ダミーコンテナでキャッシュを得る
	var dmycontainer=new createjs.Container();
	var bitmap=new createjs.Bitmap(canvas);
	//Blurフィルター
	set_blur(bitmap,w,h,strong);//Blur陰影画像にする
	dmycontainer.addChild(bitmap);

	dmycontainer.cache(0,0,w,h);
	var cache_shadow=dmycontainer.cacheCanvas;

	//キャッシュを返す
	return cache_shadow;
}

//Blurフィルター
//対象、幅、高さ、ぼかし強度
function set_blur (item,w,h,strong) {

	var blurFilter=new createjs.BlurFilter(strong,strong,1);
	item.filters=[blurFilter];
	var margins=blurFilter.getBounds();
	//完全では無いと思う、余裕重要
	item.cache(-margins.x-7,-margins.y-7,w+margins.width+14,h+margins.height+14);
}

//--------------------------------------------------------------------------------------

//START
init();

注釈文を削除すれば、幾分早くなります。未使用の関数なども含みます。
画像使用の場合、登録画像パスは当方の例です。使用の際は環境に合わせて下さい。


CSS

createJS107.css、CSS名は任意に変更可


/*日本語 createJS107.css*/

#demo-wrap {
position:relative;
width:auto;
height:580px;
text-align:center;
}

#image-box {
/*position:absolute;*/
position:relative;
top:0;left:0;
width:640px;
height:300px;
padding:0;
margin:0 auto;
box-shadow:0 0 10px #000;
-moz-box-shadow:0 0 10px #000;
-webkit-box-shadow:0 0 10px #000;
-o-box-shadow:0 0 10px #000;
-ms-box-shadow:0 0 10px #000;
background-color:#000000;
}

#image-box #mainCanvas {
border-radius:10px;
}
.radius {
border-radius:10px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
-o-box-border-radius:10px;
-ms-border-radius:10px;
}
#image-box2 {
position:relative;
top:0;left:0;
width:640px;
height:200px;
padding:0;
margin:0 auto;
background-color:#FFFFFF;
}
#image-box2 #subCanvas {
border:1px #CCCCCC solid;
}

当方のサンプルの例です。


 

簡単な説明


[説明図]

 

// 以下のような処理をすることは「一生に一度無いでしょう」。よって興味のある方はお読みください。//


 

透過PNG画像に陰影処理(ドロップシャドウ)


ドロップシャドウの無い透過PNG画像に、「Blurフィルター」で陰影処理(ドロップシャドウ)する方法です。
Textクラスで描画したテキストの処理では有りませんので注意ください。


1. 透過PNG画像より黒色の同じ画像を作ります。
2. それをCreateJSの「Blurフィルター」でドロップシャドウに加工します。
3. 元の透過PNG画像と出来上がりのドロップシャドウを重ねて表示します。
4. ドロップシャドウ付きの透過PNG画像はCompositeOperation合成で少し加工できます。
5. 上記処理は必ずしも必要なものでは有りません。最初からドロップシャドウ付きの透過PNG画像であれば良い。(ドロップシャドウ付きの透過PNG画像もCanvasに表示できる)
6. 何らかの場面で「陰影処理」が必要な場合もあるかも知れませんので、テストしておきます。


透過PNG画像の表示

透過PNG画像は以下の様にHtmlでも表示します。CanvasではBitmapクラスで、通常の画像と同じ様に表示出来ます。下の画像のテキスト部分は上下左右余裕を持って配置しています。(重ねる場合に位置あわせが簡単になるし、画像も作り易い)


そのまま「陰影処理」した場合の「デモ」を「ステージ2」に表示しています。


ドロップシャドウ付きのものは少しは加工処理を出来ますが、加工には不向きです。

textimg01.png 340x50、ドロップシャドウ

welcome32_shadow.png 340x80、ドロップシャドウ


陰影処理する対象は下記のような、ドロップシャドウ無しの白色文字透過PNG画像です。
(灰色部分は下の背景色で画像は透過しています)

welcome32.png 340x80


まったく余裕が無い場合、上下に円弧が接するような形状の場合「欠け」が生じますので、理想的には2ピクセル以上の余白が必要です。

welcome32_2.png 308x66、余白の無い画像


CreateJSの「shadowフィルター」陰影処理

「shadowフィルター」陰影処理するのが一番簡単なのですが、透過PNG画像の場合では......

 

 

図の様に、Chrome(Opera)では旨く処理されません。画像に余白がないとこれも綺麗に処理されません。


 

「Blurフィルター」でぼかして陰影処理

白色文字画像の処理例

Chrome(Opera)では、CreateJSの「shadowフィルター」陰影が処理できませんので、「Blurフィルター」でぼかして陰影を作れば、ブラウザ共通に処理できますからChrome(Opera)でもOKです。
この方法で以下処理します。

 

 

ドロップシャドウ無しの透過PNG画像が対象ですが、初めにCompositeOperation合成で「黒色」画像を作り、それを「Blurフィルター」でぼかします。
次に、通常の画像を上に重ねてドロップシャドウが付いた状態に見せかけます。


1. 幅、高さは画像の大きさです。
2. ぼかし強度は、Blurの幅です。
3. 陰影の位置は「陰影画像」の x y 値で調整できます。
4. Chromeのバグと理解して、これが修正されてもこのまま機能する。


サンプル2

透過PNG画像は白色テキストの画像です。一応処理できます。


注意、「Blurフィルター」される画像に変化はありません。CreateJSで自動的に画像の下にフィルター処理された陰影画像(cache)が挿入された様な状態になります。陰影画像はcacheCanvasにあります。




//TESTコンテナ2
pngcontainer2.x=0;
pngcontainer2.y=5;
var img=titles[1];

//陰影用の黒画像を得る
//幅、高さ、画像、色
var bitmap=colorChg_image(340,80,img,"#000000");
var shadowImage=new createjs.Bitmap(bitmap);
//対象、幅、高さ、ぼかし強度
set_blur(shadowImage,340,80,10);//Blur陰影画像にする

pngImage2=new createjs.Bitmap(img);//上画像を重ねる

//add
pngcontainer2.addChild(shadowImage,pngImage2);

-----------------------------------------------------------------------

//Blurフィルター
//対象、幅、高さ、ぼかし強度
function set_blur (item,w,h,strong) {

	var blurFilter=new createjs.BlurFilter(strong,strong,1);
	item.filters=[blurFilter];
	var margins=blurFilter.getBounds();
	//完全では無いと思う、余裕重要
	item.cache(-margins.x-7,-margins.y-7,w+margins.width+14,h+margins.height+14);

}

-----------------------------------------------------------------------

//CompositeOperationで画像の色を替える
//幅、高さ、画像、色
function colorChg_image(w,h,img,color){
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//色画像
	var img2=createColorCanvas(w,h,color);
	//画像配置
	ctx.drawImage(img2,0,0,w,h);//色画像
	ctx.globalCompositeOperation="destination-in";
	//合成
	ctx.drawImage(img,0,0,w,h);//画像

	return canvas;
}

サンプル3

透過PNG画像は白色テキストの画像ですが、模様のある画像を取り込んで装飾しました。
この例では、クローンで処理しましたが、別に処理するには上の サンプル2 と同様になります。




//TESTコンテナ3
pngcontainer3.x=0;
pngcontainer3.y=75;
var img=titles[1];

var img2=assets[1];//画像
//var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","y",2);//グラデ

//クローン
var shadowImage2=shadowImage.clone();
//対象、幅、高さ、ぼかし強度
set_blur (shadowImage2,340,80,5);//Blur陰影画像にする

//画像表示
//幅、高さ、画像、画像2
pngImage3=new createjs.Bitmap(set_textImage(340,80,img,img2));
//add
pngcontainer3.addChild(shadowImage2,pngImage3);

-----------------------------------------------------------------------

//幅、高さ、画像、画像2、
function set_textImage(w,h,img,img2) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.translate(w/2,h/2);

	//画像合成
	//ctx.drawImage(img2,-w/2,-h/2,w,h);//染め抜きはOK/画面あわせ伸縮
	ctx.drawImage(img2,-w/2,-h/2);//原点あわせのみ伸縮なし

	ctx.globalCompositeOperation="destination-in";//destination-in
	ctx.drawImage(img,-w/2,-h/2,w,h);

	return canvas;
}

サンプル4 5

こちらは、ドロップシャドウ有りの透過PNG画像が対象です。多少のCompositeOperation合成処理で変化を付けることが可能です。詳細はJSを参照ください。


作った陰影のBitmapを得る、(cache)

陰影を他の目的で使用するために陰影の画像を取得したい場合もあります。
実際の作業でここまでする事は無いと思いますが.... 、興味のある方は以下お読みください。


● 直接cacheCanvasを得る

サンプル2の場合での例とすると、Blurフィルター処理set_blur()の直後に cacheCanvas を得れば良いことになる。
表示するならBitmapクラスを利用すれば良い。
但し、これは大きさがBoundsで広がっているので、加工する場合は使い難い。



//陰影用の黒画像を得る/幅、高さ、画像、色
var bitmap=colorChg_image(340,80,img,"#000000");
var shadowImage=new createjs.Bitmap(bitmap);

----------------------------------------------------------------------------

set_blur(shadowImage,..);
var shadowImageX=new createjs.Bitmap(shadowImage.cacheCanvas);

位置を旨く合わせられるなら、こちらが簡単なのですが......


● ダミーコンテナで処理してcacheCanvasを得る

少々面倒ですが、ダミーコンテナで処理すると、得られた画像キャッシュは位置あわせが簡単になる。cache_shadow に画像の大きさと同じ「Blurフィルター」処理された、cacheCanvas を得られるのでその後の加工処理がし易い。
ダミーコンテナはステージに addChild していないので表示はしません。メモリー上の処理になる。
画像に余白を取ってテキストを配置して作成している理由がここにある。




//画像
var img=titles[1];
//陰影用の黒画像を得る/幅、高さ、画像、色
var bitmap=colorChg_image(340,80,img,"#000000");
var shadowImage=new createjs.Bitmap(bitmap);
//対象、幅、高さ、ぼかし強度
set_blur(shadowImage,340,80,10);//Blur陰影画像にする
//ダミーコンテナでキャッシュを得る
var dmycontainer=new createjs.Container();
dmycontainer.addChild(shadowImage);
dmycontainer.cache(0,0,340,80);
var cache_shadow=dmycontainer.cacheCanvas;

表示したければBitmapクラスを利用し



var shadowImageX=new createjs.Bitmap(cache_shadow);
または
var shadowImageX=new createjs.Bitmap(dmycontainer.cacheCanvas);

上記処理を少し簡素化するため次の関数でまとめて処理しても良い。処理内容は同じ。


//少しまとめている
//ぼかし陰影画像キャッシュを作る
//幅、高さ、画像、陰影色、強度
var shadowImage=new createjs.Bitmap(createShadowCanvas(340,80,titles[1],"#000000",10));

----------------------------------------------------------------------------------

//ぼかし陰影画像キャッシュを作る
//幅、高さ、画像、陰影色、強度
function createShadowCanvas(w,h,img,scolor,strong){

	//陰影用の画像を作る
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=scolor;
	ctx.fillRect(0,0,w,h);
	//destination-inマスク
	ctx.globalCompositeOperation="destination-in";
	ctx.drawImage(img,0,0,w,h);//陰影用元画像

	//bitmapに収納ダミーコンテナでキャッシュを得る
	var dmycontainer=new createjs.Container();
	var bitmap=new createjs.Bitmap(canvas);
	//Blurフィルター
	set_blur(bitmap,w,h,strong);//Blur陰影画像にする
	dmycontainer.addChild(bitmap);

	dmycontainer.cache(0,0,w,h);
	var cache_shadow=dmycontainer.cacheCanvas;

	//キャッシュを返す
	return cache_shadow;
}

----------------------------------------------------------------------------------

//Blurフィルター
//対象、幅、高さ、ぼかし強度
function set_blur (item,w,h,strong) {

	var blurFilter=new createjs.BlurFilter(strong,strong,1);
	item.filters=[blurFilter];
	var margins=blurFilter.getBounds();
	//完全では無いと思う、余裕重要
	item.cache(-margins.x-7,-margins.y-7,w+margins.width+14,h+margins.height+14);
}

 

cacheCanvas陰影画像を加工する

 

 

ダミーコンテナで処理してcacheCanvasで得た陰影画像を加工すると、陰影(destination-out)、べベル(source-in source-out)などを得ることも出来ます。
模様のある画像をCompositeOperation合成処理でマスクした画像と陰影を組み合わせれば、装飾の幅が広がるかも知れません。
下記処理は、Boundsでの大きさ修正はしていませんがきっちり位置が合います。



//OUT処理、陰影無し透過画像対象
//陰影destination-out destination-in xor/べベルsource-in source-out
//幅、高さ、陰影画像、画像、合成
pngcontainer2.addChild(new createjs.Bitmap(set_shadow_out(340,80,cache_shadow,img,"destination-out")));

----------------------------------------------------------------------

//OUT処理、陰影無し透過画像対象
//幅、高さ、陰影画像、画像、合成
function set_shadow_out(w,h,shadow_img,img,destination) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//原点移動translate
	ctx.translate(w/2,h/2);

	//下陰影画像配置
	ctx.drawImage(shadow_img,-w/2,-h/2,w,h);

	ctx.globalCompositeOperation=destination;//destination-out destination-in xor/source-in source-out
	//画像配置
	ctx.drawImage(img,-w/2,-h/2,w,h);

	return canvas;
}

次の処理では、余り品質は良くないが、陰影とエンボスの画像が得られます。



//陰影とエンボス
pngcontainer2.addChild(new createjs.Bitmap(set_image_xor(340,80,cache_shadow)));

----------------------------------------------------------------------

//XOR処理、陰影つき透過画像対象
//幅、高さ、画像
function set_image_xor(w,h,img) {
	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//原点移動translate
	ctx.translate(w/2,h/2);

	//下画像配置
	ctx.drawImage(img,-w/2,-h/2,w,h);

	ctx.globalCompositeOperation="xor";//destination-outは薄い
	//画像配置
	ctx.drawImage(img,-w/2,-h/2,w,h);

	return canvas;
}

余白の無い画像の修正

余白の無い画像の場合所定の大きさのエレメントに画像を描画して、余白を作った画像にします。
下記例では、340x80のエレメント中心に304x63の画像を描画配置します。




//画像304x63
var img=titles[3];
//画像周囲に余白を作る
//Box幅 高さ、画像、画像幅 高さ
img=set_boxCenter(340,80,img,304,63);

----------------------------------------------------------------------

//画像周囲に余白を作る/中心に配置
//Box幅 高さ、画像、画像幅 高さ
function set_boxCenter(w,h,img,w2,h2) {

	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	//中心移動
	ctx.translate(w/2,h/2);
	ctx.fillStyle='rgba(0,0,0,0)';
	ctx.fillRect(-w/2,-h/2,w,h);
	ctx.drawImage(img,-w2/2,-h2/2,w2,h2);

	return canvas;
}

その他の加工方法
2つの透過PNG画像を使用したり、アイデア次第では別の変化も可能かも知れません。ぜひ試してください。


「デモ」ではテキスト画像を使用していますが、何らかの形と考えればよい。「Flash」などと違い、複雑な図形をグラフイックで描くのは困難ですので、透過PNG画像を用いることも想定されますから一応テストしました。


Textクラスで描画したテキストには通常の陰影処理(CreateJSの「shadowフィルター」)が出来ますのでご注意ください。上記の処理とはまったく違いますしCompositeOperation合成処理の振る舞いも違ってきます。


 

その他


トリミング

大きな画像の場合はトリミングが必要に成る場合もあるでしょう。下記の、imageTrimmingCanvas関数を利用すればトリミングできます。drawImage()処理。
指定は画像範囲内で行ってください。下記例 のbackphotos[2] は読み込み画像のresult値です。



トリミング画像=imageTrimmingCanvas(画像,元画像X,元画像Y,元画像W,元画像H,0,0,新画像W,新画像H);

//トリミング画像、X、Y、幅、高さ、
var img=imageTrimmingCanvas(backphotos[2],0,100,640,100,0,0,640,100);

-------------------------------------------------------------------------------------

//トリミング画像、X、Y、幅、高さ、
function imageTrimmingCanvas(patternimg,sx,sy,sw,sh,dx,dy,dw,dh) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=sw;
	canvas.height=sh;
	var ctx=canvas.getContext("2d");
	ctx.drawImage(patternimg,sx,sy,sw,sh,dx,dy,dw,dh);

	return canvas;
}

代替画像の使用

テキストで抜く場合などでは、画像ではなくグラデーション塗りのエレメント、またはベタ塗りのエレメントがほしい場合があります。画像で作るには大変面倒です。
次の様にして簡単に作ることが出来ます。画像の代わりに入れればよい。


● ベタ塗りのエレメント
読み込み画像の変わりに「色つきのエレメント」を作り代入すればよい。



赤色ベタぬり
var img=createColorCanvas(640,100,"#FF0000");
赤色ベタぬり、透明度0.5
var img=createColorCanvas(640,100,"rgba(255,0,0,0.5)");

-------------------------------------------------------------------------------------------

//色画像
//全幅、全高さ、背景色
function createColorCanvas(w,h,c) {
	//Box
	var canvas=document.createElement("canvas");
	//指定の大きさになる
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");
	ctx.fillStyle=c;
	ctx.fillRect(0,0,w,h);

	return canvas;
}


● グラデーション塗りのエレメント(ライングラデーション)
読み込み画像の変わりに「グラデーション塗りのエレメント」を作り代入すればよい。
LinearGradientの例、二番目は画像と同じものを「エレメント」で作れる。色、direction、type、の設定で色々な形態になる。透明度は、rgba() で指定できる。


 

透明度ライングラデーションは下に陰影があるために旨く色合わせが出来ない場合有り。



1、上赤色、下黒色のY方向ライングラデーション
var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","y",2);//グラデ1

2、その他
var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","y",3);//グラデ2
var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","x",2);//グラデ3
var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","x",3);//グラデ4
var img2=createLineGradBox (340,80,"#FF0000","#000000","#FF0000","xy",3);//斜めグラデ5
var img2=createLineGradBox (340,80,"#FF0000","#FFD700","#00FF00","x",3);//グラデ6
var img2=createLineGradBox (340,80,"#FFB6C1","#C71585","#FFB6C1","y",2);//グラデ7

3、上黒色透明度0、下黒色透明度1のY方向ライングラデーション、使用に注意
var img2=createLineGradBox(340,80,"rgba(0,0,0,0)","rgba(0,0,0,1)","rgba(0,0,0,0)","y",2);

-------------------------------------------------------------------------------------------

//LinearGradientBox
//幅、高さ、色1、色2、色3、方向(x.y)、タイプ(2.3)
function createLineGradBox (w,h,color1,color2,color3,direction,type) {

	var canvas=document.createElement("canvas");
	canvas.width=w;
	canvas.height=h;
	var ctx=canvas.getContext("2d");

	//LinearGradient
	var gradient;
	if(direction == 'x') {
		gradient=ctx.createLinearGradient(0,h,w,h);
	}
	if(direction == 'y') {
		gradient=ctx.createLinearGradient(w,0,w,h);
	}
	if(direction == 'xy') {
		gradient=ctx.createLinearGradient(0,0,w,h);
	}
	if(type == 2) {
		gradient.addColorStop(0,color1);
		gradient.addColorStop(1,color2);
	}
	if(type == 3) {
		gradient.addColorStop(0,color1);
		gradient.addColorStop(0.5,color2);
		gradient.addColorStop(1,color3);
	}
	ctx.fillStyle=gradient;
	//FILL
	ctx.fillRect(0,0,w,h);

	return canvas;
}

画像

原則、使用者が用意ください。640x100画像、640x300画像、デモ使用の画像は「デモページ」にあります。


下記はTextクラスで描画したテキストなどに関する記事です。

【参照】当方の記事: CreateJS CanvasエレメントでCompositeOperation合成テキスト表示

【参照】当方の記事: CreateJS フォントをGraphicsクラスで描画する



一応、完動しますが全てテストです。効率化のため、予告無くJSなど修正する場合がありますので了承下さい。

CreateJSは結構「仕様」が変わりますので特に注意が必要です。


 

実際に試してみないと説明のみでは理解し難いと思います。以上です。

 


[ この記事のURL ]


 

ブログ記事一覧



[1]