SVG数据可视化组件基础教程6:翻牌倒计时

我是设计师邱兴,一个学习前端的设计师,今天给大家制作一个用SVG实现的带有翻牌效果的SVG倒计时器,SVG相较于Echart来说制作简单,但是效果可以非常丰富。

一、目标

通过HTML、CSS和JavaScript创建一个带有翻牌效果的SVG倒计时器,实现以下功能:

  1. 显示时、分、秒的数字卡片。
  2. 使用翻牌效果更新数字。
  3. 通过输入框设置倒计时时间。
  4. 开始、停止倒计时控制。

二、所需工具与准备

  1. 工具

    • 一个文本编辑器(如Notepad++、VS Code等)。
    • 浏览器(用于预览效果)。
  2. 基础准备

    • 确保你对HTML、CSS和JavaScript有一定的了解。
    • 确保你对SVG的基本语法有一定了解。

三、代码分析与操作步骤

1. 创建HTML结构

创建一个HTML文件(如Lesson6.html)并设置基本的HTML结构:

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 翻牌倒计时</title>
  <style>
    /* 样式部分 */
  </style>
</head>
<body>
  <div class="clock-container">
    <div class="digit-group">
      <div class="digit" id="hours-tens"></div>
      <div class="digit" id="hours-ones"></div>
    </div>
    <div class="separator">:</div>
    <div class="digit-group">
      <div class="digit" id="minutes-tens"></div>
      <div class="digit" id="minutes-ones"></div>
    </div>
    <div class="separator">:</div>
    <div class="digit-group">
      <div class="digit" id="seconds-tens"></div>
      <div class="digit" id="seconds-ones"></div>
    </div>
  </div>
  <div class="controls">
    <input type="number" id="timeInput" min="0" max="999999" value="60" placeholder="输入秒数">
    <button onclick="startTimer()">开始倒计时</button>
    <button onclick="stopTimer()">停止</button>
  </div>

  <script>
    // JavaScript部分
  </script>
</body>
</html>

2. 添加CSS样式

<style>标签中,添加以下CSS样式:

css 复制代码
body {
  background: #1a1a1a;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  margin: 0;
  font-family: Arial, sans-serif;
}
.clock-container {
  display: flex;
  gap: 20px;
  padding: 20px;
  background: #2a2a2a;
  border-radius: 10px;
  box-shadow: 0 0 20px rgba(0,0,0,0.3);
}
.digit-group {
  display: flex;
  gap: 5px;
}
.digit {
  position: relative;
  width: 60px;
  height: 80px;
}
.separator {
  display: flex;
  align-items: center;
  font-size: 40px;
  color: #fff;
  font-weight: bold;
}
.controls {
  margin-top: 30px;
  display: flex;
  gap: 10px;
}
button {
  padding: 10px 20px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  background: #4CAF50;
  color: white;
  cursor: pointer;
  transition: background 0.3s;
}
button:hover {
  background: #45a049;
}
input {
  padding: 10px;
  font-size: 16px;
  border: none;
  border-radius: 5px;
  width: 100px;
}
  • 设置页面背景颜色为深色。
  • 使用flexbox布局将倒计时器和控制按钮居中显示。
  • 设置数字卡片和分隔符的样式。
  • 设置输入框和按钮的样式。

3. 编写JavaScript代码

<script>标签中,添加以下JavaScript代码来实现翻牌倒计时功能:

ini 复制代码
// 创建数字卡片SVG
function createDigitSVG(container, digit) {
  const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
  svg.setAttribute("width", "100%");
  svg.setAttribute("height", "100%");
  svg.setAttribute("viewBox", "0 0 60 80");

  // 卡片背景
  const card = document.createElementNS("http://www.w3.org/2000/svg", "rect");
  card.setAttribute("x", "2");
  card.setAttribute("y", "2");
  card.setAttribute("width", "56");
  card.setAttribute("height", "76");
  card.setAttribute("rx", "5");
  card.setAttribute("fill", "#333");
  card.setAttribute("stroke", "#444");
  card.setAttribute("stroke-width", "2");

  // 数字
  const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
  text.setAttribute("x", "30");
  text.setAttribute("y", "50");
  text.setAttribute("text-anchor", "middle");
  text.setAttribute("font-size", "40");
  text.setAttribute("fill", "#fff");
  text.setAttribute("font-weight", "bold");
  text.textContent = digit;

  svg.appendChild(card);
  svg.appendChild(text);
  container.appendChild(svg);
}

// 初始化所有数字卡片
function initializeDigits() {
  const positions = ['hours-tens', 'hours-ones', 'minutes-tens', 'minutes-ones', 'seconds-tens', 'seconds-ones'];
  positions.forEach(pos => {
    createDigitSVG(document.getElementById(pos), '0');
  });
}

// 更新数字显示
function updateDisplay(time) {
  const hours = Math.floor(time / 3600);
  const minutes = Math.floor((time % 3600) / 60);
  const seconds = time % 60;

  const digits = [
    Math.floor(hours / 10),
    hours % 10,
    Math.floor(minutes / 10),
    minutes % 10,
    Math.floor(seconds / 10),
    seconds % 10
  ];

  const positions = ['hours-tens', 'hours-ones', 'minutes-tens', 'minutes-ones', 'seconds-tens', 'seconds-ones'];
  positions.forEach((pos, index) => {
    const container = document.getElementById(pos);
    container.innerHTML = '';
    createDigitSVG(container, digits[index]);
  });
}

let timerInterval;
let remainingTime = 0;

function startTimer() {
  const inputTime = parseInt(document.getElementById('timeInput').value);
  if (isNaN(inputTime) || inputTime < 0) {
    alert('请输入有效的秒数!');
    return;
  }

  remainingTime = inputTime;
  updateDisplay(remainingTime);

  if (timerInterval) {
    clearInterval(timerInterval);
  }

  timerInterval = setInterval(() => {
    remainingTime--;
    if (remainingTime < 0) {
      clearInterval(timerInterval);
      alert('倒计时结束!');
      return;
    }
    updateDisplay(remainingTime);
  }, 1000);
}

function stopTimer() {
  if (timerInterval) {
    clearInterval(timerInterval);
  }
}

// 初始化显示
initializeDigits();

4. 完整代码

将上述代码整合到一个HTML文件中,完整的代码如下:

xml 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <title>SVG 翻牌倒计时</title>
  <style>
    body {
      background: #1a1a1a;
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      min-height: 100vh;
      margin: 0;
      font-family: Arial, sans-serif;
    }
    .clock-container {
      display: flex;
      gap: 20px;
      padding: 20px;
      background: #2a2a2a;
      border-radius: 10px;
      box-shadow: 0 0 20px rgba(0,0,0,0.3);
    }
    .digit-group {
      display: flex;
      gap: 5px;
    }
    .digit {
      position: relative;
      width: 60px;
      height: 80px;
    }
    .separator {
      display: flex;
      align-items: center;
      font-size: 40px;
      color: #fff;
      font-weight: bold;
    }
    .controls {
      margin-top: 30px;
      display: flex;
      gap: 10px;
    }
    button {
      padding: 10px 20px;
      font-size: 16px;
      border: none;
      border-radius: 5px;
      background: #4CAF50;
      color: white;
      cursor: pointer;
      transition: background 0.3s;
    }
    button:hover {
      background: #45a049;
    }
    input {
      padding: 10px;
      font-size: 16px;
      border: none;
      border-radius: 5px;
      width: 100px;
    }
  </style>
</head>
<body>
  <div class="clock-container">
    <div class="digit-group">
      <div class="digit" id="hours-tens"></div>
      <div class="digit" id="hours-ones"></div>
    </div>
    <div class="separator">:</div>
    <div class="digit-group">
      <div class="digit" id="minutes-tens"></div>
      <div class="digit" id="minutes-ones"></div>
    </div>
    <div class="separator">:</div>
    <div class="digit-group">
      <div class="digit" id="seconds-tens"></div>
      <div class="digit" id="seconds-ones"></div>
    </div>
  </div>
  <div class="controls">
    <input type="number" id="timeInput" min="0" max="999999" value="60" placeholder="输入秒数">
    <button onclick="startTimer()">开始倒计时</button>
    <button onclick="stopTimer()">停止</button>
  </div>

  <script>
    // 创建数字卡片SVG
    function createDigitSVG(container, digit) {
      const svg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
      svg.setAttribute("width", "100%");
      svg.setAttribute("height", "100%");
      svg.setAttribute("viewBox", "0 0 60 80");

      // 卡片背景
      const card = document.createElementNS("http://www.w3.org/2000/svg", "rect");
      card.setAttribute("x", "2");
      card.setAttribute("y", "2");
      card.setAttribute("width", "56");
      card.setAttribute("height", "76");
      card.setAttribute("rx", "5");
      card.setAttribute("fill", "#333");
      card.setAttribute("stroke", "#444");
      card.setAttribute("stroke-width", "2");

      // 数字
      const text = document.createElementNS("http://www.w3.org/2000/svg", "text");
      text.setAttribute("x", "30");
      text.setAttribute("y", "50");
      text.setAttribute("text-anchor", "middle");
      text.setAttribute("font-size", "40");
      text.setAttribute("fill", "#fff");
      text.setAttribute("font-weight", "bold");
      text.textContent = digit;

      svg.appendChild(card);
      svg.appendChild(text);
      container.appendChild(svg);
    }

    // 初始化所有数字卡片
    function initializeDigits() {
      const positions = ['hours-tens', 'hours-ones', 'minutes-tens', 'minutes-ones', 'seconds-tens', 'seconds-ones'];
      positions.forEach(pos => {
        createDigitSVG(document.getElementById(pos), '0');
      });
    }

    // 更新数字显示
    function updateDisplay(time) {
      const hours = Math.floor(time / 3600);
      const minutes = Math.floor((time % 3600) / 60);
      const seconds = time % 60;

      const digits = [
        Math.floor(hours / 10),
        hours % 10,
        Math.floor(minutes / 10),
        minutes % 10,
        Math.floor(seconds / 10),
        seconds % 10
      ];

      const positions = ['hours-tens', 'hours-ones', 'minutes-tens', 'minutes-ones', 'seconds-tens', 'seconds-ones'];
      positions.forEach((pos, index) => {
        const container = document.getElementById(pos);
        container.innerHTML = '';
        createDigitSVG(container, digits[index]);
      });
    }

    let timerInterval;
    let remainingTime = 0;

    function startTimer() {
      const inputTime = parseInt(document.getElementById('timeInput').value);
      if (isNaN(inputTime) || inputTime < 0) {
        alert('请输入有效的秒数!');
        return;
      }

      remainingTime = inputTime;
      updateDisplay(remainingTime);

      if (timerInterval) {
        clearInterval(timerInterval);
      }

      timerInterval = setInterval(() => {
        remainingTime--;
        if (remainingTime < 0) {
          clearInterval(timerInterval);
          alert('倒计时结束!');
          return;
        }
        updateDisplay(remainingTime);
      }, 1000);
    }

    function stopTimer() {
      if (timerInterval) {
        clearInterval(timerInterval);
      }
    }

    // 初始化显示
    initializeDigits();
  </script>
</body>
</html>

四、总结

通过以上步骤,你可以创建一个带有翻牌效果的SVG倒计时器。这个倒计时器具有时、分、秒的数字卡片显示,支持通过输入框设置倒计时时间,并提供开始和停止控制功能。你可以通过调整代码中的参数来改变倒计时器的外观和行为。希望这个教程对你有所帮助!

以上制作的是一个最简单的一个带刻度的仪表盘,我还录制了一个更加美观的带刻度的仪表盘的视频教程,有兴趣的小伙伴可以点击查看。

相关推荐
要加油哦~4 分钟前
vue | async-validator 表单验证库 第三方库安装与使用
前端·javascript·vue.js
阿酷tony17 分钟前
视频点播web端AI智能大纲(自动生成视频内容大纲)的代码与演示
前端·人工智能·视频ai·视频智能大纲·ai智能大纲
小李小李不讲道理27 分钟前
「Ant Design 组件库探索」三:Select组件
前端·javascript·react.js
二闹27 分钟前
TypeScript核心玩法,顺便附赠面试通关秘籍!
前端·typescript
诗和远方149395623273430 分钟前
KSCrash中僵尸对象监控原理与实现
前端
XXXFIRE30 分钟前
前端必学:💻Mac + Nginx 部署 Vue3 静态项目
运维·前端
aiweker31 分钟前
python web开发-Flask 重定向与URL生成完全指南
前端·python·flask
Onion32 分钟前
CodeWave集成wujie微前端路由跳转思路
前端
伍哥的传说39 分钟前
daisyUI 扩展之 pin input 组件开发,极致pin码输入框
前端·javascript·react.js·交互
云小遥1 小时前
Cornerstone3D 2.x升级调研
前端·数据可视化