klren0312 / daliy_knowledge

知识积累,正确使用方式是watch
22 stars 4 forks source link

模仿lookingglass block动画 #753

Open klren0312 opened 10 months ago

klren0312 commented 10 months ago
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    .block {
      width: 80px;
      height: 106px;
      overflow: hidden;
    }
    .inner {
      width: 100%;
      height: 100%;
      /* transform: perspective(212px) rotateY(17.46deg); */
      transform-style: preserve-3d;
    }
    .img {
      width: calc(100% * 8);
      height: calc(100% * 6);
      background-image: url(https://lkg-blocks.imgix.net/u/353457a8de3e406e/795.png?ixlib=js-3.7.0&fm=webp&auto=format&fit=max&w=1000);
      background-size: 100% 100%;
      transform: translate(calc(-100% / 8 * 6),calc(-100% / 6 * 0));
      opacity: 1;
    }
  </style>
</head>
<body>
  <div class="block">
    <div class="inner">
      <div class="img" id="js-img"></div>
    </div>
  </div>
  <div id="js-log"></div>
  <script>
    const img = document.getElementById('js-img')
    let i = 0
    let j = 0
    const intervalFlag = setInterval(() => {
      document.getElementById('js-log').innerHTML = `i=${i}, j=${j}`
      img.style.transform = `translate(calc(-100% / 8 * ${j}),calc(-100% / 6 * ${i}))`
      if (i === 5 && j === 7) {
        i = 0
        j = 0
      } else if (j === 7) {
        j = 0
        ++i
      } else {
        ++j
      }
    }, 60)
  </script>
</body>
</html>
klren0312 commented 10 months ago
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <style>
    html, body {
      width: 100%;
      height: 100%;
      background: #333;
    }
    .container {
      display: flex;
      justify-content: center;
    }
    .block {
      width: 480px;
      height: 636px;
      overflow: hidden;
      transform-style: preserve-3d;
      transition: transform 300ms ease-out;
      border-radius: 5px;
    }
    .inner {
      width: 100%;
      height: 100%;
      transform-style: preserve-3d;
    }
    .img {
      width: calc(100% * 8);
      height: calc(100% * 6);
      background-image: url(https://lkg-blocks.imgix.net/u/353457a8de3e406e/795.png?ixlib=js-3.7.0&fm=webp&auto=format&fit=max&w=3600);
      background-size: 100% 100%;
      transform: translate(calc(-100% / 8 * 3),calc(-100% / 6 * 3));
      opacity: 1;
    }
    .multi-views {
      width: 300px;
      height: 300px;
      background-image: url(https://lkg-blocks.imgix.net/u/353457a8de3e406e/795.png?ixlib=js-3.7.0&fm=webp&auto=format&fit=max&w=3600);
      background-size: 100% 100%;
    }

    .canvas-block {
      position: relative;
    }
    .the-canvas {
      position: absolute;
      top: 0;
      left: 0;
    }
  </style>
</head>
<body>
  <div id="js-container" class="container">
    <div id="js-block" class="block">
      <div class="inner">
        <div class="img" id="js-img"></div>
      </div>
    </div>
  </div>

  <div class="canvas-block">
    <div class="multi-views"></div>
    <canvas id="js-canvas" class="the-canvas" width="300" height="300"></canvas>
  </div>
  <script>
    const row = 6
    const col = 8
    const totalViews = row * col
    const img = document.getElementById('js-img')
    const block = document.getElementById('js-block')

    const canvas = document.getElementById('js-canvas')
    const ctx = canvas.getContext('2d')
    const singleWidth = canvas.width / col
    const singleHeight = canvas.height / row

    block.addEventListener('mousemove', function(e) {
      const rect = block.getBoundingClientRect()
      let x = e.clientX - rect.left
      console.log(x)
      if (x < 0) {
        x = 0
      } else if (x > block.offsetWidth) {
        x = block.offsetWidth
      }
      console.log(x, block.offsetWidth)
      var blockWidth = block.offsetWidth
      var blockHeight = block.offsetHeight
      const unitWidth = Math.round(blockWidth / totalViews)
      let theIndex = Math.round(x / unitWidth)
      if (theIndex > totalViews - 1) {
        theIndex = totalViews - 1
      }

      const { i, j } = getCoordinates(row, col, theIndex)
      var rotateY = - (x - blockWidth / 2) / blockWidth * 30 // 水平方向旋转角度
      if (Math.abs(rotateY) > 22) {
        return
      }

      // 设置旋转角度和视点图
      const container = document.getElementById('js-container')
      block.style.transform = `perspective(${container.offsetHeight ? container.offsetHeight * 2 : 2400}px) rotateY(${rotateY}deg)`
      img.style.transform = `translate(calc(-100% / 8 * ${j}),calc(-100% / 6 * ${i}))`

      ctx.clearRect(0, 0, 300, 300)
      ctx.beginPath()
      ctx.lineWidth = 2
      ctx.strokeStyle = 'white'
      ctx.rect(j * singleWidth, i * singleHeight, singleWidth, singleHeight) // 坐标:(50, 50),宽高:(300, 300)
      ctx.stroke()
    })
    // 获取当前指定视图的坐标
    function getCoordinates(rows, cols, index) {
      const row = Math.floor(index / cols);
      const col = index % cols;
      return { i: row, j: col };
    }

  </script>
</body>
</html>
klren0312 commented 10 months ago

动画