mirror of
https://github.com/DefectingCat/DefectingCat.github.io
synced 2025-07-16 01:01:38 +00:00
更新文章:移动端触摸轮播图
1. 更新包 2. 添加Netlify标
This commit is contained in:
@ -1,2 +1,5 @@
|
|||||||
## 小破站
|
## 小破站
|
||||||
|
|
||||||
|
[](https://app.netlify.com/sites/brave-nobel-bc5790/deploys)
|
||||||
|
|
||||||
|
[xfy.plus](https://xfy.plus/)
|
12308
package-lock.json
generated
12308
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
18
package.json
18
package.json
@ -14,11 +14,11 @@
|
|||||||
"cl": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
|
"cl": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
|
||||||
},
|
},
|
||||||
"hexo": {
|
"hexo": {
|
||||||
"version": "5.3.0"
|
"version": "5.4.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"babel": "^6.23.0",
|
"babel": "^6.23.0",
|
||||||
"commitizen": "^4.2.2",
|
"commitizen": "^4.2.3",
|
||||||
"conventional-changelog-cli": "^2.1.1",
|
"conventional-changelog-cli": "^2.1.1",
|
||||||
"gulp": "^4.0.2",
|
"gulp": "^4.0.2",
|
||||||
"gulp-clean-css": "^4.3.0",
|
"gulp-clean-css": "^4.3.0",
|
||||||
@ -26,9 +26,9 @@
|
|||||||
"gulp-htmlmin": "^5.0.1",
|
"gulp-htmlmin": "^5.0.1",
|
||||||
"gulp-uglify": "^3.0.2",
|
"gulp-uglify": "^3.0.2",
|
||||||
"gulp-uglify-es": "^2.0.0",
|
"gulp-uglify-es": "^2.0.0",
|
||||||
"hexo": "^5.3.0",
|
"hexo": "^5.4.0",
|
||||||
"hexo-cli": "^4.2.0",
|
"hexo-cli": "^4.2.0",
|
||||||
"hexo-deployer-git": "^2.1.0",
|
"hexo-deployer-git": "^3.0.0",
|
||||||
"hexo-generator-archive": "^1.0.0",
|
"hexo-generator-archive": "^1.0.0",
|
||||||
"hexo-generator-category": "^1.0.0",
|
"hexo-generator-category": "^1.0.0",
|
||||||
"hexo-generator-feed": "^3.0.0",
|
"hexo-generator-feed": "^3.0.0",
|
||||||
@ -36,13 +36,15 @@
|
|||||||
"hexo-generator-sitemap": "^2.1.0",
|
"hexo-generator-sitemap": "^2.1.0",
|
||||||
"hexo-generator-tag": "^1.0.0",
|
"hexo-generator-tag": "^1.0.0",
|
||||||
"hexo-renderer-ejs": "^1.0.0",
|
"hexo-renderer-ejs": "^1.0.0",
|
||||||
"hexo-renderer-marked": "^3.3.0",
|
"hexo-renderer-marked": "^4.0.0",
|
||||||
"hexo-renderer-stylus": "^2.0.1",
|
"hexo-renderer-stylus": "^2.0.1",
|
||||||
"hexo-server": "^2.0.0",
|
"hexo-server": "^2.0.0",
|
||||||
"hexo-theme-fluid": "^1.8.7"
|
"hexo-theme-fluid": "^1.8.7",
|
||||||
|
"npm-check-updates": "^11.1.9",
|
||||||
|
"nunjucks": "^3.2.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.12.10",
|
"@babel/core": "^7.13.8",
|
||||||
"@babel/preset-env": "^7.12.11"
|
"@babel/preset-env": "^7.13.8"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
396
source/_posts/移动端触摸轮播图.md
Normal file
396
source/_posts/移动端触摸轮播图.md
Normal file
@ -0,0 +1,396 @@
|
|||||||
|
---
|
||||||
|
title: 移动端触摸轮播图
|
||||||
|
date: 2021-02-23 08:57:10
|
||||||
|
tags: [Vue, JavaScript]
|
||||||
|
categories: 实践
|
||||||
|
url: mobile-slidershow
|
||||||
|
index_img: /images/移动端触摸轮播图/logo.webp
|
||||||
|
---
|
||||||
|
|
||||||
|
## 迫害移动端
|
||||||
|
|
||||||
|
继上次的[经典轮播图的实现方案](/defect/classic-slider-show.html),这次配合了`TouchEvent`来实现了移动端的触摸轮播图。
|
||||||
|
|
||||||
|
这次原生的实现方式和 Vue 基本相同,由于需要实现触摸滑动,仅仅靠`absolute`定位和 Vue 的过渡动画是不够的。所以使用了经典的图片队列,然后克隆两张图片来调换队列。
|
||||||
|
|
||||||
|
## 封装组件
|
||||||
|
|
||||||
|
这次把整个轮播图图都尝试封装成一个单独的组件,图片的队列和动画延时都由父组件传递 props 过来。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<TouchSlider :images="images" :animeTime="'500'" />
|
||||||
|
```
|
||||||
|
|
||||||
|
组件内:
|
||||||
|
|
||||||
|
```js
|
||||||
|
props: {
|
||||||
|
// 图片队列
|
||||||
|
images: Array,
|
||||||
|
// 动画时间
|
||||||
|
animeTime: String
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
## 经典方案的实现
|
||||||
|
|
||||||
|
虽然是用 Vue 来实现的方案,但本质上还是将经典方案封装成一个组件,然后配合上`TouchEvent`来实现了移动端的触摸轮播图。
|
||||||
|
|
||||||
|
所以第一步还是先使用 Vue 的方式实现经典的布局方案。
|
||||||
|
|
||||||
|
### 布局
|
||||||
|
|
||||||
|
组件内的布局和之前的经典方案一模一样,外部的 div 使用`relative`定位,内部的 ul 通过`transform`来进行位移。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<div class="slider">
|
||||||
|
<ul class="wrapper">
|
||||||
|
<!-- v-for 循环的图片 -->
|
||||||
|
<li></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
```
|
||||||
|
|
||||||
|
与上次不同的地方是这次 ul 使用的`flex`布局,而不是针对 li 使用`flot`。相对于使用浮动`flot`来说,`flex`布局更加好控制,也更先进。
|
||||||
|
|
||||||
|
```css
|
||||||
|
.slider {
|
||||||
|
position: relative;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.wrapper {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 克隆图片
|
||||||
|
|
||||||
|
在 Vue 里就不那么依赖操作 DOM 了,克隆第一张和最后一张图片也很方便,,对传过来的图片数组取第一个和最后一个项目就可以了。
|
||||||
|
|
||||||
|
整个图片的队列通过`v-for`来循环生成。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<!-- 克隆最后一张图片 -->
|
||||||
|
<li>
|
||||||
|
<img :src="images[images.length - 1].src" alt="" class="roll-img" />
|
||||||
|
</li>
|
||||||
|
<li v-for="item in images" :key="'img' + item.id">
|
||||||
|
<img :src="item.src" alt="" class="roll-img" ref="img" />
|
||||||
|
</li>
|
||||||
|
<!-- 克隆第一张图片 -->
|
||||||
|
<li>
|
||||||
|
<img :src="images[0].src" alt="" class="roll-img" />
|
||||||
|
</li>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 队列宽度
|
||||||
|
|
||||||
|
经典方案还有个重点就是整个 ul 队列的宽度,它配额偏移量才能准确实现图片的移动。
|
||||||
|
|
||||||
|
这里给图片`<img>`都上了一个样式,用来决定图片的宽度:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.roll-img {
|
||||||
|
width: 600px;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
同时还用了个媒体查询,虽然不能做到实时的响应式,但是根据不同的设备还是能做的刷新后适配不同的设备端的。
|
||||||
|
|
||||||
|
```css
|
||||||
|
@media only screen and (max-width: 376px) {
|
||||||
|
.roll-img {
|
||||||
|
width: 375px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
既然图片的宽度确定了,那整个 ul 的宽度就是`单张图片的宽度 * 图片的数量`了。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ul
|
||||||
|
class="wrapper"
|
||||||
|
:style="{
|
||||||
|
width: imgWidth * images.length + 'px'
|
||||||
|
}"
|
||||||
|
></ul>
|
||||||
|
```
|
||||||
|
|
||||||
|
图片的数量`images.length`很容易确定,单张图片的宽度需要使用 HTMLElement 上的`HTMLElement.offsetWidth`方法。它能返回一个元素的布局宽度,这里使用它来获取单个`<img>`的宽度。获取的时机就在组件被挂载时:
|
||||||
|
|
||||||
|
```js
|
||||||
|
mounted() {
|
||||||
|
// 计算单个图片的宽度,做移动端适配
|
||||||
|
this.imgWidth = this.$refs.img[0].offsetWidth;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
现在在`data()`中还只保存了单张图片宽度`imgWidth`,慢慢来,它会越来越多的。
|
||||||
|
|
||||||
|
```js
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 单张图片的宽度
|
||||||
|
imgWidth: 0,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### 移动方法
|
||||||
|
|
||||||
|
这次依然使用`transition`过渡来实现移动的动画,控制位置使用`translateX`。
|
||||||
|
|
||||||
|
第一步先封装一个移动的方法,用了前两次的经验,这次修改了移动图片的方法,并且它接受一个参数,用于判断是否开启过渡动画:
|
||||||
|
|
||||||
|
```js
|
||||||
|
move(anime) {
|
||||||
|
// 移动方法,添加过渡动画,根据图片序列移动图片
|
||||||
|
if (anime) {
|
||||||
|
this.transitionX = `all ${this.animeTime}ms`;
|
||||||
|
} else {
|
||||||
|
this.transitionX = `none`;
|
||||||
|
}
|
||||||
|
this.translateX = -(this.imgWidth + this.imgWidth * this.imgIndex);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
图片移动的距离也使用了一种更好的公式:`-(单张图片的宽度 + 单张图片的宽度 * 当前图片索引)`。
|
||||||
|
|
||||||
|
这个公式的好处就是队列的位移由图片的索引进行驱动,当需要修改队列的位移的位置时,只需要相应的修改索引值,然后调用移动方法内的公式即可。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 默认位置
|
||||||
|
|
||||||
|
上述在`mounted()`挂载后获取了图片的宽度,现在还需要增加一个在挂载后修改下队列的位置。当克隆了两张图片分别在队列的前后时,队列的默认位置需要向左偏移一个图片的宽度。
|
||||||
|
|
||||||
|
现在在`data()`中还要再保存一个图片的索引。
|
||||||
|
|
||||||
|
```js
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// 单张图片的宽度
|
||||||
|
imgWidth: 0,
|
||||||
|
// 图片索引,用于控制位置
|
||||||
|
imgIndex: 0,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
所以在挂载后,图片的索引为0,调用移动方法即可将队列设置为默认的位置:
|
||||||
|
|
||||||
|
```js
|
||||||
|
mounted() {
|
||||||
|
// 计算单个图片的宽度,做移动端适配
|
||||||
|
this.imgWidth = this.$refs.img[0].offsetWidth;
|
||||||
|
this.move(false);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 小圆点
|
||||||
|
|
||||||
|
按钮封装的非常基本,就是普通的按钮添加两个点击事件,分别用于操作图片索引加减。这里就不再多说了。
|
||||||
|
|
||||||
|
按钮的方法:
|
||||||
|
|
||||||
|
```js
|
||||||
|
previous() {
|
||||||
|
if (Date.now() - this.flag > Number(this.animeTime) + 10) {
|
||||||
|
this.imgIndex--;
|
||||||
|
this.move(true);
|
||||||
|
this.flag = Date.now();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
next() {
|
||||||
|
if (Date.now() - this.flag > Number(this.animeTime) + 10) {
|
||||||
|
this.imgIndex++;
|
||||||
|
this.move(true);
|
||||||
|
this.flag = Date.now();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
小圆点也不是非常的复杂,简单封装一个`<ol><li></li></ol>`的结构即可。在父组件中通过`v-for`来循环生成 li,顺便绑定 images 的 index 到 li 的 id 上,用于点击事件。
|
||||||
|
|
||||||
|
```html
|
||||||
|
<IndexPoint
|
||||||
|
class="index-point"
|
||||||
|
:num="images.length"
|
||||||
|
@pointClick="pointClick"
|
||||||
|
>
|
||||||
|
<template>
|
||||||
|
<li
|
||||||
|
v-for="(item, index) in images"
|
||||||
|
:key="'point' + item.id"
|
||||||
|
:class="{ active: index == pointIndex }"
|
||||||
|
:id="index"
|
||||||
|
></li>
|
||||||
|
</template>
|
||||||
|
</IndexPoint>
|
||||||
|
```
|
||||||
|
|
||||||
|
在点击事件里,将点击的小圆点的 id 赋值到图片的索引,然后再调用`move()`方法就可以正确的移动到对于的图片上。
|
||||||
|
|
||||||
|
```js
|
||||||
|
pointClick(e) {
|
||||||
|
this.imgIndex = e.target.id;
|
||||||
|
this.move(true);
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 无限循环
|
||||||
|
|
||||||
|
轮播图的重点就在于能够无限轮播,这里使用的还是和往期一样的方案:当移动到克隆的图片时,偷偷替换图片队列。不同的是,这次没有使用`setTimeOut`来进行延时调换,而是使用了`transitionend`事件。该事件就是监听过渡动画完成后调用方法。
|
||||||
|
|
||||||
|
监听的方法还是和以前一样,通过判断图片的索引来确定是否是克隆的图片,然后偷偷调换队列。
|
||||||
|
|
||||||
|
```js
|
||||||
|
transEnd() {
|
||||||
|
if (this.imgIndex == -1) {
|
||||||
|
// 如果当前序列等于 -1,也就是克隆的图片,则偷偷调整图片队列
|
||||||
|
this.imgIndex = this.images.length - 1;
|
||||||
|
this.move(false);
|
||||||
|
} else if (this.imgIndex == this.images.length) {
|
||||||
|
// 反之亦然
|
||||||
|
this.imgIndex = 0;
|
||||||
|
this.move(false);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 自动播放
|
||||||
|
|
||||||
|
自动播放实现的也很简单,定时操作图片的索引即可。
|
||||||
|
|
||||||
|
不过这里遇到一个小 Bug,当 Chrome 在后台时,`transitionend`事件不会被监听。这就会导致使用了自动播放在后台放一会之后,所有的图片都消失了。
|
||||||
|
|
||||||
|
后来研究了下可以通过[`document.visibilityState`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document/visibilityState)判断浏览器是否处于后台,当其值不等于`hidden`时,就继续播放。
|
||||||
|
|
||||||
|
```js
|
||||||
|
autoPlay() {
|
||||||
|
this.timer = setInterval(() => {
|
||||||
|
// 当页面处于后台时,transEnd会失效
|
||||||
|
if (document.visibilityState != 'hidden') {
|
||||||
|
this.imgIndex++;
|
||||||
|
this.move(true);
|
||||||
|
}
|
||||||
|
console.log(document.visibilityState);
|
||||||
|
}, 3000);
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
visible
|
||||||
|
5 hidden
|
||||||
|
visible
|
||||||
|
```
|
||||||
|
|
||||||
|
## 触摸事件
|
||||||
|
|
||||||
|
上述方法都是将以前实现的经典方案封装到 Vue 组件里,本次的重点还是触摸的滑动方法。
|
||||||
|
|
||||||
|
触摸由三个事件组成:从 touchstart 到 touchmove 到 touchend。他们分别对应动作:触摸开始、触摸移动和触摸结束。每一次的触摸都会触发这三个事件。
|
||||||
|
|
||||||
|
[触摸事件](https://developer.mozilla.org/zh-CN/docs/Web/API/Touch_events)有个事件对象`touches`,它就是实现图片移动的主要原理。`touches`内保存这触摸时的坐标,在不同的触摸事件里可以根据坐标来移动图片。
|
||||||
|
|
||||||
|
所以这里现在 ul 上绑定对应的三个事件:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<ul
|
||||||
|
class="wrapper"
|
||||||
|
:style="{
|
||||||
|
width: imgWidth * images.length + 'px',
|
||||||
|
}"
|
||||||
|
@touchstart="touchStart"
|
||||||
|
@touchmove="touchMove"
|
||||||
|
@touchend="touchEnd"
|
||||||
|
>
|
||||||
|
```
|
||||||
|
|
||||||
|
### 触摸开始
|
||||||
|
|
||||||
|
第一个是触摸开始的阶段,当第一次触摸到 ul 时,就会触发这个事件。这个事件非常简单,就保存了两个关键的数据:点击时的 X 坐标和当前的图片位置。方便在移动时判断对应的移动位置。
|
||||||
|
|
||||||
|
```js
|
||||||
|
touchStart(e) {
|
||||||
|
this.pausePlay();
|
||||||
|
// 触摸开始
|
||||||
|
if (Date.now() - this.flag > Number(this.animeTime) + 10) {
|
||||||
|
// 获取点击时的 X 坐标
|
||||||
|
this.startX = e.touches[0].clientX;
|
||||||
|
// 点击开始时保存当前图片的位置
|
||||||
|
this.lastX = this.translateX;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 触摸移动
|
||||||
|
|
||||||
|
图片移动的位置就是`原先的位置 + 滑动的距离`。首先判断滑动的距离,使用当前`touchMove`的 X 坐标减去`touchStart`所保存的 X 坐标,就能轻松得出移动了多少距离。
|
||||||
|
|
||||||
|
然后再将图片的过渡动画取消`this.transitionX = 'none';`,再给图片添加上移动的距离`this.translateX = this.lastX + this.moveX;`
|
||||||
|
|
||||||
|
这里还做了一个简单的判断,当滑动的距离大于单张图片的宽度时`this.moveX >= this.imgWidth`,就不允许再移动了`this.moveX = this.imgWidth;`。同样使用正负值来判断左右移动的方向`this.moveX < 0 && this.moveX <= -this.imgWidth`。
|
||||||
|
|
||||||
|
```js
|
||||||
|
touchMove(e) {
|
||||||
|
// 防止在一定时间内过渡滑动
|
||||||
|
if (Date.now() - this.flag > Number(this.animeTime) + 10) {
|
||||||
|
// 移动时的坐标减去点击时的坐标等于移动的距离
|
||||||
|
this.moveX = e.touches[0].clientX - this.startX;
|
||||||
|
// 移动图片
|
||||||
|
this.transitionX = `none`;
|
||||||
|
// 防止滑动过渡
|
||||||
|
if (this.moveX >= this.imgWidth) {
|
||||||
|
this.moveX = this.imgWidth;
|
||||||
|
// 滑动位置等于上次的位置加上手指移动的距离
|
||||||
|
this.translateX = this.lastX + this.moveX;
|
||||||
|
} else if (this.moveX < 0 && this.moveX <= -this.imgWidth) {
|
||||||
|
this.moveX = -this.imgWidth;
|
||||||
|
this.translateX = this.lastX + this.moveX;
|
||||||
|
} else {
|
||||||
|
this.translateX = this.lastX + this.moveX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
### 触摸结束
|
||||||
|
|
||||||
|
当图片正确的移动后,触摸结束的事件就是对图片做一些判断,保证队列是预期的状态。
|
||||||
|
|
||||||
|
第一个判断就是当滑动了整张图片时,不需要再调用`move()`方法了,直接对左右方向进行判断,确定图片的索引加减`this.moveX > 0 ? this.imgIndex-- : this.imgIndex++;`。不过还得再调用一次` this.transEnd()`方法来偷偷调换图片队列。
|
||||||
|
|
||||||
|
```js
|
||||||
|
touchEnd() {
|
||||||
|
if (Date.now() - this.flag > Number(this.animeTime) + 10) {
|
||||||
|
// 防止滑动过渡
|
||||||
|
if (this.moveX == this.imgWidth || this.moveX == -this.imgWidth) {
|
||||||
|
this.moveX > 0 ? this.imgIndex-- : this.imgIndex++;
|
||||||
|
// 当越界时,调用恢复队列
|
||||||
|
this.transEnd();
|
||||||
|
// 当触摸大于 70 像素,触发移动动画,移动完整图片
|
||||||
|
} else if (this.moveX > 70) {
|
||||||
|
this.imgIndex--;
|
||||||
|
this.move(true);
|
||||||
|
// 当触摸小于 -70 像素,触发移动动画,移动完整图片
|
||||||
|
} else if (this.moveX < -70) {
|
||||||
|
this.imgIndex++;
|
||||||
|
this.move(true);
|
||||||
|
// 当在二者之间时,图片归位
|
||||||
|
} else {
|
||||||
|
this.move(true);
|
||||||
|
}
|
||||||
|
this.startX = 0;
|
||||||
|
this.moveX = 0;
|
||||||
|
this.flag = Date.now();
|
||||||
|
}
|
||||||
|
this.autoPlay();
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🚀
|
||||||
|
|
||||||
|
这就是在之前的轮播图上加以实现的移动端轮播图方案,还有一些小方法就没有多嘴了。
|
||||||
|
|
||||||
|
几个方法写的比较冗余,感觉可以再简单一点。主要的是对这个组件封装的很烂,整个`TouchSlider.vue`一大串。
|
||||||
|
|
||||||
|
[项目地址](https://git.defectink.com/xfy/vue-touch-slider)
|
@ -3,7 +3,7 @@ title: 经典轮播图的实现方案
|
|||||||
date: 2021-02-09 13:37:00
|
date: 2021-02-09 13:37:00
|
||||||
tags: [Vue, JavaScript]
|
tags: [Vue, JavaScript]
|
||||||
categories: 实践
|
categories: 实践
|
||||||
url: classic-slider-show
|
url: classic-slidershow
|
||||||
index_img: /images/经典轮播图的实现方案/logo.webp
|
index_img: /images/经典轮播图的实现方案/logo.webp
|
||||||
---
|
---
|
||||||
|
|
||||||
|
BIN
source/images/移动端触摸轮播图/2021-02-23-11-23-15.webp
Normal file
BIN
source/images/移动端触摸轮播图/2021-02-23-11-23-15.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 19 KiB |
BIN
source/images/移动端触摸轮播图/logo.psd
Normal file
BIN
source/images/移动端触摸轮播图/logo.psd
Normal file
Binary file not shown.
BIN
source/images/移动端触摸轮播图/logo.webp
Normal file
BIN
source/images/移动端触摸轮播图/logo.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.1 KiB |
@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
title: pgp
|
title: pgp
|
||||||
date: 2020-02-23 17:03:44
|
date: 2020-02-23 17:03:44
|
||||||
comment: true
|
comment: 'valine'
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="markdown-body">
|
<div class="markdown-body">
|
||||||
|
Reference in New Issue
Block a user