uni-app 一些实用的页面模板

news2024/12/24 8:46:20

时间倒计时

<!-- 时间倒计时 -->
<template>
  <view class="container">
    <view class="flex-row time-box">
      <view class="time-item">{{ laveTimeList[0] }}</view>
      <text>天</text>
      <view class="time-item">{{ laveTimeList[1] }}</view>
      <text>时</text>
      <view class="time-item">{{ laveTimeList[2] }}</view>
      <text>分</text>
      <view class="time-item">{{ laveTimeList[3] }}</view>
      <text>秒</text>
    </view>
    <view class="flex-row time-box">
      <view class="flex-row">
        <block v-for="(item, i) in laveTimeDateList[0]" :key="i">
          <view class="time-item date-item">{{ item }}</view>
        </block>
        <text>天</text>
      </view>
      <view class="flex-row">
        <block v-for="(item, i) in laveTimeDateList[1]" :key="i">
          <view class="time-item date-item">{{ item }}</view>
        </block>
        <text>时</text>
      </view>
      <view class="flex-row">
        <block v-for="(item, i) in laveTimeDateList[2]" :key="i">
          <view class="time-item date-item">{{ item }}</view>
        </block>
        <text>分</text>
      </view>
      <view class="flex-row">
        <block v-for="(item, i) in laveTimeDateList[3]" :key="i">
          <view class="time-item date-item">{{ item }}</view>
        </block>
        <text>秒</text>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      laveTimeList: [], // 剩余时间(天-时-分-秒)
      laveTimeDateList: [], // 在拆分
      timer: "" // 定时器
    };
  },
  onLoad() {
    this.getLeftTime("2023/10/25 14:52:00");
  },
  onUnload() {
    if (this.timer) clearInterval(this.timer);
  },
  methods: {
    /* 计算剩余时间 */
    getLeftTime(e) {
      let timeLeft = this.getTimestap(e); // 获取时间戳
      this.initDate(timeLeft); // 初始化数据
      this.timer = setInterval(() => {
        this.initDate(timeLeft); // 初始化数据
        if (timeLeft-- === 0) clearInterval(this.timer); // 清除定时
      }, 1000);
    },
    /* 初始化数据 */
    initDate(e) {
      const period = this.formateSeconds(e); // 天-时-分-秒
      this.laveTimeList = period; // 剩余时间(天-时-分-秒)
      this.laveTimeDateList = this.formatDate(JSON.stringify(period)); // 格式化日期
    },
    /* 天-时-分-秒 */
    formateSeconds(e) {
      const time = [],
        day = parseInt(e / 86400),
        hour = parseInt((e % 86400) / 3600),
        min = parseInt(((e % 86400) % 3600) / 60),
        sec = parseInt(((e % 86400) % 3600) % 60);
      time[0] = day > 0 ? this.addZero(day) : this.addZero(0);
      time[1] = hour > 0 ? this.addZero(hour) : this.addZero(0);
      time[2] = min > 0 ? this.addZero(min) : this.addZero(0);
      time[3] = sec > 0 ? this.addZero(sec) : this.addZero(0);
      return time;
    },
    /* 数字前面补零 */
    addZero(num) {
      return num < 10 ? "0" + num : num;
    },
    /* 获取时间戳 */
    getTimestap(e) {
      const curTime = parseInt(new Date().getTime() / 1000); // 当前时间
      const futureTime = parseInt(new Date(e.replace(/-/g, "/")).getTime() / 1000); // 指定时间
      return futureTime <= curTime ? 0 : futureTime - curTime;
    },
    /* 格式化日期 */
    formatDate(e) {
      const list = JSON.parse(e);
      for (let i = 0; i < list.length; i++) {
        list[i] = list[i].toString().split("");
      }
      return list;
    }
  }
};
</script>

<style lang="scss" scoped>
.container {
  .flex-row {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-direction: row;
  }
  .time-box {
    color: #eaa81b;
    font-size: 26rpx;
    margin: 20rpx;
    padding: 40rpx 20rpx;
    background: #fff;
    border-radius: 20rpx;
  }
  .time-item {
    width: 60rpx;
    text-align: center;
    height: 40rpx;
    line-height: 40rpx;
    font-size: 24rpx;
    margin: 0 20rpx;
    background: linear-gradient(90deg, #ffebb1 0%, #ffdb8f 100%);
    border-radius: 4rpx;
  }
  .date-item {
    width: 30rpx;
    margin: 0 10rpx;
  }
}
</style>

canvas 图形验证码

<!-- canvas 图形验证码 -->
<template>
  <view class="container">
    <view class="canvas-box"><canvas type="2d" id="canvasCode" @click="drawPic" /></view>
    <view class="text-tip">验证码:{{ curCode }}</view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      width: 100, // 宽度
      height: 50, // 高度
      fontSize: 25, // 字体大小
      fontFamily: "SimHei", // 字体
      count: 4, // 验证码位数
      curCode: "", // 当前验证码
      jamPointNum: 40, // 干扰点数
      jamLineNum: 10 // 干扰线数
    };
  },
  onLoad() {
    this.drawPic(); // 绘制验证码图片
  },
  methods: {
    /* 绘制验证码图片 */
    drawPic() {
      uni
        .createSelectorQuery()
        .select("#canvasCode")
        .fields({ node: true, size: true })
        .exec(res => {
          const canvasObj = res[0].node;
          const ctx = canvasObj.getContext("2d");
          // 清除画布
          ctx.fillStyle = "rgb(255, 255, 255)";
          ctx.fillRect(0, 0, 91, 36);
          // 绘制背景色
          ctx.fillStyle = this.randomColor(180, 240); // 颜色若太深可能导致看不清
          ctx.fillRect(0, 0, this.width, this.height);
          // 绘制文字
          const str = "ABCEFGHJKLMNPQRSTWXY123456789";
          let codeTemp = "";
          for (let i = 0; i < this.count; i++) {
            const txt = str[this.randomNum(0, str.length)];
            codeTemp += txt;
            ctx.fillStyle = this.randomColor(50, 160); // 随机生成字体颜色
            ctx.font = this.randomNum(this.fontSize, this.fontSize + 6) + "px " + this.fontFamily; // 随机生成字体大小
            const x = 10 + i * 20;
            const y = this.randomNum(25, 30);
            const deg = this.randomNum(-30, 30);
            // 修改坐标原点和旋转角度
            ctx.translate(x, y);
            ctx.rotate((deg * Math.PI) / 180);
            ctx.fillText(txt, 5, 0);
            // 恢复坐标原点和旋转角度
            ctx.rotate((-deg * Math.PI) / 180);
            ctx.translate(-x, -y);
          }
          this.curCode = codeTemp;
          // 绘制干扰线
          for (let i = 0; i < this.jamLineNum; i++) {
            ctx.strokeStyle = this.randomColor(40, 180);
            ctx.beginPath();
            ctx.moveTo(this.randomNum(0, this.width), this.randomNum(0, this.height));
            ctx.lineTo(this.randomNum(0, this.width), this.randomNum(0, this.height));
            ctx.stroke();
          }
          // 绘制干扰点
          for (let i = 0; i < this.jamPointNum; i++) {
            ctx.fillStyle = this.randomColor(0, 255);
            ctx.beginPath();
            ctx.arc(this.randomNum(0, this.width), this.randomNum(0, this.height), 1, 0, 2 * Math.PI);
            ctx.fill();
          }
        });
    },
    randomNum(min, max) {
      // 生成一个随机数
      return Math.floor(Math.random() * (max - min) + min);
    },
    randomColor(min, max) {
      // 生成一个随机色
      const red = this.randomNum(min, max); // 红色
      const green = this.randomNum(min, max); // 绿色
      const blue = this.randomNum(min, max); // 蓝色
      return `rgb(${red}, ${green}, ${blue})`;
    }
  }
};
</script>

<style lang="scss" scoped>
.container {
  .canvas-box {
    width: 200rpx;
    height: 100rpx;
    margin: 200rpx auto;
  }
  .text-tip {
    width: 80%;
    text-align: center;
    color: #333;
    font-size: 28rpx;
    margin: 80rpx auto;
  }
}
</style>

圆角灯笼

<!-- 圆角灯笼 -->
<template>
  <view class="container">
    <!-- 灯笼-内 -->
    <view class="cont-box">
      <view class="lantern-box">
        <view class="line-tip"></view>
        <view class="outer-bg">
          <view class="inner-bg"><view class="text-tip">福</view></view>
        </view>
        <view class="spike-box">
          <view class="spike-tip"></view>
          <view class="dots-tip"></view>
        </view>
      </view>
    </view>
    <!-- 灯笼-外 -->
    <view class="cont-box cont-outer-box">
      <view class="lantern-box">
        <view class="line-tip"></view>
        <view class="outer-bg">
          <view class="inner-bg"><view class="text-tip">幸</view></view>
        </view>
        <view class="spike-box">
          <view class="spike-tip"></view>
          <view class="dots-tip"></view>
        </view>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {};
  },
  onLoad() {},
  methods: {}
};
</script>

<style lang="scss" scoped>
.container {
  .cont-box {
    position: fixed;
    top: -80rpx;
    right: -40rpx;
    z-index: 999;
    .lantern-box {
      position: relative;
      width: 240rpx;
      height: 180rpx;
      background: rgba(216, 0, 15, 0.8);
      margin: 100rpx;
      transform-origin: 50% -200rpx;
      -webkit-transform-origin: 50% -200rpx;
      animation: swing 3s infinite ease-in-out;
      -webkit-animation: swing 3s infinite ease-in-out;
      box-shadow: -10rpx 10rpx 100rpx 8rpx rgba(250, 108, 0, 1);
      border-radius: 50% 50%;
    }
    .lantern-box::before {
      content: " ";
      position: absolute;
      top: -14rpx;
      left: 58rpx;
      display: block;
      width: 120rpx;
      height: 24rpx;
      background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
      border: solid 2rpx #dc8f03;
      border-radius: 10rpx 10rpx 0 0;
      z-index: 999;
    }
    .lantern-box::after {
      content: " ";
      position: absolute;
      bottom: -14rpx;
      left: 20rpx;
      display: block;
      width: 120rpx;
      height: 24rpx;
      margin-left: 40rpx;
      background: linear-gradient(to right, #dc8f03, #ffa500, #dc8f03, #ffa500, #dc8f03);
      border: solid 2rpx #dc8f03;
      border-radius: 0 0 10rpx 10rpx;
    }
    .line-tip {
      position: absolute;
      top: -40rpx;
      left: 120rpx;
      width: 4rpx;
      height: 40rpx;
      background: #dc8f03;
    }
    .outer-bg {
      width: 200rpx;
      height: 180rpx;
      background: rgba(216, 0, 15, 0.1);
      margin: 24rpx 16rpx 16rpx 16rpx;
      border: 4rpx solid #dc8f03;
      border-radius: 50% 50%;
      .inner-bg {
        width: 90rpx;
        height: 180rpx;
        background: rgba(216, 0, 15, 0.1);
        margin: -8rpx 16rpx 16rpx 52rpx;
        border: 4rpx solid #dc8f03;
        border-radius: 50% 50%;
        .text-tip {
          text-align: center;
          line-height: 170rpx;
          color: #dc8f03;
          font-size: 3.1rem;
          font-family: 华文行楷, Arial, Lucida Grande, Tahoma, sans-serif;
          font-weight: bold;
        }
      }
    }
    .spike-box {
      position: relative;
      width: 10rpx;
      height: 40rpx;
      background: #ffa500;
      margin: -10rpx 0 0 118rpx;
      transform-origin: 50% -90rpx;
      -webkit-transform-origin: 50% -90rpx;
      animation: swing 4s infinite ease-in-out;
      -webkit-animation: swing 4s infinite ease-in-out;
      border-radius: 0 0 10rpx 10rpx;
      .dots-tip {
        position: absolute;
        top: 28rpx;
        left: -4rpx;
        width: 20rpx;
        height: 20rpx;
        background: #dc8f03;
        border-radius: 50%;
      }
      .spike-tip {
        position: absolute;
        top: 36rpx;
        left: -4rpx;
        width: 20rpx;
        height: 70rpx;
        background: #ffa500;
        border-radius: 0 0 0 10rpx;
      }
    }
  }
  .cont-outer-box {
    top: -60rpx;
    right: 20rpx;
    .lantern-box {
      animation: swing 5s infinite ease-in-out;
      -webkit-animation: swing 5s infinite ease-in-out;
      box-shadow: -10rpx 10rpx 60rpx 8rpx rgba(252, 144, 61, 1);
    }
  }
  @keyframes swing {
    0% {
      -webkit-transform: rotate(-10deg);
    }
    50% {
      -webkit-transform: rotate(10deg);
    }
    100% {
      -webkit-transform: rotate(-10deg);
    }
  }
  @-webkit-keyframes swing {
    0% {
      -webkit-transform: rotate(-10deg);
    }
    50% {
      -webkit-transform: rotate(10deg);
    }
    100% {
      -webkit-transform: rotate(-10deg);
    }
  }
}
</style>

<style>
page {
  background-color: #222;
}
</style>

自定义顶部导航栏

<!-- 自定义顶部导航栏 -->
<template>
  <view class="container" :style="'padding-top: ' + navHeight + 'rpx'">
    <view class="head-back">
      <image src="/static/return.png" mode="aspectFill" @click="toBack" />
      <image src="/static/home.png" mode="aspectFill" @click="toHome" />
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      statusBarHeight: 0, // 状态导航栏高度
      navigationBarHeight: 0, // 导航栏高度(标题栏高度)
      navHeight: 0 // 总体高度
    };
  },
  onLoad() {
    /** 状态栏高度 */
    this.statusBarHeight = wx.getSystemInfoSync().statusBarHeight;
    /** 获取微信胶囊的位置信息 width,height,top,right,left,bottom */
    const custom = wx.getMenuButtonBoundingClientRect();
    /** 导航栏高度(标题栏高度) = 胶囊高度 + (顶部距离 - 状态栏高度) * 2 */
    this.navigationBarHeight = custom.height + (custom.top - this.statusBarHeight) * 2;
    /** 总体高度 = 状态栏高度 + 导航栏高度 */
    this.navHeight = this.navigationBarHeight + this.statusBarHeight;
  },
  methods: {
    /* 返回 */
    toBack() {
      console.log("返回");
    },
    /* 回到首页 */
    toHome() {
      console.log("回到首页");
    }
  }
};
</script>

<style lang="scss" scoped>
.container {
  padding-bottom: 25rpx;
  background-color: rgba(0, 0, 0, 0.7);
  .head-back {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 180rpx;
    height: 60rpx;
    padding: 0 20rpx;
    margin-left: 25rpx;
    border: 1rpx solid rgba(204, 204, 204, 0.6);
    box-sizing: border-box;
    border-radius: 50rpx;
    image {
      width: 40rpx;
      height: 40rpx;
    }
  }
  .head-back::after {
    content: "";
    position: absolute;
    top: 10%;
    left: calc(50% - 1rpx);
    width: 2rpx;
    height: 80%;
    background: #fff;
  }
}
</style>

滚动自动吸顶

<!-- 滚动自动吸顶 -->
<template>
  <view class="container">
    <view class="head-box">头部内容区域</view>
    <view class="nav-box" :class="isFixed ? 'fix-tip' : ''" id="navBox">
      <view class="nav-item" :class="{ 'active-tip': curNav === i }" v-for="(item, i) in navList" :key="i" @click="navToggle(i)">
        {{ item }}
      </view>
    </view>
    <view :class="isFixed ? 'p-t-nav' : ''" id="contBox">
      <view class="cont-item" v-for="(item, i) in curNav * 10 + 5" :key="i">{{ item }}</view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      isFixed: false, // 是否吸顶
      navTop: 0, // 导航栏到顶部的距离
      curNav: 0, // 当前导航栏
      navList: ["未开始", "进行中", "已结束"]
    };
  },
  onReady() {
    // 获取节点距离顶部的距离
    uni
      .createSelectorQuery()
      .select("#navBox")
      .boundingClientRect(rect => {
        if (rect && rect.top) this.navTop = parseInt(rect.top);
      })
      .exec();
  },
  /* 监听页面滚动事件 */
  onPageScroll(e) {
    this.isFixed = parseInt(e.scrollTop) >= this.navTop;
  },
  methods: {
    /* 导航栏切换 */
    navToggle(i) {
      if (this.curNav == i) return;
      this.curNav = i;
      if (this.isFixed) uni.pageScrollTo({ selector: "#contBox", duration: 0.5 }); // duration.滚动到指定位置需要的时间
    }
  }
};
</script>

<style lang="scss" scoped>
.container {
  $navHeight: 88rpx; // nav导航栏高度
  .head-box {
    width: 100%;
    height: 300rpx;
    color: #fff;
    font-size: 26rpx;
    padding: 30rpx;
    background: linear-gradient(90deg, #f54ea2, #ff7676);
    box-sizing: border-box;
  }
  .nav-box {
    position: relative;
    display: flex;
    width: 100%;
    height: $navHeight;
    line-height: $navHeight;
    background: #fff;
    box-shadow: 0 5rpx 5rpx #ccc;
    .nav-item {
      position: relative;
      flex: 1;
      text-align: center;
      color: #333;
      font-size: 28rpx;
    }
    .nav-item::after {
      content: "";
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      bottom: 4rpx;
      width: 0;
      height: 6rpx;
      background: linear-gradient(90deg, #f54ea2, #ff7676);
      transition: 0.3s width linear;
      border-radius: 3rpx;
    }
    .active-tip {
      color: transparent;
      font-size: 30rpx;
      background-clip: text;
      -webkit-background-clip: text;
      background-image: linear-gradient(90deg, #f54ea2, #ff7676);
      transition: 0.3s all linear;
      transition-delay: 0.1s;
      font-weight: 900;
    }
    .active-tip::after {
      width: 40%;
    }
  }
  .fix-tip {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 99;
  }
  .p-t-nav {
    padding-top: $navHeight;
  }
  .cont-item {
    text-align: center;
    height: 50rpx;
    line-height: 50rpx;
    color: #999;
    padding: 20rpx;
    background: #fff;
    border-bottom: 1rpx solid #eaeef1;
  }
}
</style>

swiper 消息滚动

<!-- swiper 消息滚动 -->
<template>
  <view>
    <!-- 展示一条数据 -->
    <template>
      <view class="tit-box">
        <view class="tit-tip">展示一条数据</view>
      </view>
      <view class="scroll-notice">
        <image class="horn-tip" src="https://img1.baidu.com/it/u=3874629958,3395061015&fm=253" />
        <swiper
          class="notice-box"
          vertical
          autoplay
          circular
          interval="4000"
          duration="1500"
          display-multiple-items="1"
          easing-function="easeInOutCubic"
        >
          <swiper-item v-for="(item, i) in swiperList" :key="i">
            <view class="item-box">
              <view>{{ item.bonusTime }}</view>
              <view class="name-tip">抽中了 {{ item.awardName }}</view>
            </view>
          </swiper-item>
        </swiper>
        <image class="arrow-tip" src="https://img0.baidu.com/it/u=1153718811,3800194060&fm=253" />
      </view>
    </template>
    <!-- 展示两条数据 -->
    <template>
      <view class="tit-box">
        <view class="tit-tip">展示两条数据</view>
      </view>
      <view class="fix-two-box">
        <view class="title-box">
          <view class="line-tip"></view>
          <view class="title-tip">展示两条数据</view>
          <view class="line-tip"></view>
        </view>
        <swiper class="fix-swiper" vertical autoplay circular interval="3000" display-multiple-items="2">
          <swiper-item v-for="(item, i) in dataList" :key="i">
            <view class="item-box">
              <view>{{ item.bonusTime }}</view>
              <view class="name-tip">抽中了 {{ item.awardName }}</view>
            </view>
          </swiper-item>
        </swiper>
      </view>
    </template>
    <!-- 高度随数据长度而变化 -->
    <template>
      <view class="tit-box">
        <view class="tit-tip">高度随数据长度而变化</view>
        <view class="btn-tip" :class="{ 'is-sel': curLen === 3 }" @click="toSwitchLen(3)">3条</view>
        <view class="btn-tip" :class="{ 'is-sel': curLen === 6 }" @click="toSwitchLen(6)">6条</view>
        <view class="btn-tip" :class="{ 'is-sel': curLen === 'all' }" @click="toSwitchLen('all')">全部</view>
      </view>
      <view class="vary-swiper">
        <swiper
          vertical
          autoplay
          circular
          interval="3000"
          :style="'height: ' + (swiperList.length > 6 ? 460 : swiperList.length * 60) + 'rpx'"
          :display-multiple-items="swiperList.length > 6 ? 7 : swiperList.length"
        >
          <swiper-item v-for="(item, i) in swiperList" :key="i">
            <view class="item-box">
              <view>{{ item.bonusTime }}</view>
              <view class="name-tip">抽中了 {{ item.awardName }}</view>
            </view>
          </swiper-item>
        </swiper>
      </view>
    </template>
  </view>
</template>

<script>
export default {
  data() {
    return {
      dataList: [
        { bonusTime: "2023/11/01 10:10", awardName: "iPhone 12 Pro Max" },
        { bonusTime: "2023/11/02 11:15", awardName: "华为Mate 40 Pro" },
        { bonusTime: "2023/11/03 12:20", awardName: "三星Galaxy S21 Ultra" },
        { bonusTime: "2023/11/04 13:25", awardName: "小米11 Ultra" },
        { bonusTime: "2023/11/05 14:30", awardName: "OPPO Find X3 Pro" },
        { bonusTime: "2023/11/06 15:35", awardName: "vivo X60 Pro+" },
        { bonusTime: "2023/11/07 16:40", awardName: "谷歌Pixel 6 Pro" },
        { bonusTime: "2023/11/08 17:45", awardName: "荣耀V40" }
      ], // 数据源
      /* 高度随数据长度而变化 */
      curLen: "",
      swiperList: []
    };
  },
  onLoad() {
    this.toSwitchLen("all"); // 切换数据长度
  },
  methods: {
    /* 切换数据长度 */
    toSwitchLen(e) {
      if (this.curLen === e) return;
      this.curLen = e;
      const rowData = JSON.parse(JSON.stringify(this.dataList));
      if (e === "all") e = rowData.length;
      this.swiperList = rowData.slice(0, e);
    }
  }
};
</script>

<style lang="scss" scoped>
.tit-box {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 60rpx 30rpx 30rpx;
  .tit-tip {
    font-weight: 900;
  }
  .btn-tip {
    font-size: 24rpx;
    color: #ff6348;
    padding: 5rpx 20rpx;
    border: 1px solid #ff7f50;
    border-radius: 15rpx;
  }
  .is-sel {
    color: #fff;
    background: #ff6348;
  }
}
/* 展示一条数据 */
.scroll-notice {
  $noticeHeight: 66rpx;
  display: flex;
  align-items: center;
  flex-direction: row;
  height: $noticeHeight;
  line-height: $noticeHeight;
  padding: 0 24rpx;
  margin: 30rpx;
  background: #fdf6ec;
  border-radius: 12rpx;
  // 小喇叭
  .horn-tip {
    flex-shrink: 0;
    width: 34rpx;
    height: 28rpx;
    margin-right: 10rpx;
  }
  .notice-box {
    flex: 1;
    height: $noticeHeight;
    .item-box {
      display: flex;
      align-items: center;
      font-size: 26rpx;
      .name-tip {
        color: #ff9900;
        margin-left: 6rpx;
      }
    }
  }
  // 向右箭头
  .arrow-tip {
    flex-shrink: 0;
    width: 22rpx;
    height: 22rpx;
  }
}
/* 展示两条数据 */
.fix-two-box {
  margin: 30rpx;
  border: 1px solid #2979ff;
  border-radius: 30rpx;
  .title-box {
    $bgColor: #2979ff; // 字体、线条颜色
    $lineWidth: 140; // 线条长度
    display: flex;
    align-items: center;
    justify-content: center;
    margin-top: 30rpx;
    .line-tip {
      position: relative;
      width: $lineWidth + rpx;
      height: 1rpx;
      background: $bgColor;
    }
    .line-tip::before {
      content: "";
      position: absolute;
      bottom: -7rpx;
      width: $lineWidth / 3 + 10 + rpx;
      height: 1rpx;
      background: $bgColor;
    }
    .line-tip:nth-child(1)::before {
      right: 0;
    }
    .title-tip {
      color: $bgColor;
      font-size: 36rpx;
      margin: 0 20rpx;
      font-weight: 900;
    }
  }
  .fix-swiper {
    height: 150rpx;
    font-size: 28rpx;
    margin-top: 30rpx;
    .item-box {
      display: flex;
      align-items: center;
      justify-content: space-between;
      font-size: 26rpx;
      padding: 10rpx 30rpx;
      .name-tip {
        color: #2979ff;
      }
    }
  }
}
/* 高度随数据长度而变化 */
.vary-swiper {
  margin: 30rpx;
  box-sizing: border-box;
  border-radius: 30rpx;
  border: 1px solid #ff7f50;
  .item-box {
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 26rpx;
    padding: 10rpx 30rpx;
    .name-tip {
      color: #ff6348;
    }
  }
}
</style>

swiper 商品滑动

<!-- swiper 商品滑动 -->
<template>
  <view>
    <!-- 一次滑动三条 -->
    <view class="container">
      <view class="tit_box">
        <view class="tit-tip">精选商品</view>
      </view>
      <view class="cont-box">
        <swiper class="swiper-box" :indicator-dots="false" autoplay interval="5000" duration="1000" circular>
          <swiper-item v-for="(row, i) in goodsList" :key="i">
            <view class="item-box" v-for="(item, j) in row.list" :key="j">
              <image class="img-tip" :src="item.img" mode="aspectFill" />
              <view class="name-tip">商品{{ j }}</view>
            </view>
          </swiper-item>
        </swiper>
      </view>
    </view>
    <!-- 一次滑动一条 -->
    <view class="container">
      <view class="tit_box">
        <view class="tit-tip">精选商品</view>
      </view>
      <view class="cont-box">
        <swiper
          class="swiper-box"
          :indicator-dots="false"
          autoplay
          interval="1500"
          duration="1000"
          circular
          :display-multiple-items="recordList.length > 2 ? 3 : recordList.length"
        >
          <swiper-item v-for="(item, i) in recordList" :key="i">
            <view class="item-box" style="width: 100%">
              <image class="img-tip" :src="item.img" mode="aspectFill" />
              <view class="name-tip">商品{{ i }}</view>
            </view>
          </swiper-item>
        </swiper>
      </view>
    </view>
  </view>
</template>

<script>
export default {
  data() {
    return {
      goodsList: [
        {
          list: [
            { img: "https://images.pexels.com/photos/1660030/pexels-photo-1660030.jpeg" },
            { img: "https://images.pexels.com/photos/1640774/pexels-photo-1640774.jpeg" },
            { img: "https://images.pexels.com/photos/699953/pexels-photo-699953.jpeg" }
          ]
        },
        {
          list: [
            { img: "https://images.pexels.com/photos/70497/pexels-photo-70497.jpeg" },
            { img: "https://images.pexels.com/photos/7441761/pexels-photo-7441761.jpeg" },
            { img: "https://images.pexels.com/photos/842571/pexels-photo-842571.jpeg" }
          ]
        },
        {
          list: [
            { img: "https://images.pexels.com/photos/17216084/pexels-photo-17216084.jpeg" },
            { img: "https://images.pexels.com/photos/8969237/pexels-photo-8969237.jpeg" },
            { img: "https://images.pexels.com/photos/1099680/pexels-photo-1099680.jpeg" }
          ]
        }
      ],
      recordList: [
        { img: "https://images.pexels.com/photos/1660030/pexels-photo-1660030.jpeg" },
        { img: "https://images.pexels.com/photos/1640774/pexels-photo-1640774.jpeg" },
        { img: "https://images.pexels.com/photos/699953/pexels-photo-699953.jpeg" },
        { img: "https://images.pexels.com/photos/70497/pexels-photo-70497.jpeg" },
        { img: "https://images.pexels.com/photos/7441761/pexels-photo-7441761.jpeg" },
        { img: "https://images.pexels.com/photos/842571/pexels-photo-842571.jpeg" },
        { img: "https://images.pexels.com/photos/17216084/pexels-photo-17216084.jpeg" }
      ]
    };
  },
  onLoad() {},
  methods: {}
};
</script>

<style lang="scss" scoped>
.container {
  position: relative;
  height: 228rpx;
  margin: 20rpx;
  background: #ff4757;
  border-radius: 20rpx;
  overflow: hidden;
  .tit_box {
    width: 110rpx;
    text-align: center;
    height: 100%;
    background: #ff6b81;
    .tit-tip {
      display: inline-block;
      color: #fff;
      width: 50rpx;
      text-align: center;
      vertical-align: middle;
      font-size: 30rpx;
      white-space: pre-wrap;
      font-weight: 900;
    }
  }
  .tit_box::after {
    content: "";
    display: inline-block;
    height: 100%;
    vertical-align: middle;
  }
  .cont-box {
    position: absolute;
    top: 20rpx;
    left: 108rpx;
    width: 84%;
    white-space: nowrap;
    overflow-y: auto;
    box-sizing: border-box;
    .swiper-box {
      height: 192rpx;
      overflow: hidden;
      .item-box {
        float: left;
        width: calc(100% / 3);
        height: 192rpx;
        text-align: center;
        .img-tip {
          display: block;
          width: 145rpx;
          height: 154rpx;
          margin: 0 auto 9rpx;
          border-radius: 16rpx;
        }
        .name-tip {
          text-align: center;
          height: 30rpx;
          line-height: 30rpx;
          color: #fff;
          font-size: 22rpx;
        }
      }
    }
  }
}
</style>

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

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

相关文章

喜讯 | 同立海源生物入选2023年国创中心细胞疗法“揭榜挂帅”技术攻关项目

近日&#xff0c;2023年国家生物药技术创新中心细胞疗法“揭榜挂帅”技术攻关拟立项目名单公示&#xff0c;北京同立海源生物科技有限公司&#xff08;简称“同立海源生物”&#xff09;参评的 “细胞分选激活磁珠研发项目” 凭借公司多年在细胞分选磁珠领域的技术沉淀和创新性…

【期末考复习向】transformer的运作机制

1.transformer的encoder运作 transformer的encoder部分包括了输入和处理2大部分。首先是输入部分inputs&#xff0c;这里初始的inputs是采用独热向量进行表示的&#xff0c;随后经过word2vec等操作把独热向量&#xff08;采用独热向量的好处就是可向量是正交的&#xff0c;可以…

K8S(五)—命名空间与资源配额

目录 命名空间(Namespace)命令计算资源配额创建命名空间绑定一个ResourceQuota资源将命名空间和资源限制对象进行绑定尝试创建第二个 Pod查看ResourceQuota 绑定第二个ResourceQuota为命名空间配置默认的 CPU 、memory请求和限制&#xff08;1&#xff09;Pod 中所有容器都没有…

样本空间的一个划分

假设试验E的样本空间为S&#xff0c;为E的一组事件&#xff0c;如果这组事件满足如下条件&#xff1a; &#xff0c;其中&#xff0c;&#xff0c;即事件两两之间互不相容 那么就称为样本空间S的一个划分。

3D Font

在游戏中使用3D文本 只需添加预制件并立即生成您的文本。 特点: *真实3D字母&#xff0c;可用作游戏对象*移动友好低聚 *VR兼容 *WebGL兼容 *30种以上不同字体 *材料和颜色可定制 WebGL演示 https://indiechest.itch.io/3d-font-engine 下载&#xff1a; ​​Unity资源商店链…

redis:二、缓存击穿的定义、解决方案(互斥锁、逻辑过期)的优缺点和适用场景、面试回答模板

缓存击穿的定义 缓存击穿是一种现象&#xff0c;具体就是某一个数据过期时&#xff0c;恰好有大量的并发请求过来&#xff0c;这些并发的请求可能会瞬间把DB压垮。典型场景就是双十一等抢购活动中&#xff0c;首页广告页面的数据过期&#xff0c;此时刚好大量用户进行请求&…

Linux的五种IO模型

众所周知&#xff0c;出于对 OS 安全性的考虑&#xff0c;用户进程是不能直接操作 I/O 设备的。必须通过系统调用请求操作系统内核来协助完成 I/O 动作。 下图展示了 Linux I/O 的过程。 操作系统内核收到用户进程发起的请求后&#xff0c;从 I/O 设备读取数据到 kernel buff…

使用PM2,在生产环境稳定运行你的node项目

PM2 一个 node&#xff0c;本身就用几行代码&#xff0c;就可以启动个 server 进程&#xff0c;监听个端口&#xff0c;为大家提供 Web 服务 一、依赖安装 npm install pm2 -g 二、命令行启动 普通执行启动 pm2 start <js 文件路径 >.js 携带参数启动 pm2 start < 某种…

AR眼镜_AR智能眼镜整机硬件方案定制

AR眼镜的主要模块包括显示、光学模组、传感器和摄像头、主板、音频和网络连接等。其中&#xff0c;光学显示、主板处理器是决定AR眼镜成本的关键&#xff0c;光机占整体AR眼镜成本43%、处理器占整体成本31%。 AR眼镜的主板设计难点在于尺寸要足够小且要处理好散热问题。主板上的…

Fuzz入门教学——污点分析

1、简介 污点分析是一种用于检测和防止安全漏洞的技术。它关注数据流中的敏感信息&#xff08;污点&#xff09;如何在程序中传播&#xff0c;从而导致安全风险。这种分析通常用于发现潜在的安全漏洞&#xff0c;例如隐私数据泄露或者对数据完整性的威胁。污点分析标记程序中的…

集成显卡Intel® UHD Graphics 630 安装Pytorch

安装Pytorch是为了搭建maskrcnn环境。 查了一圈发现&#xff1a; 显卡Intel UHD Graphics 630是集成显卡&#xff0c;所以不能安装cuda和cudann&#xff0c;也不能使用GPU加速 所以也需要放弃在该电脑上的用VMware新建Ubuntu虚拟机&#xff0c;然后安装有cuda版本的Pytorch&a…

2023-12-08 队列与栈

栈与队列一 232. 用栈实现队列 思路&#xff1a;对于使用栈实现队列的话&#xff0c;必须使用两个共同来维护使得每次都能先进先出&#xff01; class MyQueue:def __init__(self):# 需要建立两个list来维护出栈以及进栈self.stack_in []self.stack_out []def push(self, x…

C# 两个日期比较大小

文章目录 C# 两个日期比较大小直接比较大小工具类DateTime.Compare C# 两个日期比较大小 直接比较大小 string ed "2023-12-13 09:27:59.000";//过去式DateTime nowDateTime DateTime.Now;DateTime expirationDate Convert.ToDateTime(ed);//质保期 长日期DateT…

压缩pdf怎么压缩又小又清晰?超级实用!

当PDF文件过大时&#xff0c;很容易遇到无法上传等现象&#xff0c;这时候我们可以借助一些专业的压缩工具&#xff0c;将PDF文件压缩变小&#xff0c;如果你还不知道怎么做&#xff0c;下面就来看下具体的压缩方法吧。 方法一&#xff1a;使用嗨格式压缩大师 1、打开电脑上安…

【Debug小结】关于部署Java项目的Jar包到本地服务器失败

问题描述&#xff1a; 在Idea中完成项目编码后&#xff0c;使用Package打包成.jar文件 接下来使用cmd执行java -jar xxx 命令后 报错如下&#xff1a;Error: A JNI error has occurred, please check your installation and try again Exception in thread "main" j…

【内存函数】

目录 memcpy使用和模拟实现memmove使用和模拟实现memset使用memcmp使用 1. memcpy使用和模拟实现 void * memcpy ( void * destination, const void * source, size_t num) ; 函数memcpy从source的位置开始向后复制num个字节的数据到destination指向的内存的位置这个函数在遇到…

【Jenkins】Centos环境安装Jenkins(通过docker安装)

通过docker环境安装Jenkins 参考官网 https://hub.docker.com/r/jenkins/jenkins/ 1、安装docker环境 # 删除已有安装包 sudo yum remove docker \docker-client \docker-client-latest \docker-common \docker-latest \docker-latest-logrotate \docker-logrotate \docker-…

企业考勤技术,这个方法很靠谱!

在当今社会&#xff0c;随着科技的不断进步&#xff0c;人脸识别技术在各个领域得到了广泛应用。其中&#xff0c;三维人脸考勤系统作为一种高效、准确的考勤解决方案&#xff0c;正在成为企业管理和人力资源管理的重要工具之一。 与传统的二维人脸识别相比&#xff0c;三维人脸…

Corona最新渲染器Corona11详解,附送下载地址

近日&#xff0c;Corona进行了大版本更新&#xff0c;发布了最新的Corona11。这次更新&#xff0c;包含众多新功能和新修复&#xff0c;借助 Corona 11 用户可将作品提升到更高的创作水准&#xff0c;更真实可感的视觉水平。 那么更新了那些呢&#xff1f;一起来看看吧&#x…

Restormer技术点小结

1. 解决cnn的不足&#xff1a; 1&#xff09;感受野有限 2&#xff09;输入尺寸固定 2. 解决transform的不足&#xff1a; 1&#xff09;计算复杂度随着空间分辨率的增加而二次增长 3. 优势结构&#xff1a;MDTA(Multi-Dconv Head Transposed Attention)和GDFN( Gated-Dco…