在模板 .phtml 中使用 interact.js 的 magento 动态多维数据集

magento dynamic cubes using interact.js in template .phtml

我使用 interact.js 库编写了这段代码,它在 chrome、firefox 和 w3schools "Try it Yourself" 上独立运行时绝对运行良好(某些情况下不适用于 Edge 和 IE原因)。问题是,当我使用 layout.xml 中的这段代码调用 template.phtml 时,magento 只渲染一次,因此不允许用户调整立方体的大小。

<!-- CSS -->
<style type="text/css">
svg {
  width: 100%;
  height: 300px;
  background-color: #CDC9C9;

  -ms-touch-action: none;
      touch-action: none;
}
.edit-rectangle {
  fill: black;
  stroke: #fff;
}
body { margin: 0; }
</style>

<!-- Content -->
<br>
<svg>
</svg>

<br>
<button onclick="location.href = 'square';" id="previousbutton">Go back</button>
<button onclick="location.href = 'squaresection';" style="float:right" id="nextButton">Proceed to next step</button>
<br>
<br>

<script type="text/javascript" src="interact.js">
</script>

<!-- JavaScript -->

<script type="text/javascript">

var svgCanvas = document.querySelector('svg'),
    svgNS = 'http://www.w3.org/2000/svg',
    rectangles = [];
    labels = [];
    rectNumb = 5;

function Rectangle (x, y, w, h, svgCanvas) {
  this.x = x;
  this.y = y;
  this.w = w;
  this.h = h;
  this.stroke = 0;
  this.el = document.createElementNS(svgNS, 'rect');

  this.el.setAttribute('data-index', rectangles.length);
  this.el.setAttribute('class', 'edit-rectangle');
  rectangles.push(this);

  this.draw();
  svgCanvas.appendChild(this.el);
}


function Label (x, y, text, svgCanvas){
  this.x = x;
  this.y = y;
  this.text = text;
  this.el = document.createElementNS(svgNS, 'text');
  labels.push(this);

  this.draw();
  svgCanvas.appendChild(this.el);
}
Label.prototype.draw = function () {
  this.el.setAttribute('x', this.x);
  this.el.setAttribute('y', this.y);
  this.el.setAttribute('font-family', "Verdana");
  this.el.setAttribute('font-size', 14);
  this.el.setAttribute('fill', "black");
  this.el.innerHTML = this.text;
}

Rectangle.prototype.draw = function () {
  this.el.setAttribute('x', this.x + this.stroke / 2);
  this.el.setAttribute('y', this.y + this.stroke / 2);
  this.el.setAttribute('width' , this.w - this.stroke);
  this.el.setAttribute('height', this.h - this.stroke);
  this.el.setAttribute('stroke-width', this.stroke);
}

interact('.edit-rectangle')
  // change how interact gets the
  // dimensions of '.edit-rectangle' elements
  .rectChecker(function (element) {
    // find the Rectangle object that the element belongs to
    var rectangle = rectangles[element.getAttribute('data-index')];
    // return a suitable object for interact.js
    return {
      left  : rectangle.x,
      top   : rectangle.y,
      right : rectangle.x + rectangle.w,
      bottom: rectangle.y + rectangle.h
    };
  })
/*
.draggable({
    max: Infinity,
    onmove: function (event) {
      var rectangle = rectangles[event.target.getAttribute('data-index')];

      rectangle.x += event.dx;
      rectangle.y += event.dy;
      rectangle.draw();
    }
  })
*/
 .resizable({
    onstart: function (event) {},
    onmove : function (event) {
      if (event.target.getAttribute('data-index') > 0)
      {
        // Main Rect
        var rectangle = rectangles[event.target.getAttribute('data-index')];
        var rectangle2 = rectangles[event.target.getAttribute('data-index') - 1];

        if (rectangle.w - event.dx > 10 && rectangle2.w + event.dx > 10){
          rectangle.x += event.dx;
          rectangle.w = rectangle.w - event.dx;

          rectangle2.w = rectangle2.w + event.dx;
        }

        rectangle.draw();
        rectangle2.draw();

        var label = labels[event.target.getAttribute('data-index')];
        var label2 = labels[event.target.getAttribute('data-index') - 1];
        label.text = rectangle.w + " mm";
        label2.text = rectangle2.w + " mm";

        label.x = rectangle.x + rectangle.w / 4;
        label2.x = rectangle2.x + rectangle2.w / 4;

        label.draw();
        label2.draw();
      }
    },
    onend  : function (event) {},

    edges: {
      top   : false,     // Disable resizing from top edge. 
      left  : true,      
      bottom: false,      
      right : false       // Enable resizing on right edge
    },

    inertia: false,

    // Width and height can be adjusted independently. When `true`, width and
    // height are adjusted at a 1:1 ratio.
    square: false,

    // Width and height can be adjusted independently. When `true`, width and
    // height maintain the aspect ratio they had when resizing started.
    preserveAspectRatio: false,

    // a value of 'none' will limit the resize rect to a minimum of 0x0
    // 'negate' will allow the rect to have negative width/height
    // 'reposition' will keep the width/height positive by swapping
    // the top and bottom edges and/or swapping the left and right edges
    invert: 'reposition',

    // limit multiple resizes.
    // See the explanation in the @Interactable.draggable example
    max: Infinity,
    maxPerElement: 3,
});

interact.maxInteractions(Infinity);

var positionX = 50,
    positionY = 80,
    width = 80,
    height = 80;

for (var i = 0; i < rectNumb; i++) {
  positionX = 50 + 82 * i;
  new Rectangle(positionX, positionY, width, height, svgCanvas);
}
for (var i = 0; i < rectNumb; i++) {
  positionX = 50 + 82 * i;
  new Label(positionX + width/4, positionY + height + 20, width +" mm", svgCanvas); 
}
</script>

任何有关我如何将此代码实施到 magento 中的建议都将不胜感激。

Magento 没有只渲染一次代码。问题是 canvas 事件侦听器总是假定指针坐标是错误的。由于 canvas 是页面的第一个元素(因为它是该 .phtml 文件中的第一个元素),事件侦听器假定它将显示在顶部,但由于 magento 页面的方式,情况并非如此渲染作品。

通过测量 canvas 上方内容的高度并在将其传递给事件侦听器之前从指针位置中减去该高度即可解决此问题。

此解决方案的问题在于它仅适用于单页或内容高度高于 canvas(=> 相同设计)的多个页面。如果有人知道一种不需要 "recalculate" 每个具有不同设计的页面的高度的方法,将不胜感激分享知识。