Vue2时间轴组件(TimeLine/分页、自动顺序播放、暂停、换肤功能、时间选择,鼠标快速滑动)

news2024/11/17 2:44:15

目录

1介绍背景

2实现原理

3组件介绍

4代码

5其他说明


1介绍背景

项目背景是  一天的时间轴  10分钟为一间隔 一天被划分成144个节点  一页面12个节点 代码介绍的很详细 可参考或者借鉴

2实现原理

对Element-plus滑块组件的二次封装
基于Vue2(2.6.14),对element-plus(2.15.13)中slider滑块组件的二次封装。其中,用到了element-plus中的部分icon图标。

组件主要是对时间节点进行分页、顺序播放、暂停、换肤功能、时间选择,点击事件,上一页下一页,父组件监听到当前时间的改变,从而触发相应的业务逻辑。

3组件介绍

light天亮模式

dark黑夜模式

4代码

<template>
  <div class="TimeLineBox">
    <h3>时间轴 {{ timeYMD }} {{ timeSFM }} </h3>
    <div class="TimeLineBox_content">
      <div class="block custom-block">
        <!-- <span class="demonstration">默认</span> -->
        <el-date-picker v-model="dayDate" type="date" placeholder="选择日期" size="small" @change="handleDatePickerChange"
          style="width: 150px;" :editable="false">
        </el-date-picker>
      </div>
      <TimeLine  :second="1000" :timeYMD="timeYMD" :timeSet="timeSet"
        @handleNowValueChange="handleNowValueChange">
      </TimeLine>
    </div>
    
  </div>
</template>
<script>
//--start-#引入时间轴组件#-->
import TimeLine from "./../components/TimeLine.vue";
//--start-#引入第三方关于时间的文件#-->
import moment from 'moment';
export default {
  components: {
    TimeLine
  },
  data() {
    return {
      //--start-#用于时间轴显示的初始化时间时分秒#-->
      timeSFM: "00:10:00",
      //--start-#时间集合#-->
      timeSet: [],
     
      //--start-#用于时间轴显示的初始化时间年月日#-->
      timeYMD: "",
      // //--start-#拼接时间组合 具体就是年月日时分秒#-->
      // timeCombination: null
      dayDate: '',

    }
  },
  mounted() {
    this.computerTimeSet();
  },
  computed: {},
  methods: {
    handleDatePickerChange() {
      //--start-#获取时间选择器的年月日#-->
      //console.log("@@", this.dayDate);
      if (this.dayDate) {
        //--start-#非空执行#-->
        this.handleTimeSetNode(moment(this.dayDate).format('YYYY-MM-DD'))
      }
    },
    //--start-#计算时间轴中需要的时间节点集合方法#-->
    computerTimeSet() {
      //--start-#获取当天的年月日0时0分0秒#-->
      let startOfDay = moment().startOf('day');
      //--start-#获取当天的前一天年月日0时0分0秒#-->
      let previousDate = startOfDay.subtract(1, 'days');
      this.handleTimeSetNode(previousDate)
    },
    handleTimeSetNode(timeNode) {
      //--start-#获取当天的前一天年月日用于计算时间节点#-->
      let oneTimeNode = new Date(timeNode);
      //--start-#获取当天的前一天年月日  用于时间轴标题显示#-->this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD HH:mm:ss');
      this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');
      //--start-#遍历计算获取当天10分钟一次的时间节点组合#-->
      for (let i = 0; i < 144; i++) {
        //--start-#获取时间 并设置分钟位加10,意思是加10分钟#-->
        oneTimeNode.setMinutes(oneTimeNode.getMinutes() + 10);
        //this.timeSet.push(moment(oneTimeNode).format('YYYY-MM-DD HH:mm:ss'));
        //--start-#获取时间节点并加入到时间节点集合中#-->
        this.timeSet.push(moment(oneTimeNode).format('HH:mm:ss'));
      }
    },
    //--start-#父子函数回调,接收时间值的改变并响应#-->
    handleNowValueChange(val, val2) {
      if (val === "nextDay") {
        let oneTimeNode = new Date(this.timeYMD);
        oneTimeNode.setDate(oneTimeNode.getDate() + 1);
        this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');
        this.timeSFM = val2;
      }
      else if (val === "preDay") {
        let oneTimeNode = new Date(this.timeYMD);
        oneTimeNode.setDate(oneTimeNode.getDate() - 1);
        this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');
        this.timeSFM = val2;
      }
      else if (val === "nextDayAndZero") {
        let oneTimeNode = new Date(this.timeYMD);
        oneTimeNode.setDate(oneTimeNode.getDate() + 1);
        this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');
        this.timeSFM = val2;
      }
      else if (val === "preDayAndZero") {
        let oneTimeNode = new Date(this.timeYMD);
        oneTimeNode.setDate(oneTimeNode.getDate() - 1);
        this.timeYMD = moment(oneTimeNode).format('YYYY-MM-DD');
        this.timeSFM = val2;
      }
      else {
        this.timeYMD = val;
        this.timeSFM = val2;
      }
      console.log(val, val2);
    }
  },
// watch:{
//   light(newVal,oldVal){
//     console.log(newVal,oldVal);
//   }
// }
}
</script>
<style lang="less" scoped>
.TimeLineBox {
  width: 100%;
  height: 100%;
  //background-image: url("./../assets/images/播放.png");
  background-size: 100% 100%;
  background-color: aqua;
  position: relative;

  h3 {
    color: rgb(241, 19, 19);
    position: absolute;
    bottom: 150px;
    left: 50%;
    transform: translate(-50%, 0);
  }

  .TimeLineBox_content {
    position: absolute;
    bottom: 50px;
    left: 50%;
    transform: translate(-50%, 0);
    width: 1000px;
    // width: 80%;
    height: 90px;

    .custom-block {
      position: absolute;
      left: 20px;
      top: 5px;
      z-index: 10;

      //background-color: rgb(233, 11, 11);

      ::v-deep .el-input__inner {
        background-color: rgba(255, 255, 255, 0.0);
        border: none;
      }
    }

  }
}
</style>
<template>
  <div :class="bgcolor == 'light' ? 'TimeLine2-light' : 'TimeLine2-dark'">
    <div class="LeftBox">
      <el-slider v-model="value" :step="1" show-stops :show-tooltip="false" :min="minValue" :max="maxValue"
        :marks="marks" @change="handleTimeLineChange" v-if="timeSet.length" />
    </div>
    <div class="RightBox">
      <el-tooltip class="box-item" effect="light" content="上一页" placement="top">
        <el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" @click.native="handlePrePage"
          class="el-icon-d-arrow-left  icon-size">
        </el-icon>
      </el-tooltip>

      <el-tooltip class="box-item" effect="light" content="播放/暂停" placement="top">
        <el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" v-if="playSwitch"
          class="el-icon-video-pause icon-size" @click.native="handlePlay">
        </el-icon>
        <el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" v-if="!playSwitch"
          class="el-icon-video-play icon-size" @click.native="handlePlay">

        </el-icon>
      </el-tooltip>

      <el-tooltip class="box-item" effect="light" content="下一页" placement="top">
        <el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" @click.native="handleNextPage"
          class="el-icon-d-arrow-right  icon-size">
        </el-icon>
      </el-tooltip>
    </div>
    <div class="skin-control">
      <el-icon :color="bgcolor == 'light' ? '#4a0987' : 'white'" size="30px" @click.native="skinControlSwitch"
        class="el-icon-s-opportunity" :class="bgcolor == 'light' ? 'skin-control-light' : 'skin-control-dark'">
      </el-icon>
    </div>
  </div>


</template>
<script>

export default {
  data() {
    return {
      //--start-#定义时间定时器指引#-->
      timer: null,
      //--start-#时间轴页面容量#-->
      pageSize: 12,
      //--start-#时间轴页面数#-->
      pageCode: 1,
      //--start-#时间轴初始化显示的位置(0-11)#-->
      value: 0,
      //--start-#时间轴最小值#-->
      minValue: 0,
      //--start-#时间轴最大值#-->
      maxValue: 0,
      //--start-#遮罩,element公司提供的技术接口#-->
      marks: {},
      //--start-#播放按键转换#-->
      playSwitch: false,
      //--start-#时间集合12节点为一组#-->
      time12ArrNode: [],
      zeroTimeNode: undefined,
      startZero: true,
      bgcolor: "light"
    }
  },
  props: {

    //--start-#父组件时间轴展示标题#-->
    timeYMD: {
      type: String,
      default: '',
    },
    //--start-#时间节点集合#-->
    timeSet: {
      type: Array,
      default: [],
    },
    //--start-#播放时的时间间隔#-->
    second: {
      type: Number,
      default: 1000,
    },
  },
  mounted() { },
  computed: {},
  methods: {
    //--start-#处理皮肤空间切换#-->
    skinControlSwitch() {
      if (this.bgcolor === "dark")
        this.bgcolor = "light"
      else if (this.bgcolor === "light")
        this.bgcolor = "dark"
    },
    //--start-#处理时间轴点击事件#-->
    handleTimeLineChange(val) {
      if (this.time12ArrNode[val] === "00:00:00") {
        this.zeroTimeNode = "00:00:00";
        this.$emit("handleNowValueChange", "nextDayAndZero", "00:00:00");
      }
      else {
        if (this.zeroTimeNode === "00:00:00") {
          this.zeroTimeNode = undefined;
          this.$emit("handleNowValueChange", "preDayAndZero", this.time12ArrNode[val]);
        }
        else {
          this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[val]);
        }
      }
    },
    //--start-#处理播放是与否#-->
    handlePlay() {
      this.playSwitch = !this.playSwitch;
    },
    computeTime12ArrNode() {
      this.time12ArrNode = Array.from(this.timeSet).slice(
        (this.pageCode - 1) * this.pageSize,
        this.pageCode * this.pageSize
      );
    },
    //--start-#处理上一页#-->
    handlePrePage() {
      //console.log(this.zeroTimeNode);
      this.startZero = false;
      if (this.pageCode === 1) {

        this.pageCode = Math.ceil(this.timeSet.length / this.pageSize)
        this.value = 0;
        this.computeTime12ArrNode();
        this.$emit("handleNowValueChange", "preDay", "22:10:00");

      }
      else if (this.pageCode > 1 && !this.zeroTimeNode) {

        this.pageCode--;
        this.value = 0;
        this.computeTime12ArrNode();
        this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[0]);
        if (this.time12ArrNode[0] == "00:10:00") {
          this.startZero = true;
        }
      }
      else if (this.pageCode === Math.ceil(this.timeSet.length / this.pageSize) && this.zeroTimeNode === "00:00:00") {

        // this.zeroTimeNode = undefined;
        this.pageCode--;
        this.value = 0;
        this.computeTime12ArrNode();
        this.$emit("handleNowValueChange", "preDay", "20:10:00");
      }
      this.zeroTimeNode = undefined;
      // console.log("@@", this.zeroTimeNode);
    },
    //--start-#处理下一页#-->
    handleNextPage() {
      this.startZero = false;
      //console.log(this.zeroTimeNode);
      if (this.pageCode === Math.ceil(this.timeSet.length / this.pageSize) && this.zeroTimeNode === "00:00:00") {
        this.pageCode = 1;
        this.value = 0;
        this.computeTime12ArrNode();
        this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[0]);
        this.startZero = true;
      }
      else if (this.pageCode === Math.ceil(this.timeSet.length / this.pageSize)) {
        this.pageCode = 1;
        this.value = 0;
        this.computeTime12ArrNode();
        this.$emit("handleNowValueChange", "nextDay", "00:10:00");
      }
      else if (this.pageCode < Math.ceil(this.timeSet.length / this.pageSize)) {
        this.pageCode++;
        this.value = 0;
        this.computeTime12ArrNode();
        this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[0]);
      }
      this.zeroTimeNode === undefined;
    },
    handlePalyNextPage() {
      this.pageCode++;
      this.value = 0;
      this.computeTime12ArrNode();
      this.zeroTimeNode = undefined;
    }
  },
  //--start-#监视时间轴#-->
  watch: {
    timeYMD(newVal, oldVal) {
      if (this.playSwitch)
        this.playSwitch = !this.playSwitch;
    },
    timeSet(newVal, oldVal) {
      this.time12ArrNode = Array.from(newVal).slice(
        (this.pageCode - 1) * this.pageSize,
        this.pageCode * this.pageSize
      );
    },
    time12ArrNode(newVal, oldVal) {
      let obj = {};
      this.time12ArrNode.forEach((item, index) => {
        obj[index * 1] = item;
      });
      this.marks = obj;
      this.maxValue = this.time12ArrNode.length - 1;
    },
    //--start-#深度监视#-->
    deep: true,
    playSwitch(newVal, oldVal) {
      if (newVal) {
        this.timer = setInterval(() => {
          if (this.value < this.maxValue) {

            //--start-#判断是不是一天的第一个节点,即00:10:00#-->
            if (this.value === 0 && this.startZero) {
              this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[Math.floor(this.value)]);
              this.startZero = false;
            }
            else {
              this.value++;
              //--start-#判断是不是一天的最后一个节点,即00:00:00#-->
              if (this.time12ArrNode[Math.floor(this.value)] === "00:00:00") {
                this.$emit("handleNowValueChange", "nextDayAndZero", "00:00:00");
                this.zeroTimeNode = "00:00:00";
                this.playSwitch = !this.playSwitch;
              }
              //--start-#正常范围内增长值#-->
              else {
                this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[Math.floor(this.value)]);
              }
            }
          }
          //--start-#判断是不是每页12个时间节点的最后一个执行完毕,调用下一页生成#-->
          else if (this.value === this.maxValue && this.pageCode < Math.ceil(this.timeSet.length / this.pageSize)) {
            this.handlePalyNextPage();
            this.$emit("handleNowValueChange", this.timeYMD, this.time12ArrNode[Math.floor(this.value)]);
          }
          //console.log("@2", this.value, this.maxValue, this.time12ArrNode[Math.floor(this.value)]);
        }, this.second);
      } else {
        if (this.timer) {
          clearInterval(this.timer);
        }
      }
    }

  }
}
</script>

<style lang="less" scoped>
.TimeLine2-light {
  user-select: none;
  width: 100%;
  height: 100%;

  border: 2px solid slateblue;
  border-radius: 10px;

  background-color: rgba(255, 255, 255, 0.5);

  backdrop-filter: blur(10px);

  display: flex;
  justify-content: space-between;
  align-items: center;

  .LeftBox {
    width: 80%;
    height: 100;

    padding: 0px 30px;

    ::v-deep .el-slider__runway {

      background-color: #cccccc88;
    }

    ::v-deep .el-slider__button {
      width: 10px;
      height: 10px;
      background-color: transparent;
      border: none;
    }

    ::v-deep .el-slider__stop {
      width: 1px;
      height: 12px;
      background-color: #4a0987;
      z-index: 999;
      display: block;
    }

    ::v-deep .el-slider__marks-text {
      color: #4a0987;
    }
  }

  .RightBox {
    width: 20%;
    height: 100;

    display: flex;
    justify-content: space-around;
    align-items: center;


  }

}

.skin-control {
  position: absolute;
  top: 5px;
  right: 5px;

}

.skin-control-light {
  color: rgba(248, 17, 17, 0.5);
}

.skin-control-dark {
  color: rgba(12, 35, 241, 0.5);
}

.icon-size {
  font-size: 20px;
}

.TimeLine2-dark {
  user-select: none;
  width: 100%;
  height: 100%;

  border: 2px solid white;
  border-radius: 10px;

  background-color: rgba(41, 5, 75, .5);

  backdrop-filter: blur(10px);

  display: flex;
  justify-content: space-between;
  align-items: center;

  .LeftBox {
    width: 80%;
    height: 100;

    padding: 0px 30px;

    ::v-deep .el-slider__runway {

      background-color: #fff3;
    }

    ::v-deep .el-slider__button {
      width: 10px;
      height: 10px;
      background-color: transparent;
      border: none;
    }

    ::v-deep .el-slider__stop {
      width: 1px;
      height: 12px;
      background-color: white;
      z-index: 999;
      display: block;
    }

    ::v-deep .el-slider__marks-text {
      color: white;
    }
  }

  .RightBox {
    width: 20%;
    height: 100;

    display: flex;
    justify-content: space-around;
    align-items: center;
  }
}
</style>

5其他说明

原文参考了

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

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

相关文章

数字孪生引领智慧医院革新:未来医疗的智能化之路

数字孪生&#xff08;Digital Twin&#xff09; 是指将物理实体或系统的数字化模型与其实时运行数据相结合&#xff0c;以反映实体的状态、行为和性能&#xff0c;并通过数据分析和仿真来优化决策和管理。在智慧医院建设中&#xff0c;数字孪生技术扮演着关键角色。 1. 数字孪生…

基于SpringBoot+Vue的瑜伽体验课预约管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于JavaSpringBootVueMySQL的…

国内按月/季/年使用GPT4.0及OpenAI最新的模型

其实gpt官方版本不仅对于网络要求很高&#xff0c;且订阅用户对高级模型的使用也是有次数限制的&#xff0c; 国内想要稳定且最快同步官网的最新模型&#xff0c;我推荐一个地址,可以方便的不限次数的使用GPT4.0等模型&#xff0c; 今天早上刚出的OpenAI全新的草莓模型&#xf…

uniapp 发布苹果IOS详细流程,包括苹果开发者公司账号申请、IOS证书、.p12证书文件等

记录一下uniapp发布苹果IOS的流程。 一、苹果开发者公司账号申请 1、邓白氏编码申请&#xff08;先申请公司邓白氏编码&#xff0c;这一步需要1-2周&#xff0c;没有这个编码苹果开发者没法申请&#xff0c;已有编码的跳过此步骤&#xff09;&#xff1a; 1&#xff09;联系苹…

【C++ Primer Plus习题】16.1

大家好,这里是国中之林! ❥前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。有兴趣的可以点点进去看看← 问题: 解答: main.cpp #include <iostream> #include <string> usin…

Linux通配符*、man 、cp、mv、echo、cat、more、less、head、tail、等指令、管道 | 、指令的本质 等的介绍

文章目录 前言一、Linux通配符*二、man 指令三、 cp 指令四、mv指令五、 echo 指令六、cat 指令七、more 指令八、 less 指令九、 head 指令十、 tail指令十一、 管道 |十二、指令的本质总结 前言 Linux通配符*、man 、cp、mv、echo、cat、more、less、head、tail、等指令、管…

[Unity Demo]重启项目之从零开始制作空洞骑士Hollow Knight第一集:导入素材以及建立并远程连接git仓库

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、导入素材二、使用步骤 1.建立并远程连接git2.github和仓库连接总结 前言 好久没来CSDN看看&#xff0c;突然看到前两年自己写的文章从零开始制作空洞骑士只…

【计算机网络 - 基础问题】每日 3 题(一)

✍个人博客&#xff1a;Pandaconda-CSDN博客 &#x1f4e3;专栏地址&#xff1a;http://t.csdnimg.cn/fYaBd &#x1f4da;专栏简介&#xff1a;在这个专栏中&#xff0c;我将会分享 C 面试中常见的面试题给大家~ ❤️如果有收获的话&#xff0c;欢迎点赞&#x1f44d;收藏&…

基于云计算的虚拟电厂负荷预测

基于云计算的虚拟电厂负荷预测 随着电网规模的扩大及新能源的不断应用&#xff0c;并网电网的安全性和经济性备受关注。 电网调度不再是单一或局部控制&#xff0c;而是采用智能网络集成方式调度 。 智能电网应具有以下特点&#xff1a;坚强自愈&#xff0c;可以抵御外来干扰甚…

使用 Milvus、vLLM 和 Llama 3.1 搭建 RAG 应用

vLLM 是一个简单易用的 LLM 推理服务库。加州大学伯克利分校于 2024 年 7 月将 vLLM 作为孵化项目正式捐赠给 LF AI & Data Foundation 基金会。欢迎 vLLM 加入 LF AI & Data 大家庭&#xff01;&#x1f389; 在主流的 AI 应用架构中&#xff0c;大语言模型&#xff0…

【devops】devops-git之介绍以及日常使用

本站以分享各种运维经验和运维所需要的技能为主 《python零基础入门》&#xff1a;python零基础入门学习 《python运维脚本》&#xff1a; python运维脚本实践 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8…

【GBase 8c V5_3.0.0 分布式数据库常用几个SQL】

1.检查应用连接数 以管理员用户 gbase&#xff0c;登录数据库主节点。 接数据库&#xff0c;并执行如下 SQL 语句查看连接数。 SELECT count(*) FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS s;2.查看空闲连接 查看空闲(state 字段为”idle”)且长时间没有更…

【linux-Day3】linux下的基本指令

【linux-Day3】linux下的基本指令 linux下的基本指令&#x1f4e2;man&#xff1a;访问linux手册页&#x1f4e2;echo&#xff1a;把字符串写入指定文件中&#x1f4e2;cat&#xff1a;查看目标文件的内容&#x1f4e2;cp&#xff1a;复制文件或目录&#x1f4e2;mv&#xff1a…

【【通信协议ARP的verilog实现】】

【【通信协议ARP的verilog实现】】 eth_arp_test.v module eth_arp_test(input sys_clk , //系统时钟input sys_rst_n , //系统复位信号&#xff0c;低电平有效input touch_key , //触摸按键,用于触发开发…

【JVM】判断对象能否回收的两种方法:引用计数算法,可达性分析算法

1、引用计数算法&#xff1a; 给对象添加一个引用计数器&#xff0c;当该对象被其它对象引用时计数加一&#xff0c;引用失效时计数减一&#xff0c;计数为0时&#xff0c;可以回收。 特点&#xff1a;占用了一些额外的内存空间来进行计数&#xff0c;原理简单&#xff0c;判…

wincc利用拓展屏实现多台显示器显示单个项目配置方法详解

以下视频为完整操作教程 wincc利用拓展屏实现多台显示器显示单个项目配置方法详解 一、硬件接线 首先要保证wincc项目主机电脑要具备两个显示器接口&#xff0c;不管是VGA还是HDMI的都可以&#xff0c;让后将两台显示器接到同一台电脑上。如下图&#xff1a; 二、windows设置 …

基于python+django+vue的社区爱心养老管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、SSM项目源码 系统展示 【2025最新】基于pythondjangovueMySQL的社…

设计模式重新整理

系统整理 河北王校长的 贯穿设计模式 和 王争的设计模式之美&#xff0c;希望能形成肌肉记忆 文章目录 为什么需要掌握设计模式1. 六大原则介绍1. 单一职责原则2. 开闭原则3. 里式替换原则4. 依赖倒置原则5. 接口隔离原则6. 迪米特法则 分类 单例模式适配器模式封装有缺陷的接口…

FFmpeg与OpenCV联合开发

本文讲述如何利用FFmpeg SDK与OpenCV 从RTSP流中获取图像&#xff08;OpenCV MAT 对象格式&#xff09;。 一&#xff0c;构造RTSP视频流 因为是在本机实验&#xff0c;所以我自己构造了一个RTSP流。如果你有现成的RTSP流也可以的。 实验用的源视频是黑神话悟空的《云宫讯音》…

苹果CMS vs. 海洋CMS:哪个系统更易于百度收录?

在选择网站内容管理系统&#xff08;影视网站选择那个CMS&#xff1f;&#xff09;时&#xff0c;收录效率和优化能力是关键考量因素。苹果CMS和海洋CMS都是受欢迎的选项&#xff0c;但在百度收录效果上&#xff0c;苹果CMS表现得更为出色。以下将详细探讨苹果CMS为何在百度收录…