CSS 伪类、伪元素的应用实例:电池充电、高能进度条

news2024/12/28 20:54:19

一、目的

    本文通过 CSS 伪类、伪元素,结合动画 animation 和 Vue 动态样式属性(通过 CSS 变量)的写法,来实现电池充电、高能进度条的效果,如下图所示。

二、基础知识

1、CSS 伪类、伪元素

简单概括成以下 4 点:

1、CSS 伪类是对当前元素下,处于某些特定状态时而添加特殊效果的样式(基于文档之外的抽象,所以叫伪类),不同状态可以应用不同的样式。不产生新元素,写法用单冒号(:)开头,比如 :hover、:active、:visited、:first-child 等。

2、CSS 伪元素是对当前元素下,某些特殊部位应用样式,通过创建虚拟元素实现,一般与 content 属性一起使用(基于元素的抽象,所以叫伪元素)。表示文档中不存在实际的元素,写法用双冒号(::)开头,比如 ::before、::after 等。

3、注意的是,单冒号(:)在一些旧版 CSS 中也被用来表示伪元素,这是为了兼容旧的浏览器,但是在最新的 CSS 规范中,建议应该使用双冒号(::)来表示伪元素,与伪类区分开来。

4、灵活应用 CSS 伪类、伪元素可以创建出更丰富的前端页面效果。

更多详细可以参考以下文档链接:

  • 伪元素 - CSS:层叠样式表 | MDN
  • CSS 伪元素 | 菜鸟教程

2、CSS 变量 var()

定义:用于插入自定义属性,如果一个属性在多处被使用,该方法就很有用。

语法:var(custom-property-name, value),参数说明如下表格。

描述
custom-property-name必需。自定义属性的名称,必需以 -- 开头。
value可选。备用值,在属性不存在的时候使用。

详细使用示例:

/* 在 :root 上使用自定义属性,其中 :root 表示文档根元素,该定义将在整个文档内生效 */
:root {
  --main-bg-color: red;
  --second-bg-color: var(--main-bg-color); /* 可以继承自其他已定义的变量,称为派生变量 */
  --main-margin: 20px;
}
#div1 {
  background-color: var(--main-bg-color); /* 等同于 background-color: red; */

  --main-txt-color: blue; /* 也可以在局部定义变量 */
  color: var(--main-txt-color); /* 等同于 color: blue; */
}
#div2 {
  background-color: var(--second-bg-color); /* 等同于 background-color: red; */

  /* 如果一个变量未被定义,可以使用回退值来替代 */
  padding: var(--main-padding, 10px); /* 等同于 padding: 10px; */

  /* 使用自定义属性作为回退值 */
  margin: var(--second-margin, var(--main-margin, 30px)); /* 等同于 margin: 20px; 因为 --main-margin 有被设置,所以它的回退值不生效*/
}

CSS 变量可以被 JavaScript 动态修改,根据上面示例来操作,如下代码:

// 语法:DOM.style.setProperty(custom-property-name, value)
document.getElementById('div1').style.setProperty('--main-txt-color', 'green')

三、具体操作实现

    为了节省代码,达到简单实用的目的,本次实例代码采用 Vue2 框架,ElementUI 组件库,搭配 CSS 预处理器 Scss 完成的。

    Scss 写样式能用更简单且高级的写法降低开发成本,比如嵌套规则,父选择器 & 等,如果需要 HTML + CSS + JS 的形式,读者可以自行转化。

实例 1 —— Battery.vue 组件:

  1. 首先通过 CSS 伪元素描画出电池雏形和电池容量,同时加入闪电图标;
  2. 接着实现充电时波浪效果所需的容器,通过 CSS 伪类中的 hover 来实现鼠标悬停时效果;
  3. 然后通过 CSS 伪元素描画出充电时的波浪,让 CSS 伪类 hover 与 CSS 伪元素相结合,并加上动画实现样式效果;
  4. 最后通过 Vue 动态属性 :style 绑定值传入 CSS 中的变量 var() 使用,实现动态变化。更多具体内容查看下面完整代码。
<template>
  <div style="padding: 50px;">
    <div class="battery" :style="{'--height': `${100 - elecVal || 0}%`}">
      <img :src="iconUrl" alt="闪电icon">
      <div class="cover" :style="{'--top': `${0 - elecVal || 0}%`}"></div>
    </div>

    <div style="margin-top: 20px;">
      当前电量:
      <el-input-number
        v-model="elecVal"
        :min="0"
        :max="100"
        :step="5"
        :precision="2"
        controls-position="right"
        style="width: 120px;"
      ></el-input-number>
      %
    </div>
    
  </div>
</template>

<script>
export default {
  data() {
    return {
      elecVal: 75, // 电池电量
      iconUrl: 'https://showdoc.keytop.cn/Public/Uploads/2024-04-28/662dbe484313f.png' // 图标线上地址
    }
  }
}
</script>

<style lang="scss" scoped>
.battery { // 电池容器
  width: 100px;
  height: 150px;
  background: rgb(246, 246, 246);
  border: 1px solid rgb(211, 211, 211);
  border-radius: 5px; // 大小、背景、边框
  position: relative; // 后面绝对定位的前提
  img { // 让闪电图标在电池里水平垂直居中,并处于高层级
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    z-index: 100;
  }
  &::before { // 伪元素 - 模拟电池正极头
    content: "";
    width: 50px;
    height: 15px;
    position: absolute;
    left: 50%;
    top: -15px;
    transform: translate(-50%, 0); // 大小,水平居中,垂直定位
    background: rgb(246, 246, 246);
    border: 1px solid rgb(211, 211, 211);
    border-bottom: none;
    border-radius: 5px 5px 0 0; // 背景、边框
  }
  &::after { // 伪元素 - 模拟电量容量
    content: "";
    background-color: rgb(68, 220, 148); // 容量颜色
    position: absolute;
    left: 0;
    top: var(--height); // 容量大小,通过值传入动态变化
    right: 0;
    bottom: 0;
  }
  .cover{ // 充电时波浪效果容器
    width: 100%;
    height: 100%;
    position: absolute;
    left: 0;
    top: 0; // 占满整个原电池容器
    overflow: hidden; // 超出部分隐藏
    z-index: 10;
  }
  &:hover{ // 伪类 - 当鼠标 hover 在电池上时,模拟正在充电的波浪效果
    .cover::before, .cover::after{ // 伪元素 - 两层波浪
      content: "";
      background: rgba(246, 246, 246, 0.8);
      border-radius: 40% 30%;
      position: absolute;
      width: 150px;
      height: 150px;
      left: -30%;
      top: var(--top); // 波浪所处位置,通过值传入动态变化
      transform: translate(-50%, 0); // 大小,水平居中,垂直定位
      animation: coverBefore 10s linear infinite; // 通过动画实现波浪
    }
    .cover::after{
      background: rgba(246, 246, 246, 0.6); // 通过背景色深浅来体现出两层效果
      animation: coverAfter 10s linear infinite;
    }
  }
}
// 定义的动画
@keyframes coverBefore {
  0% {
    transform: rotate(0deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
@keyframes coverAfter {
  0% {
    transform: rotate(30deg);
  }
  100% {
    transform: rotate(360deg);
  }
}
</style>

实例 2 —— EnergyProgress.vue 组件:

  1. 首先通过 CSS 描画出进度条容器,设置背景色及背景区域为 content-box;
  2. 接着通过 CSS 伪元素来填充进度条,让其与进度条容器契合,设置相同的 height、padding、background-clip,通过 linear-gradient() 实现填充的渐变颜色;
  3. 然后再通过 CSS 伪元素描画出结尾节点,并对节点的中心点进行定位;
  4. 最后通过 Vue 动态属性 :style 绑定值传入 CSS 中的变量 var() 使用,实现动态变化。更多具体内容查看下面完整代码。
<template>
  <!-- 这里使用该背景色只是为了效果看得更明显而已 -->
  <div style="padding: 50px; background-color: #000; color: #fff;">
    <div class="energy-progress" :style="{'--width': `${progress || 0}%`}"></div>

    <div style="margin-top: 20px;">
      当前进度条:
      <el-input-number
        v-model="progress"
        :min="0"
        :max="100"
        :step="5"
        :precision="2"
        controls-position="right"
        style="width: 120px;"
      ></el-input-number>
      %
    </div>
  </div>
</template>

<script>
  export default {
    data(){
      return{
        progress: 66.6, // 进度条值
      }
    }
  }
</script>

<style lang="scss" scoped>
.energy-progress{ // 进度条容器
  width: 300px;
  height: 15px; // 大小
  background-color: rgb(22, 91, 128);
  padding: 3px 0;
  background-clip: content-box; // 缩小容器本身,为了结尾的节点让出空间
  position: relative; // 后面绝对定位的前提
  &::before{ // 伪元素 - 已填充进度条的部分
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: var(--width); // 填充容量,通过值传入动态变化
    height: 15px;
    padding: 3px 0;
    background-clip: content-box; // 为了与进度条容器契合,同理的
    background-image: linear-gradient(to right, rgb(22, 91, 128) 0%, rgb(97, 177, 242) 70%, #fff 100%); // 进度条填充颜色渐变效果
  }
  &::after{ // 伪元素 - 结尾节点
    content: "";
    position: absolute;
    top: 0;
    left: var(--width); // 根据填充容量定位,通过值传入动态变化
    width: 6px;
    height: 15px; // 大小
    background-color: #fff;
    border-radius: 5px;
    margin-left: -3px; // 这个设为宽度一半的负值,让原本是根据左边框对准位置的,这下让其中心对准位置了
    transform: rotate(30deg);
  }
  &:hover{ // 伪类 - 当鼠标 hover 在电池上时,模拟进度条高能效果
    cursor: pointer;
    &::before{ // 伪元素 - 宽度填充动画(1 秒完成,且先慢后快)
      animation: moveBefore 1s;
    }
    &::after{ // 伪元素 - 结尾节点填充动画(1 秒完成,且先慢后快)
      animation: moveAfter 1s;
    }
  }
}
// 定义的动画
@keyframes moveBefore {
  0% {
    width: 0;
  }
  100% {
    width: var(--width);
  }
}
@keyframes moveAfter {
  0% {
    left: 0;
  }
  100% {
    left: var(--width);
  }
}
</style>

    这是我本人在工作学习中做的一些总结,同时也分享出来给需要的小伙伴哈 ~ 供参考学习,有什么建议也欢迎评论留言,转载请注明出处哈,感谢支持!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1636440.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JavaScript转换和校验数字

本节我们使用的案例还是继续之前的银行家应用程序&#xff0c;只不过我们呢增加了两个账号&#xff0c;代码如下&#xff1a; const account1 {owner: Jonas Schmedtmann,movements: [200, 455.23, -306.5, 25000, -642.21, -133.9, 79.97, 1300],interestRate: 1.2, // %pin…

Macos安装OrbStack

什么是OrbStack OrbStack 是一种在 macOS 上运行容器和 Linux 机器的快速、轻便和简单方法。它是 Docker Desktop 和 WSL 的超强替代品&#xff0c;所有这些都在一个易于使用的应用程序中。 在Macos M系列芯片上&#xff0c;经常遇到docker镜像不兼容的问题&#xff0c;此时使…

Git客户端(TortoiseGit)使用详解

1.概述 使用TortoiseGit比直接使用git 客户端和命令实现代码版本管理更为方便&#xff0c;本文根据实际使用情况作一些记录&#xff0c;特别是对于解决冲突的处理。 2.Git安装与配置 下载 Git - Downloads&#xff0c; 可参考Git安装步骤完成Git的安装与配置。 3.TortoiseG…

【最大公约数 排序】2344. 使数组可以被整除的最少删除次数

本文涉及知识点 最大公约数 排序 LeetCode2344. 使数组可以被整除的最少删除次数 给你两个正整数数组 nums 和 numsDivide 。你可以从 nums 中删除任意数目的元素。 请你返回使 nums 中 最小 元素可以整除 numsDivide 中所有元素的 最少 删除次数。如果无法得到这样的元素&a…

Java设计模式 _结构型模式_组合模式

一、组合模式 1、组合模式 组合模式&#xff08;Composite Pattern&#xff09;是这一种结构型设计模式。又叫部分整体模式。组合模式依据树形结构来组合对象&#xff0c;用来表示部分以及整体层次关系。即&#xff1a;创建了一个包含自己对象组的类&#xff0c;该类提供了修改…

校园二手|基于SprinBoot+vue的微信小程序的校园二手平台(源码+数据库+文档)

校园二手平目录 目录 基于SprinBootvue的微信小程序的校园二手平台 一、前言 二、系统设计 三、系统功能设计 1搜索功能、分类功能测试 2商品购买功能测试 3用户注册功能测试 4商品信息管理功能测试 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设…

【网站项目】木里风景文化管理平台

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

电脑装了两个Win10系统,怎么修改其名称方便识别?

前言 有小伙伴在上一期的双系统教程上留言说怎么修改双系统引导时候显示的名称 不然看起来两个系统好像都没啥分别&#xff0c;如果是Windows10Windows11的方案还好说&#xff0c;但如果是两个Windows10或者是两个Windows11&#xff0c;有时候还真的很不好分辨。 万一想要启动…

【stomp 实战】Spring websocket 用户订阅和会话的管理源码分析

通过Spring websocket 用户校验和业务会话绑定我们学会了如何将业务会话绑定到spring websocket会话上。通过这一节&#xff0c;我们来分析一下会话和订阅的实现 用户会话的数据结构 SessionInfo 用户会话 用户会话定义如下&#xff1a; private static final class Sessio…

第三节课,功能2:开发后端用户的管理接口-- postman--debug测试

一、如何使用postman 网址&#xff1a; https://www.postman.com/downloads/ 【Postman小白教程】五分钟学会如何使用Postman~_哔哩哔哩_bilibili postman安装使用_bowser agent在postman哪里-CSDN博客 二、下载后 登录&#xff0c;开始测试 2.1 关于postman 报错&#…

IOT-9608I-L 的GPIO应用

目录 概述 1 GPIO接口介绍 2 板卡上操作IO 2.1 查看IO驱动 2.2 使用ECHO操作IO 2.2.1 端口选择 2.2.2 查看IO 2.2.3 echo操作IO 3 C语言实现一个操作IO的案例 3.1 功能介绍 3.2 代码实现 3.3 详细代码 4 测试 测试视频地址&#xff1a; IOT-9608I-L的一个简单测试&a…

探索APP分发的新趋势 - 内容包括小猪APP分发平

APP分发探索APP分发的新趋势 - 内容包括小猪APP分发平台的重要性 APP分发是移动互联网的核心环节探索APP分发的新趋势 - 内容包括小猪APP分发平台&#xff0c;它链接探索APP分发的新趋势 - 内容包括小猪APP分发平台了开发者和用户探索APP分发的新趋势 - 内容包括小猪APP分发平…

区块链 | 由外部实体导致的 NFT 安全问题

&#x1f98a;原文&#xff1a; Understanding Security Issues in the NFT Ecosystem &#x1f98a;警告&#xff1a; 本文只记录了原文的第 6 节。 1 问题描述 NFT 所指向的数字资产&#xff08;图片、视频等&#xff09;必须是可以访问的&#xff0c;这样 NFT 才具有意义…

牛客网刷题 | BC70 计算单位阶跃函数

目前主要分为三个专栏&#xff0c;后续还会添加&#xff1a; 专栏如下&#xff1a; C语言刷题解析 C语言系列文章 我的成长经历 感谢阅读&#xff01; 初来乍到&#xff0c;如有错误请指出&#xff0c;感谢&#xff01; 描述 KiKi最近学习了信号…

慧言AIVoceChat实现在线客服及社区频道

原文链接&#xff1a;小回博客 慧言AI&VoceChat实现在线客服及社区频道 一、VoceChat 简介 官网&#xff1a;https://voce.chat VoceChat 是一款支持独立部署的个人云社交媒体聊天服务。15MB 的大小可部署在任何的服务器上&#xff0c;部署简单&#xff0c;很少需要维护…

VS2022 .Net6.0 无法打开窗体设计器

拿Vs2022 建了个Demo&#xff0c;运行环境是net6.0-windows&#xff0c;无论双击或是右键都打不开窗体设计器 打开项目目录下的*.csproj.user <?xml version"1.0" encoding"utf-8"?> <Project ToolsVersion"Current" xmlns"htt…

变电站综合自动化系统:Modbus-PLC-645转IEC104网关方案

前言 电力行业作为关系国计民生的重要基础产业&#xff0c;是关系千家万户的公用事业。但是要做好电力行业安全保障工作的前提&#xff0c;是需要对应的技术人员详细了解电力工业使用的系统、设备以及各类协议的安全特性&#xff0c;本文将主要介绍IEC 104协议的定义和钡铼技术…

动手学深度学习——softmax分类

1. 分类问题 回归与分类的区别&#xff1a; 回归可以用于预测多少的问题&#xff0c; 比如"预测房屋被售出价格"&#xff0c;它是个单值输出。softmax可以用来预测分类问题&#xff0c;例如"某个图片中是猫、鸡还是狗&#xff1f;"&#xff0c;这是一个多…

Springboot+Vue项目-基于Java+MySQL的入校申报审批系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

Tomact安装配置及使用(超详细)

文章目录 web相关知识概述web简介(了解)软件架构模式(掌握)BS&#xff1a;browser server 浏览器服务器CS&#xff1a;client server 客户端服务器 B/S和C/S通信模式特点(重要)web资源(理解)资源分类 URL请求路径(理解)作用介绍格式浏览器通过url访问服务器的过程 服务器(掌握)…