Fabric JS-反复裁剪无法保持先前的位置

如何解决Fabric JS-反复裁剪无法保持先前的位置

FabricJS在重复(多次)裁剪图像时遇到了一些问题。我设法通过在图像上绘制一个矩形,然后将其推入fabricjs组来裁剪它。然后我将clipPath反转以显示裁剪后的图像。

enter image description here

我对另一部分重复该过程以多次裁剪。但以某种方式无法保持先前的裁剪位置。因此,先前裁切的图像将从原始位置移动。我尝试使用克隆,但仍然无法保持该位置。

enter image description here

这里是jsFiddle:https://jsfiddle.net/advcha/xy7h8u40/14/或代码:

<!DOCTYPE html>
<html lang='en'>
    <head>
        <meta charset='UTF-8'>
        <title>Fabricjs Crop Background Image</title>
        <script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>
        <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/3.6.6/fabric.min.js"></script>
        <style>
            body {
                background-color:#ccc;
            }
        </style>
        <script type="text/javascript">
            $(document).ready(function() {
                var lastSelectedPicture = null;
                var isInsertingCropRectangle = false;
                canvas = new fabric.Canvas('c',{
                  selection: true,preserveObjectStacking: true,});

                var crop_rect,isDown,origX,origY,mask,target;
                var done = false;

                var scaleX = 1.0;
                var scaleY = 1.0;

                var maskArray = [];
                var counter = 0;

                var src = "https://upload.wikimedia.org/wikipedia/commons/4/44/LampFlowchart.png";
                fabric.Image.fromURL(src,function(img) {
                  img.selectable = true;
                  img.id = 'target';

                  scaleX = canvas.width / img.width;
                  scaleY = canvas.height / img.height;

                  img.set({
                    originX: 'left',originY: 'top',scaleX: scaleX,scaleY: scaleY,});
                  canvas.add(img);
                });

                canvas.on('object:added',function(e) {
                  target = null;
                  mask = null;
                  canvas.forEachObject(function(obj) {
                    //console.log(obj.get('id'));
                    var id = obj.get('id');
                    if (id === 'target') {
                       target = obj;
                        //target.dirty = true;
                       canvas.setActiveObject(obj);
                    }
                    /*if (id === 'mask') {*/
                    if (id.includes('mask')) {
                        mask = obj;
                        counter++;
                    }
                  });
                });

                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;
                    done = false;
                });

                document.getElementById("invert_crop").addEventListener("click",function() {
                  if (target !== null && mask !== null) {
                    target.setCoords();
                    
                    // Re-scale mask
                    mask = rescaleMask(target,mask);
                    mask.setCoords();
                    mask.set({opacity: 1.0});

                    //maskArray.push(mask);
                    var maskCloned;
                    mask.clone(function(cloned) {
                        maskCloned = cloned;
                    });
                    
                    maskArray.push(maskCloned);
                    console.log(maskArray);
                    var g = new fabric.Group(maskArray);

                    g.inverted = true;
                    target.clipPath = g;
                    
                    target.dirty=true;
                    canvas.setActiveObject(target);
                    canvas.bringToFront(target);
                    target.selectable = true;
                    canvas.remove(mask);
                    canvas.renderAll();
                  }
                });

                //////////////////////////////////////////////////////////
                // RE-SCALE MASK FOR CROPPING
                //////////////////////////////////////////////////////////
                function rescaleMask(target,ori_mask){
                  ori_mask.scaleX = 1;
                  ori_mask.scaleY = 1;

                  ori_mask.scaleX/=target.scaleX;
                  ori_mask.scaleY/=target.scaleY;
                 
                  var targetCenterX = target.width * target.scaleX / 2;
                  var targetCenterY = target.height * target.scaleY / 2;

                  var maskOverlapX = ori_mask.left  - target.left;
                  var maskOverlapY = ori_mask.top - target.top;
                  var centerBasedX = maskOverlapX - targetCenterX;
                  var centerBasedY = maskOverlapY - targetCenterY;

                  if( maskOverlapX >= targetCenterX){
                    centerBasedX = (maskOverlapX - targetCenterX)/target.scaleX;
                  }
                  else{
                 
                    centerBasedX = (-(targetCenterX) + maskOverlapX)/target.scaleX;
                  }

                  if( maskOverlapY >= targetCenterY){
                    centerBasedY = (maskOverlapY - targetCenterY)/target.scaleY;
                  }
                  else{
                    centerBasedY = (-(targetCenterY) + maskOverlapY)/target.scaleY;
                  }

                  ori_mask.left = centerBasedX;
                  ori_mask.top = centerBasedY;
                  ori_mask.originX = 'left';
                  ori_mask.originY = 'top';
                    
                  ori_mask.setCoords();
                  ori_mask.dirty=true;
                  canvas.renderAll();
                  
                  //var newMask = mask;
                  return(ori_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_'+counter,});
                        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;
                    }
                }
            });
        </script>
    </head>
    <body>
        <div>
            <canvas style="-moz-user-select: none; cursor: crosshair;" width="500" height="500" id="c"></canvas>
        </div>
        <div>
            <button id="mask">Mask</button>
            <button id="invert_crop">Invert Crop</button>
        </div>
    </body>
</html>

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 &lt;select id=&quot;xxx&quot;&gt; SELECT di.id, di.name, di.work_type, di.updated... &lt;where&gt; &lt;if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 &lt;property name=&quot;dynamic.classpath&quot; value=&quot;tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams[&#39;font.sans-serif&#39;] = [&#39;SimHei&#39;] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -&gt; systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping(&quot;/hires&quot;) public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate&lt;String
使用vite构建项目报错 C:\Users\ychen\work&gt;npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-