【问题标题】:Multiple canvas created from fields_for loop not working从 fields_for 循环创建的多个画布不起作用
【发布时间】:2019-12-13 07:02:07
【问题描述】:

我有一个带有 fields_for 的表单,我需要为每个 ff.object.print_location.id 提供一个画布

这是带有帆布的整个表格:

<%= f.fields_for :shop_product_print_files do |ff| %>

  <%= ff.object.print_location.title %>
...
...
...
        <script src="https://cdnjs.cloudflare.com/ajax/libs/fabric.js/2.0.0-beta.7/fabric.min.js"></script>
        <label title="Add a background" class="myFile2%>"><span class="mdi mdi-image"> Add Background</span>
           <input type="file" id="file2-<%= "#{ff.object.print_location.id}" %>" />
        </label>
        <label title="Add an image" class="myFile"><span class="mdi mdi-image"> Add Photo</span>
           <input type="file" id="file-<%= "#{ff.object.print_location.id}" %>" />
        </label>
        <a id="lnkDownload-<%= "#{ff.object.print_location.id}" %>" title="Save"><span class="mdi mdi-download"> Save</span></a>
        <canvas id="fCanvas-<%= "#{ff.object.print_location.id}" %>" width="400" height="400"></canvas>

        <script>

          var canvas = new fabric.Canvas('fCanvas-<%= "#{ff.object.print_location.id}" %>');

          var myImage = document.createElement('canvas');

          document.getElementById('file-<%= "#{ff.object.print_location.id}" %>').addEventListener("change", function(e) {
             var file = e.target.files[0];
             var reader = new FileReader();
             reader.onload = function(f) {
                var data = f.target.result;
                fabric.Image.fromURL(data, function(img) {
                   var oImg = img.set({
                      left: 0,
                      top: 0,
                      angle: 0,
                      border: '#000',
                   }).scale(0.2);
                   canvas.add(oImg).renderAll();
                   //var a = canvas.setActiveObject(oImg);
                   var dataURL = canvas.toDataURL({
                      format: 'png',
                      quality: 1
                   });
                });
             };
             reader.readAsDataURL(file);
          });

          document.getElementById('file2-<%= "#{ff.object.print_location.id}" %>').addEventListener("change", function(e) {
             var file = e.target.files[0];
             var reader = new FileReader();
             reader.onload = function(f) {
                var data = f.target.result;
                fabric.Image.fromURL(data, function(img) {
                   // add background image
                   canvas.setBackgroundImage(img, canvas.renderAll.bind(canvas), {
                      scaleX: canvas.width / img.width,
                      scaleY: canvas.height / img.height
                   });
                });
             };
             reader.readAsDataURL(file);
          });


             // Download
          var imageSaver = document.getElementById('lnkDownload-<%= "#{ff.object.print_location.id}" %>');
          imageSaver.addEventListener('click', saveImage, false);

          function saveImage(e) {
             this.href = canvas.toDataURL({
                format: 'png',
                quality: 0.8
             });
             this.download = 'custom-<%= "#{ff.object.print_location.id}" %>.png'
          }

        </script>

当我这样做 ^ 时,每个 print_location 都会出现画布,但我无法将图像上传到所有人(仅适用于循环中的最后一个画布,并且所有文件上传输入都被放入循环中的最后一个画布中。

例如:如果我为第一个(第二个或第四个等)画布上传文件,它将出现在最后一个画布中)并让它出现。

当我使用时:

const canvas = new fabric.Canvas('fCanvas-<%= "#{ff.object.print_location.id}" %>');

const myImage = document.createElement('canvas');

...画布可以正常工作,但仅适用于第一个 print_location,其他任何一个都没有。

总共有 6 个 print_locations 需要遍历。

在 fields_for 循环中使用 var 时,是什么阻止了文件/图像出现在画布中?

我该怎么做才能让他工作?

这是此工作的代码笔:https://codepen.io/anon/pen/YmEGyW

尝试(删除 file-2 并下载到它只是为了看看我是否可以让画布单独工作然后应用它):

var canvas = new fabric.Canvas('fCanvas');

  document.querySelectorAll('[id$=file-']).forEach((fileInput) => {
    fileInput.addEventListener('change', function(e){
      let id = this.id.replace('file-','');
      let canvas = new fabric.Canvas('fCanvas-'+id);

      // the rest of your "change" code
      var file = e.target.files[0];
      var reader = new FileReader();
      reader.onload = function(f) {
         var data = f.target.result;
         fabric.Image.fromURL(data, function(img) {
            var oImg = img.set({
               left: 0,
               top: 0,
               angle: 0,
               border: '#000',
            }).scale(0.2);
            // canvas.add(oImg).renderAll();
            canvas.add(oImg);

            //var a = canvas.setActiveObject(oImg);
            var dataURL = canvas.toDataURL({
               format: 'png',
               quality: 1
            });
         });
      };
    }
    reader.readAsDataURL(file);
  });

【问题讨论】:

    标签: javascript ruby-on-rails canvas html5-canvas fabricjs


    【解决方案1】:

    您不应在循环的每次迭代中添加脚本。在循环外添加一次,但执行类似...

    // add the 'change' eventListener to all elements with id starting with "file-"
    document.querySelectorAll('[id$=file-']).forEach((fileInput) => {
      fileInput.addEventListener('change', function(e){
        let id = this.id.replace('file-','');
        let canvas = new fabric.Canvas('fCanvas-'+id);
    
        // the rest of your "change" code
    
      })
    })
    
    // do something similar for inputs with id starting with "file2-"
    

    您的循环的问题是您在任何地方都使用相同的名称,使用“var”您将用新的名称替换以前的名称(这就是为什么它仅适用于最后一个元素),使用“const”您正在防止变量来改变它的赋值(这就是为什么它只适用于第一个,你的浏览器控制台肯定有一些错误)。

    【讨论】:

    • 我有点困惑。我是否删除了var canvas = new fabric.Canvas('fCanvas-&lt;%= "#{ff.object.print_location.id}" %&gt;'); 并从脚本中删除了所有&lt;%= "#{ff.object.print_location.id}" %&gt;(我认为这很明显,但要确保)?
    • 添加了我在底部所做的尝试。我对它的工作原理有点迷茫,我确信它确实是我没有正确实现它。每当我想循环 javascript 时,我都会做我第一次尝试时所做的事情,并且通常可以工作
    • 检查浏览器控制台,你肯定有一些错误可以指导你。我只是给你一个大致的想法(将代码移出循环并使用 querySelectorAll 来定位输入),但你的代码太长太复杂,无法提出具体的解决方案。阅读 stackoverflow 指南,您需要提供一个最小示例来重现您的问题。我看过你的问题,你通常只是复制粘贴很多代码,这几乎不可能回答。通常,如果您尝试将代码减少到最少,您可能会自己找到答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 2021-12-17
    相关资源
    最近更新 更多