最近在做一个小程序,帖子中用到了一个关于文字、图片和视频的一些操作。
最终的样式
未添加任何图片和视频
点击视频和图片的任意一个上传按钮就会开始上传
添加图片
这部分可以对图片进行预览和删除
添加视频
视频和删除和播放
这个可以实现输入文字的统计和限制,图片的上传、预览和删除,视频的上传和删除功能。
如何实现上面的那些样式呢?
大家可以先阅读下面的文档,会发现其实很简单。
小程序关于图片操作的api文档:https://developers.weixin.qq.com/miniprogram/dev/api/wx.compressImage.html
小程序关于视频操作的api文档:https://developers.weixin.qq.com/miniprogram/dev/api/wx.saveVideoToPhotosAlbum.html
首先wxml文件
<view class="containor">
<view class="publish_text_area">
<!-- 标题 -->
<view class="text_area_title">
<input
class="title_input"
placeholder="请输入标题"
maxlength="25"
placeholder-style="color:#b3b3b3;font-size:16px;"
bindinput="handleTitleInput"
value="{{title}}"
></input>
<!-- 标题字数限制 -->
<view
class="{{ titleCount < 25 ? 'title_input_counter' : 'title_input_error_counter' }}"
>{{titleCount}}/25</view>
</view>
<!-- 内容 -->
<view class="text_area_content">
<view class="area_content">
<view class="area_content_out">
<textarea
class="content-textarea"
placeholder="请输入正文内容..."
maxlength="255"
placeholder-style="color:#b3b3b3;font-size:12px;"
style="height: 8rem"
bindinput="handleContentInput"
value="{{content}}"
/>
<!-- 字数限制 -->
<view class="{{ contentCount < 255 ? 'content_textarea_counter' : 'content_textarea_error_counter'}}">{{contentCount}}/255</view>
</view>
</view>
</view>
</view>
<view class="publish_imgs_area">
<!-- 图片 -->
<view class="imgs_area" wx:for="{{images}}" wx:key="*this">
<view class="iamge_item">
<image
class="iamge_content"
src="{{item}}"
data-id="{{index}}"
mode="aspectFill"
bindtap="previewIamge"
/>
<image
class="iamge_cancel"
src="./images/cancel.png"
mode="aspectFill"
data-id="{{index}}"
bindtap="deleteImage"
/>
</view>
</view>
<!-- 视频 -->
<view class="video_area" wx:if="{{video != ''}}">
<video
class="video_item"
src="{{video}}"
controls
></video>
<image
class="video_delete"
src="./images/video_del.png"
mode="aspectFill"
bindtap="videoDelete"
/>
</view>
<!-- 图片上传图片按钮 -->
<view class="imgs_area" bindtap="chooseImage" wx:if="{{images.length < 9 && video == ''}}">
<view class="iamge_item">
<image class="iamge_content" src="./images/upload.png" mode="aspectFill" />
</view>
</view>
<!-- 视频上传图片按钮 -->
<view class="imgs_area" bindtap="chooseVideo" wx:if="{{video == '' && images.length == 0}}">
<view class="iamge_item">
<image class="iamge_content" src="./images/video.png" mode="aspectFill" />
</view>
</view>
</view>
<view class="btn_all_area">
<button
class="btn_area"
type="primary"
bindtap="submitClick"
>提交</button>
<button
class="btn_area"
type="warn"
bindtap="resetClick"
>重置</button>
</view>
</view>
接下来wxss文件
page {
background-color: #f1efef;
}
.containor {
display: flex;
flex-direction: column;
justify-content: center;
}
.publish_text_area {
background-color: #ffffff;
display: flex;
flex-direction: column;
justify-content: center;
margin:20rpx 20rpx 6rpx 20rpx;
border-radius: 15rpx;
}
.text_area_title {
display: flex;
flex-direction: row;
justify-content: space-between;
margin: 10rpx;
}
.text_area_content {
}
.title_input {
font-size: 30rpx;
width:590rpx;
}
.title_input_counter {
font-size:32rpx;
color:#b3b3b3;
margin-top:5rpx;
}
.title_input_error_counter {
font-size:32rpx;
color:#ce2f2f;
margin-top:5rpx;
}
.area_content {
border-top: 1rpx solid #f1efef;
margin-left: 10rpx;
margin-right: 10rpx;
}
.area_content_out {
/* border-top: 1px solid #f1efef; */
margin-top: 10rpx;
}
.content-textarea {
width: 690rpx;
font-size: 24rpx;
}
.content_textarea_counter {
color:#d4d0d0;
font-size:30rpx;
text-align:right;
}
.content_textarea_error_counter {
color:#ce2f2f;
font-size:30rpx;
text-align:right;
}
/* 图片部分 */
.publish_imgs_area{
background-color: #ffffff;
display: flex;
flex-direction: row;
justify-content: flex-start;
flex-wrap: wrap;
border-radius: 15rpx;
margin: 20rpx;
padding-left: 8rpx;
padding-top: 8rpx;
padding-bottom: 8rpx;
/* height: 450rpx; */
}
.iamge_item {
width: 225rpx;
height: 225rpx;
padding: 4rpx;
}
.iamge_content{
width: 223rpx;
height: 223rpx;
border-radius: 15rpx;
border: 1px solid #f1efef;
}
.iamge_cancel{
width:40rpx;
height:40rpx;
border-radius:50%;
position:relative;
top:-259rpx;
right:-204rpx;
z-index:800;
}
/* 视频部分样式 */
.video_area {
width: 700rpx;
position: relative;
}
.video_item {
width: 700rpx;
}
.video_delete {
width: 50rpx;
height: 50rpx;
position: absolute;
top: 10rpx;
right: 2rpx;
}
.btn_all_area {
background-color: #ffffff;
display: flex;
flex-direction: row;
justify-content: center;
margin:20rpx 20rpx 6rpx 20rpx;
border-radius: 15rpx;
/* position: absolute;
bottom: 0; */
}
.btn_area {
width: 350rpx;
}
最后是Js文件
对于图片的上传,可以存在两种情况:1、第一次就上传了九张图片;2、第一次不够九张,第二次接着上传。所有我们需要对这个条件就行判断。
Page({
/**
* 页面的初始数据
*/
data: {
// 标题数
titleCount: 0,
// 详情数
contentCount: 0,
// 标题内容
title: '',
// 标题内容
content: '',
// 图片列表
images: [],
// 视频
video : '',
},
// 图片操作的具体函数
ImageOperator() {
wx.chooseImage({
count: 9,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: res => {
// 上传的图片数据
const imgList = res.tempFilePaths;
// 原始的图片数据
const imageList = this.data.images;
// 原来的图片数量
let imageLenght = imageList.length;
// 当前的图片数量
let nowLenght = imgList.length;
console.log(imageLenght);
if ( imageLenght == 9 ) {
console.log("数量已经有9张,请删除在添加...");
}
if ( imageLenght < 9 ) {
let images = [];
// 获取缺少的图片张数
let residue = 9 - imageLenght;
// 如果缺少的张数大于当前的的张数
if ( residue >= nowLenght ) {
// 直接将两个数组合并为一个
images = imageList.concat(imgList);
}else {
// 否则截取当前的数组一部分
images = imageList.concat(imgList.slice(0, residue));
}
this.setData({
images
})
}
}
})
},
// 标题操作
handleTitleInput(event) {
let inputValue = event.detail.value;
// 确保标题不存在空格
if(inputValue.lastIndexOf(" ") != -1){
inputValue = inputValue.substring(0, inputValue.lastIndexOf(" "));
}
let titleCount = inputValue.length;
if(titleCount <= 25){
this.setData({
titleCount: titleCount ,
title: inputValue
})
}
},
// 内容操作
handleContentInput(event) {
let textareaValue = event.detail.value;
let contentCount = textareaValue.length;
if(contentCount <= 255){
this.setData({
contentCount: contentCount,
content: textareaValue
})
}
},
// 图片获取
chooseImage() {
if (this.data.images.length == 0) {
wx.showToast({
title: '视频和图片只能选择上传一种类型!',
icon: 'none',
duration: 2000,
success: res => {
this.ImageOperator()
}
})
}else {
this.ImageOperator()
}
},
// 删除图片
deleteImage(event) {
//获取数据绑定的data-id的数据
const nowIndex = event.currentTarget.dataset.id;
let images = this.data.images;
images.splice(nowIndex, 1);
this.setData({
images
})
},
// 预览图片
previewIamge(event) {
const nowIndex = event.currentTarget.dataset.id;
const images = this.data.images;
wx.previewImage({
current: images[nowIndex], //当前预览的图片
urls: images, //所有要预览的图片
})
},
// 上传视频
chooseVideo() {
// 弹层
wx.showToast({
title: '视频和图片只能选择上传一种类型!',
icon: 'none',
duration: 2000,
success: res => {
wx.chooseVideo({
sourceType: ['album', 'camera'],
compressed: true,
maxDuration: 10,
camera: 'back',
success: res => {
console.log(res);
const video = res.tempFilePath;
this.setData({video})
}
})
}
})
},
// 删除视频
videoDelete(){
wx.showModal({
title: '警告',
content: '确定要删除该视频吗',
success: res => {
if (res.confirm) {
this.setData({
video: ''
})
}
}
})
},
// 表单提交事件
submitClick() {
},
// 重置表单
resetClick() {
wx.showModal({
title: '警告',
content: '重置表单将需要重新上传数据',
success: res => {
if (res.confirm) {
this.setData({
titleCount: 0,
contentCount: 0,
title: '',
content: '',
images: [],
video : ''
})
}
}
})
}
})
这样就实现了,代码还有很多需要优化的地方,如果需要请自行斟酌使用!