如何在点击时动态地将框居中

问题描述 投票:0回答:1

如何正确计算 viewpoint("0 0 1200 800")

center

我想在我的JS中分配

translate(${translateXValue}px, -300px) rotateY(180deg) scale(1.5)
;*中的值。

我希望点击时该框位于 viewpoint(blue background)

center
中。我的 Y 值是静态的
-300px
因为我不确定如何动态计算 x 和 y

const foreignObjects = [{
    x: 0,
    y: 0,
    width: "100%",
    height: "100%",
    content: '<div xmlns="http://www.w3.org/1999/xhtml"></div>',
    style: {
      backgroundColor: "blue"
    }
  },
  {
    x: 100,
    y: 0,
    width: 1000,
    height: 750,
    content: '<div class="container"></div>',
    style: {}
  }
];

const boxes = [{
    y: -50,
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
];

function applyStyles(element, styles) {
  for (const [key, value] of Object.entries(styles)) {
    element.style[key] = value;
  }
}

function renderBoxes(container) {
  boxes.forEach(box => {
    const div = document.createElement('div');
    div.className = box.class;
    applyStyles(div, box.style);
    let clicked = false;

    div.addEventListener('click', () => {
      if (clicked) {
        // Reset the transformation
        div.style.transform = 'none';
        clicked = false;
      } else {
        // Calculate the translation needed to move the element to the top and center of the viewport
        const translateXValue = (600 / 2);
        // Apply the transformation
        div.style.transform = `translate(${translateXValue}px, -300px) rotateY(180deg) scale(1.5)`;
        clicked = true;
      }
    });

    container.appendChild(div);
  });
}

function renderForeignObjects() {
  const svg = document.getElementById('mySvg');

  foreignObjects.forEach(obj => {
    const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
    foreignObject.setAttribute('x', obj.x);
    foreignObject.setAttribute('y', obj.y);
    foreignObject.setAttribute('width', obj.width);
    foreignObject.setAttribute('height', obj.height);

    const div = document.createElement('div');
    div.innerHTML = obj.content;
    applyStyles(div.firstChild, obj.style);

    if (div.firstChild && div.firstChild.classList.contains('container')) {
      renderBoxes(div.firstChild);
    }

    foreignObject.appendChild(div);
    svg.appendChild(foreignObject);
  });
}

// Call the function to render foreign objects
renderForeignObjects();
.a {
  height: 100vh;
  width: 100%;
}

div {
  width: 100%;
  height: 100%;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

.container {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  position: relative;
}
<svg id="mySvg" xmlns="http://www.w3.org/2000/svg" class="a p" viewBox="0 0 1200 800">
</svg>

javascript
1个回答
1
投票

看起来你只需将 x 值更改为 50% 并将 div css 位置设置为“absolute”即可。清除变换时还会恢复位置类型。

查看并运行代码片段以查看更改。

const foreignObjects = [{
    x: 0,
    y: 0,
    width: "100%",
    height: "100%",
    content: '<div xmlns="http://www.w3.org/1999/xhtml"></div>',
    style: {
      backgroundColor: "blue"
    }
  },
  {
    //Whole page
    x: 100,
    y: 0,
    width: 1000,
    height: 750,
    content: '<div class="container"></div>',
    style: {}
  }
];

const boxes = [{
    y: -50,
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ddd"
    }
  },
  {
    class: "box",
    style: {
      width: "110px",
      height: "110px",
      margin: "0 5px",
      backgroundColor: "#ccc"
    }
  },
];

function applyStyles(element, styles) {
  for (const [key, value] of Object.entries(styles)) {
    element.style[key] = value;
  }
}

function renderBoxes(container) {
  boxes.forEach(box => {
    const div = document.createElement('div');
    div.className = box.class;
    applyStyles(div, box.style);
    let clicked = false;

    div.addEventListener('click', () => {
      if (clicked) {
        // Reset the transformation
        div.style.transform = 'none';
        // NOTE Change css position back to what it was 
        div.style.position="revert";
        clicked = false;
      } else {
        // Calculate the translation needed to move the element to the top and center of the viewport
        const translateXValue = (600 / 2);
        // Apply the transformation
//        div.style.transform = `translate(${translateXValue}px, -300px) rotateY(180deg) scale(1.5)`;
        // NOTE Use 50% for the x 
        div.style.transform = `translate(50%, -300px) rotateY(180deg) scale(1.5)`;
        // NOTE Change css position to "absolute"
        div.style.position="absolute";
        
        clicked = true;
      }
    });

    container.appendChild(div);
  });
}

function renderForeignObjects() {
  const svg = document.getElementById('mySvg');

  foreignObjects.forEach(obj => {
    const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
    foreignObject.setAttribute('x', obj.x);
    foreignObject.setAttribute('y', obj.y);
    foreignObject.setAttribute('width', obj.width);
    foreignObject.setAttribute('height', obj.height);

    const div = document.createElement('div');
    div.innerHTML = obj.content;
    applyStyles(div.firstChild, obj.style);

    if (div.firstChild && div.firstChild.classList.contains('container')) {
      renderBoxes(div.firstChild);
    }

    foreignObject.appendChild(div);
    svg.appendChild(foreignObject);
  });
}

// Call the function to render foreign objects
renderForeignObjects();
.a {
  height: 100vh;
  width: 100%;
}

div {
  width: 100%;
  height: 100%;
  background-size: contain;
  background-position: center;
  background-repeat: no-repeat;
}

.container {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  position: relative;
}
<svg id="mySvg" xmlns="http://www.w3.org/2000/svg" class="a p" viewBox="0 0 1200 800">
</svg>

© www.soinside.com 2019 - 2024. All rights reserved.