作るため写真コラージュメーカー私は、オブジェクトベースのクリッピング機能を備えた fabric js を使用しています。この機能は素晴らしいのですが、クリッピング領域内の画像は拡大縮小、移動、回転できません。固定位置のクリッピング領域が必要で、画像はユーザーが望むように固定クリッピング領域内に配置できます。
グーグルで検索したら、非常に近い解決策が見つかりました。
var canvas = new fabric.Canvas('c');
var ctx = canvas.getContext("2d");
ctx.beginPath();
ctx.rect(10,10,150,150);
ctx.rect(180,10,200,200);
ctx.closePath();
ctx.stroke();
ctx.clip();
あるクリッピング領域の画像が別のクリッピング領域に表示されています。どうすればこれを回避できますか。または、fabric js を使用してこれを実現する別の方法はありますか。
ベストアンサー1
これは、プロパティを使用して Fabric で実現できますclipTo
が、関数内で変換 (スケールと回転) を「逆転」させる必要がありますclipTo
。
Fabricでプロパティを使用するとclipTo
、スケーリングと回転が適用されます後クリッピングは画像に合わせて拡大縮小され、回転します。これに対処するには、逆行するプロパティ関数の変換clipTo
。
私の解決策は、Fabric.Rect
クリップ領域の「プレースホルダー」として機能することです (Fabric を使用してオブジェクトを移動し、クリップ領域を移動できるため、これには利点があります)。
私の解決策は、ローダッシュユーティリティライブラリ、特に_.bind()
(コンテキストについてはコードを参照してください)。
フィドルの例
壊す
1. ファブリックを初期化する
まず、もちろんキャンバスが必要です。
var canvas = new fabric.Canvas('c');
2. クリップ領域
var clipRect1 = new fabric.Rect({
originX: 'left',
originY: 'top',
left: 180,
top: 10,
width: 200,
height: 200,
fill: 'none',
stroke: 'black',
strokeWidth: 2,
selectable: false
});
これらのRect
オブジェクトに名前プロパティを指定してclipFor
、clipTo
関数がクリップするオブジェクトを見つけられるようにします。
clipRect1.set({
clipFor: 'pug'
});
canvas.add(clipRect1);
ない持っているクリップ領域の実際のオブジェクトにはなりませんが、Fabric を使用して移動できるため、管理が容易になります。
3. クリッピング機能
コードの重複を避けるために、画像のプロパティで使用される関数をclipTo
個別に定義します。
angle
Image オブジェクトのプロパティは度単位で保存されるため、これを使用してラジアンに変換します。
function degToRad(degrees) {
return degrees * (Math.PI / 180);
}
findByClipName()
は便利な関数であり、ローダッシュ、クリップする Image オブジェクトの プロパティを持つ を検索しますclipFor
(たとえば、下の画像ではname
になります'pug'
)。
function findByClipName(name) {
return _(canvas.getObjects()).where({
clipFor: name
}).first()
}
そして、これが実際に動作する部分です。
var clipByName = function (ctx) {
var clipRect = findByClipName(this.clipName);
var scaleXTo1 = (1 / this.scaleX);
var scaleYTo1 = (1 / this.scaleY);
ctx.save();
ctx.translate(0,0);
ctx.rotate(degToRad(this.angle * -1));
ctx.scale(scaleXTo1, scaleYTo1);
ctx.beginPath();
ctx.rect(
clipRect.left - this.left,
clipRect.top - this.top,
clipRect.width,
clipRect.height
);
ctx.closePath();
ctx.restore();
}
注記:this
上記の関数でのの使用法については、以下を参照してください。
4.fabric.Image
オブジェクトの使用clipByName()
最後に、次のようにイメージをインスタンス化してclipByName
関数を使用するようにすることができます。
var pugImg = new Image();
pugImg.onload = function (img) {
var pug = new fabric.Image(pugImg, {
angle: 45,
width: 500,
height: 500,
left: 230,
top: 170,
scaleX: 0.3,
scaleY: 0.3,
clipName: 'pug',
clipTo: function(ctx) {
return _.bind(clipByName, pug)(ctx)
}
});
canvas.add(pug);
};
pugImg.src = 'https://fabricjs.com/lib/pug.jpg';
何_.bind()
をするのですか?
参照は_.bind()
関数。
私がこれを使用している_.bind()
理由は次の 2 つです。
Image
参照オブジェクトを渡す必要がありますclipByName()
- プロパティ
clipTo
にはオブジェクトではなくキャンバス コンテキストが渡されます。
基本的に、_.bind()
指定したオブジェクトをコンテキストとして使用する関数のバージョンを作成できますthis
。