私のプロジェクトでは、キャンバスを使用して他の同じサイズとパターン画像に1つの異なるカラー画像を実装する必要があり、画像は円形または長方形ではありません。これらはすべて波形であり、すべてのonclick
関数で複数のグラフィックを表示するために単一のメイン背景画像に適用されます。
重なった画像は、選択した別の色に変更する必要があります。私の質問キャンバスを使用する方法はありますか?キャンバスによって描画される画像の色を変更できるか、常に異なる画像を使用してCSS/jQueryで適用する必要がありますか?.
キャンバスの画像のマスキングとオーバーラップについて読みました。しかし、正方形または円形ではないため、私の画像では理解できません。最初に、単一の画像に複数の波形を描画する方法です。私が検索したことはわかりませんが、完璧なソリューションを検索できません。
私のニーズは、キャンバス上に1つの波の画像を描画し、クリック機能から色を変更し、さらに背景画像で別のdivを設定し、さらに2つ以上のキャンバスが重なることです。これは可能ですか?
(つまり、この機能は車で複数のグラフィックを作成または設定するためのものであり、各グラフィック画像はキャンバスに設定する必要があり、別のグラフィックはdivと最初のキャンバスにオーバーラップする必要があります)
コンテキスト合成を使用して、画像の一部を置き換えることができます。
たとえば、この青いロゴが既に画像としてある場合:
ロゴの上部を紫色にしたい場合:
合成を使用して、画像の上部の色を変更できます。
まず、お気に入りの画像エディターを使用して、色を変更したくない不要な部分を切り取ります。
残ったものはオーバーレイと呼ばれます。
画像のこのオーバーレイ部分は、プログラムで色を変更します。
このオーバーレイは、任意の色にプログラムで色を変更できます。
オーバーレイのプログラム上の色の変更方法:
変更されたオーバーレイ色でロゴを完成させる方法
この「デスティネーショントップ」の合成効果は、「ドローイングアンダー」とも呼ばれます。
このオーバーレイは、テクスチャに置き換えることもできます!
ここにコードとフィドルがあります: http://jsfiddle.net/m1erickson/bfUPr/
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; padding:20px; }
#canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var truck,logo,overlay;
var newColor="red";
var imageURLs=[];
var imagesOK=0;
var imgs=[];
imageURLs.Push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/boxTruck.png");
imageURLs.Push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmall.png");
imageURLs.Push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/TVlogoSmallOverlay.png");
loadAllImages();
function loadAllImages(){
for (var i = 0; i < imageURLs.length; i++) {
var img = new Image();
imgs.Push(img);
img.onload = function(){ imagesOK++; imagesAllLoaded(); };
img.src = imageURLs[i];
}
}
var imagesAllLoaded = function() {
if (imagesOK==imageURLs.length ) {
// all images are fully loaded an ready to use
truck=imgs[0];
logo=imgs[1];
overlay=imgs[2];
start();
}
};
function start(){
// save the context state
ctx.save();
// draw the overlay
ctx.drawImage(overlay,150,35);
// change composite mode to source-in
// any new drawing will only overwrite existing pixels
ctx.globalCompositeOperation="source-in";
// draw a purple rectangle the size of the canvas
// Only the overlay will become purple
ctx.fillStyle=newColor;
ctx.fillRect(0,0,canvas.width,canvas.height);
// change the composite mode to destination-atop
// any new drawing will not overwrite any existing pixels
ctx.globalCompositeOperation="destination-atop";
// draw the full logo
// This will NOT overwrite any existing purple overlay pixels
ctx.drawImage(logo,150,35);
// draw the truck
// This will NOT replace any existing pixels
// The purple overlay will not be overwritten
// The blue logo will not be overwritten
ctx.drawImage(truck,0,0);
// restore the context to it's original state
ctx.restore();
}
}); // end $(function(){});
</script>
</head>
<body>
<canvas id="canvas" width=500 height=253></canvas>
</body>
</html>
現状の問題は、少し不明確なIMOです。クリッピングが必要なシナリオに適用できるより一般的な答えを与えるには、(少なくとも)2つのアプローチを使用できます。
コンポジットモードは最も簡単な方法ですが、クリッピングマスクを透明な背景(通常はPNG)の画像として事前に定義する必要があるため、柔軟性が最も低くなります。
画像の塗りつぶし部分を使用して、次に描かれたものをクリップするか、透明な領域を使用して塗りつぶすことができます。
次に、ソリッドパーツを使用して、次の描画されたシェイプ/イメージをクリップするアプローチを示します。
/// draw the shape we want to use for clipping
ctx1.drawImage(imgClip, 0, 0);
/// change composite mode to use that shape
ctx1.globalCompositeOperation = 'source-in';
/// draw the image to be clipped
ctx1.drawImage(img, 0, 0);
ここでglobalCompositeOperation
がsource-in
に変更されます。これは、ソース画像(目的地の隣に描画する画像)が内部に描画されることを意味しますinside既存のソリッドデータ。透明な領域には何も描画されません。
クリッピングマスクが次のようになっている場合(ネットからのランダムfair-use):
そして、このようなイメージ:
結果は次のようになります。
クリッピングのパスを定義することもできます。必要に応じてパスを調整したりアニメートしたりできるため、これは非常に柔軟です。
注:ブラウザーでは、現在、Pathを使用したクリッピングは少し "壊れやすい"ため、ブラウザーとしてクリップパスを設定および使用する前後にsave()
およびrestore()
を使用することを検討してください。現時点ではクリップをリセットできません(restore
はデフォルトのクリップを復元します=キャンバス全体)。
単純なジグザグパスを定義してみましょう(これがあなたの場合の波になります)。
/// use save when using clip Path
ctx2.save();
ctx2.beginPath();
ctx2.moveTo(0, 20);
ctx2.lineTo(50,0);
/// ... more here - see demo
ctx2.lineTo(400, 20);
ctx2.lineTo(400, 100);
ctx2.lineTo(0, 100);
ctx2.closePath();
/// define this Path as clipping mask
ctx2.clip();
/// draw the image
ctx2.drawImage(img, 0, 0);
/// reset clip to default
ctx2.restore();
clip
を使用してクリッピングマスクを設定したので、次にキャンバスに描画されたものはすべて、その形状内に収まるようにクリップされます(形状が開始位置で終了できることを確認してください)。