Image Fabric JS 2.4.1如何使用clipPath裁剪缩放比例小于或大于1:1的图像
我一直在试图找出在目标图像调整大小后计算遮罩矩形的位置和大小时我做错了什么 以下是fabric JS的文档: clipPath:fabric.Object 一种无笔划的FabriObject,它用形状定义剪裁区域。以黑色填充clipPath对象在对象渲染后使用,并且上下文放置在对象画布的中心。如果希望clipPath的0,0与对象中心对齐,请使用clipPath.originX/Y来“居中” 类型: 织物,物体 资料来源: fabric.js,第12991行 当图像没有调整大小(比例为1:1 X&Y)时,我的代码可以完美地工作。在名为rescaleMask的代码函数中,我尝试将遮罩定位到零中心X&Y,当我在一张图纸上手动运行数学时,似乎数学是正确的。很明显,有一个我不知道的部分导致定位以不同的方式关闭,这取决于正在执行裁剪的象限。这里有很多代码,但重要的是掩码是动态创建的,而不是硬编码的。问题一定出在重新缩放掩码函数中,因此希望可以忽略代码的其余部分 我创建了一个带有数字正方形的测试图像图,我将通过单击遮罩按钮来裁剪它,用鼠标左键在其中一个框周围绘制一个矩形,然后单击裁剪按钮。在创建遮罩和裁剪之前调整图像大小时会出现问题 以下是测试图像: 这是一个jsfiddleImage Fabric JS 2.4.1如何使用clipPath裁剪缩放比例小于或大于1:1的图像,image,scale,fabricjs,crop,mask,Image,Scale,Fabricjs,Crop,Mask,我一直在试图找出在目标图像调整大小后计算遮罩矩形的位置和大小时我做错了什么 以下是fabric JS的文档: clipPath:fabric.Object 一种无笔划的FabriObject,它用形状定义剪裁区域。以黑色填充clipPath对象在对象渲染后使用,并且上下文放置在对象画布的中心。如果希望clipPath的0,0与对象中心对齐,请使用clipPath.originX/Y来“居中” 类型: 织物,物体 资料来源: fabric.js,第12991行 当图像没有调整大小(比例为1:1 X
对于掩码,您需要考虑
target.scaleX
和target.scaleY
var lastSelectedPicture=null;
var isInsertingCropRectangle=false;
canvas=new fabric.canvas('c'{
选择:正确,
对,对,
身高:700,
宽度:800
});
变量crop_rect、isDown、origX、origY、mask、target;
var done=false;
var src=”https://stealth-apsvaw.streamhoster.com/fabric_js_2_4_1_crop_test/graph_paper_540.png";
fabric.Image.fromURL(src,function(img){
img.selective=true;
img.id='目标';
img.top=30;
img.left=30;
canvas.add(img);
});
canvas.on('object:added',function(e){
target=null;
掩码=空;
canvas.forEachObject(函数(obj){
//警报(obj.get('id'));
var id=obj.get('id');
如果(id=='target'){
目标=obj;
canvas.setActiveObject(obj);
}
如果(id==‘掩码’){
//警报(完成);
//警报(“面具”);
面罩=obj;
}
});
});
canvas.on('object:modified',function(e){
e、 target.setCoords();
canvas.renderAll();
});
//////////////////////////////////////////////////////////
//面具
//////////////////////////////////////////////////////////
document.getElementById(“掩码”).addEventListener(“单击”,函数)(){
isInsertingCropRectangle=true;
canvas.discardActiveObject();
lastSelectedPicture.selectable=false;
lastSelectedPicture.setCoords();
lastSelectedPicture.dirty=true;
canvas.renderAll();
canvas.discardActiveObject();
isInsertingCropRectangle=true;
});
//////////////////////////////////////////////////////////
//收成
//////////////////////////////////////////////////////////
document.getElementById(“裁剪”).addEventListener(“单击”,函数)(){
如果(目标!==null&&mask!==null){
target.setCoords();
//重缩放掩模
掩码=重新缩放掩码(目标,掩码);
mask.setCoords();
//收成
target.clipPath=掩码;
target.dirty=true;
canvas.setActiveObject(目标);
帆布带(目标);
target.selective=true;
帆布。除去(面具);
canvas.renderAll();
控制台日志(目标);
}
});
//////////////////////////////////////////////////////////
//用于裁剪的重缩放遮罩
//P R O B L M I N T I S F U N T N
//////////////////////////////////////////////////////////
函数重缩放掩码(目标,掩码){
mask.scaleX=1;
mask.scaleY=1;
mask.scaleX/=target.scaleX;
mask.scaleY/=target.scaleY;
var targetCenterX=target.width*target.scaleX/2;
var targetCenterY=target.height*target.scaleY/2;
var maskOverlapX=mask.left-target.left;
var maskOverlapY=mask.top-target.top;
var centerBasedX=maskOverlapX-targetCenterX;
var centerBasedY=maskOverlapY-targetCenterY;
如果(maskOverlapX>=targetCenterX){
centerBasedX=(maskOverlapX-targetCenterX)/target.scaleX;
}
否则{
centerBasedX=((targetCenterX)+maskOverlapX)/target.scaleX;
}
如果(maskOverlapY>=targetCenterY){
centerBasedY=(maskOverlapY-targetCenterY)/target.scaleY;
}
否则{
centerBasedY=((targetCenterY)+maskOverlapY)/target.scaleY;
}
log('targetleft='+target.left);
log('targettop='+target.top);
console.log('targetCenterX='+targetCenterX);
console.log('targetCenterY='+targetCenterY);
log('maskleft='+mask.left);
log('masktop='+mask.top);
log('maskOverlapX='+maskOverlapX);
log('maskOverlapY='+maskOverlapY);
console.log('centerBasedX='+centerBasedX);
log('centerBasedY='+centerBasedY);
mask.left=centerBasedX;
mask.top=centerBasedY;
mask.originX='左';
mask.originY='top';
mask.setCoords();
mask.dirty=true;
canvas.renderAll();
//var newMask=掩码;
返回(掩码);
}
canvas.on('mouse:down',函数(o){
如果(isInsertingCropRectangle==true){
log('mouse down done='+done);
如果(完成){
canvas.renderAll();
返回;
}
isDown=真;
var pointer=canvas.getPointer(o.e);
origX=指针.x;
origY=pointer.y;
crop_rect=新织物.rect({
左:origX,
上图:奥里基,
宽度:pointer.x-origX,
嗨
<canvas id="c" width="500" height="500" style="border:1px solid #ccc"></canvas>
<button id="mask">Mask</button>
<button id="crop">Crop</button>
var lastSelectedPicture = null;
var isInsertingCropRectangle = false;
var canvas = new fabric.Canvas('c', {
selection: true,
preserveObjectStacking: true,
height: 700,
width: 800
});
var crop_rect, isDown, origX, origY, mask, target;
var done = false;
var src = "https://stealth-apsvaw.streamhoster.com/fabric_js_2_4_1_crop_test/graph_paper_540.png";
fabric.Image.fromURL(src, function(img) {
img.selectable = true;
img.id = 'target';
img.top = 30;
img.left = 30;
canvas.add(img);
});
canvas.on('object:added', function(e) {
target = null;
mask = null;
canvas.forEachObject(function(obj) {
//alert(obj.get('id'));
var id = obj.get('id');
if (id === 'target') {
target = obj;
canvas.setActiveObject(obj);
}
if (id === 'mask') {
//alert(done);
//alert('mask');
mask = obj;
}
});
});
canvas.on('object:modified', function(e) {
e.target.setCoords();
canvas.renderAll();
});
//////////////////////////////////////////////////////////
// MASK
//////////////////////////////////////////////////////////
document.getElementById("mask").addEventListener("click", function() {
isInsertingCropRectangle = true;
canvas.discardActiveObject();
lastSelectedPicture.selectable = false;
lastSelectedPicture.setCoords();
lastSelectedPicture.dirty = true;
canvas.renderAll();
canvas.discardActiveObject();
isInsertingCropRectangle = true;
});
//////////////////////////////////////////////////////////
// CROP
//////////////////////////////////////////////////////////
document.getElementById("crop").addEventListener("click", function() {
if (target !== null && mask !== null) {
target.setCoords();
// Re-scale mask
mask = rescaleMask(target, mask);
mask.setCoords();
// Do the crop
target.clipPath = mask;
target.dirty=true;
canvas.setActiveObject(target);
canvas.bringToFront(target);
target.selectable = true;
canvas.remove(mask);
canvas.renderAll();
console.log(target);
}
});
//////////////////////////////////////////////////////////
// RE-SCALE MASK FOR CROPPING
// P R O B L E M I N T H I S F U N C T I O N
//////////////////////////////////////////////////////////
function rescaleMask(target, mask){
mask.scaleX = 1;
mask.scaleY = 1;
var targetCenterX = target.width * target.scaleX / 2;
var targetCenterY = target.height * target.scaleY / 2;
var maskOverlapX = mask.left - target.left;
var maskOverlapY = mask.top - target.top;
var centerBasedX = maskOverlapX - targetCenterX;
var centerBasedY = maskOverlapY - targetCenterY;
if( maskOverlapX >= targetCenterX){
centerBasedX = maskOverlapX - targetCenterX;
}
else{
centerBasedX = -(targetCenterX) + maskOverlapX;
}
if( maskOverlapY >= targetCenterY){
centerBasedY = maskOverlapY - targetCenterY;
}
else{
centerBasedY = -(targetCenterY) + maskOverlapY;
}
console.log('targetleft = '+target.left);
console.log('targettop = '+target.top);
console.log('targetCenterX = '+targetCenterX);
console.log('targetCenterY = '+targetCenterY);
console.log('maskleft = '+mask.left);
console.log('masktop = '+mask.top);
console.log('maskOverlapX = '+maskOverlapX);
console.log('maskOverlapY = '+maskOverlapY);
console.log('centerBasedX = '+centerBasedX);
console.log('centerBasedY = '+centerBasedY);
mask.left = centerBasedX;
mask.top = centerBasedY;
mask.originX = 'left';
mask.originY = 'top';
mask.setCoords();
mask.dirty=true;
canvas.renderAll();
//var newMask = mask;
return(mask);
}
canvas.on('mouse:down', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse down done = '+done);
if (done) {
canvas.renderAll();
return;
}
isDown = true;
var pointer = canvas.getPointer(o.e);
origX = pointer.x;
origY = pointer.y;
crop_rect = new fabric.Rect({
left: origX,
top: origY,
width: pointer.x - origX,
height: pointer.y - origY,
opacity: .3,
transparentCorners: false,
selectable: true,
id: 'mask'
});
canvas.add(crop_rect);
canvas.renderAll();
}
else{
}
});
canvas.on('mouse:move', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse move done = '+done);
if (done) {
canvas.renderAll();
return;
}
if (!isDown) return;
var pointer = canvas.getPointer(o.e);
if (origX > pointer.x) {
crop_rect.set({
left: Math.abs(pointer.x)
});
}
if (origY > pointer.y) {
crop_rect.set({
top: Math.abs(pointer.y)
});
}
crop_rect.set({
width: Math.abs(origX - pointer.x)
});
crop_rect.set({
height: Math.abs(origY - pointer.y)
});
crop_rect.setCoords();
canvas.renderAll();
}
else{
}
});
canvas.on('mouse:up', function(o) {
if( isInsertingCropRectangle == true ){
console.log('mouse up done = '+done);
if (done) {
canvas.renderAll();
return;
}
isDown = false;
crop_rect.set({
selectable: true
});
done = true;
}
else{
}
});
canvas.on('selection:created', function(event) {
console.log("canvas.on('selection:created'");
selectionChanged(event);
});
canvas.on('selection:updated', function(event) {
console.log("canvas.on('selection:updated'");
selectionChanged(event);
});
function selectionChanged(event){
console.log("selectionChanged");
console.log("selectionChanged type = "+event.target.type);
switch(event.target.type) {
case 'textbox':
break;
case 'image':
lastSelectedPicture = event.target;
break;
case 'rect':
break;
case 'group':
break;
default:
break;
}
}