0

I'm working on implementation simple image viewer component. I need only to be able to rotate and zoom image. However, I met an issue, that after this transformation even appeared scrollbar does not fully allow to see the whole image. Similar problem are discussed here: CSS Transform scale scrolling issue

However, applying transform-origin property are working only in case with zoom only. However, I still want to be able to do both: zoom and rotate image, and see the whole image.

I know, that transform operations are applied to coordinate system, not to image itself. However, I don't know what to do with transform-origin in such case, plus it seem to me like it's not a proper way to do such obvious and simple thing. It feels like there should be simple soultion.

<html>
<head>
    <meta charset="utf-8">
    <!-- CSS -->
    <style type="text/css">
        .container {
          width: 350px;
          height: 250px;
          overflow: scroll;
        }

        .image {
            width: 100%;
            height: 100%;
            background-image: url(https://loremflickr.com/cache/resized/65535_52383984787_bfe7aba4a6_320_240_nofilter.jpg);
            background-position: center center;
            background-repeat: no-repeat;
            background-size: contain;
        }
    </style>
</head>
<body>
    <!-- HTML -->
    <div class="container">
      <div class="image" id="img"></div>
    </div>
    <button id="rl">Rotate left</button>
    <button id="rr">Rotate right</butto>
    <button id="zp">Zoom +</button>
    <button id="zm">Zoom -</button>
    <button id="reset">Reset</button>
    <div id="output"></div>

    <!-- JavaScript -->

    <script type="text/javascript">
        const imgEl = document.querySelector("#img");
        const output = document.querySelector("#output")

        var zoom = 1;
        var rotate = 0;

        const mkTransformations = () =>
          `transform: scale(${zoom}) rotate(${rotate}deg);`;

        const applyTransformations = () => {
          const props = 
          imgEl.setAttribute("style", mkTransformations());
          output.innerHTML = mkTransformations()
        };

        document.querySelector("#rl").addEventListener("click", function (el) {
          rotate -= 90;
          applyTransformations();
        });

        document.querySelector("#rr").addEventListener("click", function (el) {
          rotate += 90;
          applyTransformations();
        });

        document.querySelector("#zp").addEventListener("click", function (el) {
          zoom += 0.2;
          applyTransformations();
        });

        document.querySelector("#zm").addEventListener("click", function (el) {
          zoom -= 0.2;
          applyTransformations();
        });
        document.querySelector("#zm").addEventListener("click", function (el) {
          zoom -= 0.2;
          applyTransformations();
        });
        document.querySelector("#reset").addEventListener("click", function (el) {
          zoom = 1;
          rotate = 1;
          applyTransformations();
        });     
    </script>
</body>
</html>

Here is the same code on CodePen: https://codepen.io/IvanGerasin-the-vuer/pen/XWPamxG

1 Answers1

1

I found the solution: split this transformations into different elements.

    <div class="container" styles="transform: rotate(90deg); transform-origin: center">
      <div class="image" id="img" styles="transform: scale(1.5); transform-origin: 0 0"></div>
    </div>

Scale transformation should be inner element and rotate transformation - to outer element. Otherwise, your scroll axises will be swapped. Also, don't forget to add "overflow: scroll".