(2021.9.1 已终止)
一、主要内容及功能
- 推送航天信息内容
- 小程序前后台交互
- 播放视频
- 收藏及浏览历史
二、效果及主要实现代码
- 浏览页
- 点击过渡动画
- 详情页
-
收藏文章
说明:如果未点击收藏则仅为历史记录(key前加0标记)。 -
点赞
-
- 浏览页代码
- wxml
<!--pages/viewer/index.wxml--> <!-- 加载界面 --> <view class="loading" hidden="{{isLoaded}}"> <image src="/imgs/satellite.png" width="widthFix"></image> <view class="slogan">我们的征程是星辰大海</view> </view> <view> <!-- 轮播图 --> <view> <swiper indicator-dots circular autoplay indicator-active-color="#666ccc" interval='4000' duration='500'> <swiper-item wx:for="{{swiperPic}}" wx:key='id'> <image mode="widthFix" src="{{url}}{{item}}"></image> </swiper-item> </swiper> </view> <!-- 列表 --> <view class="list"> <view hover-class="click" wx:for='{{list}}' wx:key='id' bindtap="gotoDetails" data-val='{{item}}'> <view class="listItem"> <text>{{item.tit}}</text> </view> <view class='plus'>{{item.type}} {{item.date}}</view> </view> </view> </view>
- js
// pages/viewer/index.js const app = getApp(); Page({ /** * 页面的初始数据 */ data: { url: app.globalData.url }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var url = this.data.url; // 列表 wx:wx.request({ url: url+'list.php', complete: (res) => { this.setData({list: res.data}) // console.log(res.data) } }) // 轮播图 wx:wx.request({ url: url+'swiper.php', complete: (res) => { this.setData({swiperPic: res.data.swiper}) // console.log(this.data.swiperPic) } }) }, // 前往详情页 gotoDetails: function(choice) { this.setData({isLoaded: false}) // 传递数组 wx.navigateTo({ url: '/pages/details/details?obj='+JSON.stringify(choice.currentTarget.dataset.val) }) // console.log(choice.currentTarget.dataset.val) }, /** * 生命周期函数--监听页面显示 从details界面返回时,需重置加载 */ onShow: function () { this.setData({isLoaded: true}) var url = this.data.url; // 列表 wx:wx.request({ url: url+'list.php', complete: (res) => { this.setData({list: res.data}) // console.log(res.data) } }) } })
- 详情页主要代码
- wxml
<!--pages/details/details.wxml--> <view class="contain"> <!-- 第二个容器 --> <view class="contain2"> <!-- 标题 --> <view class='tit'>{{item.tit}}</view> <!-- 判断是否有图片 --> <view wx:if="{{item.pic}}"> <view class='source'>来源:国家航天局</view> <image src="{{url}}{{item.pic}}" mode="widthFix"></image> </view> <!-- 判断是否有视频 --> <view wx:elif="{{item.video}}"> <view class='source'>来源:央视网</view> <video id="Video" src="{{url}}{{item.video}}" controls></video> </view> <!-- 文字内容 --> <view class="content">{{item.content}}</view> <!-- 日期 --> <view class='data'>时间:{{item.date}}</view> </view> <!-- 底部点赞 和 收藏样式 --> <view class="bottom"> <block> <button hover-class="none" wx:if='{{collected}}' bindtap="cancelFavorites" style="width:150rpx;height:140rpx;right:100rpx;"><image src="/imgs/collection2.png" ></image>收藏</button> <button hover-class="none" wx:else bindtap="addFavorites" style="width:150rpx;height:140rpx;right:100rpx;"><image src="/imgs/collection1.png"></image>收藏</button> </block> <block> <button hover-class="none" style="width:150rpx;height:150rpx;right:0rpx;" bindtap="liker"> <image wx:if="{{liked}}" src="/imgs/like1.png"></image> <image wx:else src="/imgs/like.png"></image>{{liker}}</button> </block> </view> </view>
- js
// pages/details/details.js const app = getApp(); Page({ /** * 页面的初始数据 */ data: { url: app.globalData.url, collected: false, liked: false }, // 添加收藏,重置浏览历史记录(去0) addFavorites: function() { wx.removeStorageSync("0"+this.data.item.tit) wx.setStorageSync(this.data.item.tit, this.data.item) this.setData({collected: true}) }, // 取消收藏,重置浏览历史记录(加0) cancelFavorites: function() { wx.setStorageSync("0"+this.data.item.tit, this.data.item) wx.removeStorageSync(this.data.item.tit) this.setData({collected: false}) }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var obj = JSON.parse(options.obj) // console.log(obj) this.setData({item: obj}) var article = wx.getStorageSync(obj.tit) if (article != "") { this.setData({ collected: true }) } else { // 浏览历史 wx.setStorageSync("0"+this.data.item.tit, this.data.item) } var liker = this.data.item.liker this.setData({liker: liker}) }, // 点赞功能 liker:function() { var liker = Number(this.data.liker) + 1 wx:wx.request({ url: this.data.url+'liker.php?get='+this.data.item.tit, complete: (res) => { this.setData({ liked: true, liker: liker+"" }) } }) } })
- wxss
/* pages/details/details.wxss */ .contain, .bottom { width: 100%; } .contain2 { margin: 20rpx; } image, video { width: 100%; } .tit { text-align: center; margin: 40rpx; font-size: 50rpx; } .content { text-indent: 2em; } .data { text-align: right; margin-top: 20rpx; } .source { text-align: center; color: #aeaeae; } .bottom { /* display: flex; flex-direction: row; */ width: 100%; margin-top: 40rpx; } .bottom image { width: 50rpx; height: 50rpx; } button { background: none; position: absolute; }
- 个人页
-
流星动画效果
-
登录
-
足迹(浏览历史页)
-
收藏页
-
个人页主要代码
- wxml
<!--pages/user/index.wxml--> <!-- 加载界面 --> <view class="loading" hidden="{{isLoaded}}"> <image src="/imgs/satellite.png" width="widthFix"></image> <view class="slogan">我们的征程是星辰大海</view> </view> <!-- 顶部样式:点击头像登录,显示头像和昵称 --> <view> <!-- 流星动画效果 --> <view class="star"><image src="/imgs/star.png"></image></view> <view class="topBarBackground"></view> <view class="topBar"> <button class="btn" open-type='getUserInfo' bindgetuserinfo='getInfo' style="width:200rpx;height:200rpx" disabled="{{isLogin}}"> <image src="{{avatar}}" mode="widthFix" class="avatar" style="border-radius:{{avatar_radius}}"></image> </button> <text>{{nickName}}</text> </view> <!-- 登录后导航栏 及 退出键 --> <view wx:if="{{isLogin}}" class="navContain"> <!-- 中部导航栏 --> <view class="midNav"> <view hover-class="click"> <image src="/imgs/num.png" mode="widthFix"></image> <text>我的行星编号: {{planet.name}}</text> </view> <view hover-class="click" bindtap="planetInfo" data-val="{{num}}"> <image src="/imgs/log.png" mode="widthFix"></image> <text>行星信息</text> </view> </view> <!-- 底部导航栏 --> <view class="bottomNav"> <navigator wx:for="{{botNav}}" url="{{item.path}}" wx:key='id' bindtap="introduction"> <image src="{{item.img}}"></image> <text>{{item.name}}</text> </navigator> </view> </view> </view>
- js
// pages/user/index.js var util = require("../../utils/util.js"); Page({ /** * 页面的初始数据 */ data: { avatar: '/imgs/avatar.png', nickName: '点击头像登录', avatar_radius: '0%', isLogin: false, botNav: [ { path: "/pages/list/list?type=0", img: "/imgs/history.png", name: "足迹", }, { path: "/pages/list/list?type=1", img: "/imgs/collection.png", name: "收藏", }, { path: "/pages/introduction/introduction", img: "/imgs/about.png", name: "关于", } ], planet: [] }, /** * 获取用户信息 及 生成行星编号 */ getInfo: function(e) { let info = e.detail.userInfo; this.setData({ nickName: "你好," + info.nickName, avatar: info.avatarUrl, avatar_radius: '100%', isLogin: true, planet: util.getPlanetInfo() }) // console.log(info) // console.log(this.data.planet) }, /** * 点击 “关于”导航栏 跳转介绍界面 */ introduction: function() { this.setData({isLoaded:false}) }, /** * 行星信息弹窗 */ planetInfo: function() { var planet = this.data.planet; // console.log(planet) wx.showModal({ title: planet.name, content: "Discovered in: "+planet.discovered+"\nMass: "+planet.mass+"\nOrbital Period: "+planet.OrbitalPeriod+"\n Radius: "+planet.Radius, showCancel: false }) }, /** * 生命周期函数--监听页面显示 从introduction界面返回时,需重置加载 */ onShow: function () { this.setData({isLoaded: true}) } })
- wxss
/* pages/user/index.wxss */ .topBar, .midNav, .midNav view, navigator{ display: flex; align-items: center; } /* 高斯模糊 */ .topBarBackground { background: linear-gradient(#003472,#0388f6,#fff); position: absolute; width: 100%; height: 500rpx; left: 0; top: 0; z-index: -2; filter: blur(15rpx); transform: scale(1.2); } /* 顶部样式 */ .topBar { height: 500rpx; width: 100%; flex-direction: column; justify-content: center; color: #fff; font-weight: 800; font-size: large; } /* 头像 */ .avatar { width: 100%; height: 100%; } /* 登录按键 */ .btn { background: none; padding: 10rpx; border-radius: 50%; } .btn:active { background: #eee; } /* 流星动画 */ .star { z-index: -1; width: 50rpx; height: 50rpx; margin-top: 25rpx; position: absolute; animation: y 6s infinite ease-in-out; } .star image { z-index: 2; width: 50rpx; height: 50rpx; animation: x 6s infinite ease-in-out; } @keyframes y { to{transform: translateY(90rpx);} } @keyframes x { 0% {opacity: 0;} 60% {opacity: 1;} 100% {opacity: 0;} to {transform: translateX(500rpx);} } /* 中部导航栏 */ .midNav, .midNav view { border-radius: 10rpx; } .midNav { background: #fff; height: 140rpx; box-shadow: 0px 3px 10px 1px #e7e7e7; margin-top: -80rpx; justify-content: space-around; } .midNav view { width: 50%; padding: 5%; height: 50%; } .midNav image { width: 70rpx; height: 70rpx; } .midNav text { margin-left: 10rpx; } /* 底部导航栏 */ .midNav, .bottomNav { width: 90%; margin-left: 5%; margin-right: 5%; } .bottomNav { margin-top: 50rpx; box-shadow: 0px 3px 10px 1px #e7e7e7; } navigator { line-height: 60rpx; background: #fff; border-bottom: 1px solid #eee; padding: 15rpx; } navigator image { width: 50rpx; height: 50rpx; margin-right: 30rpx; }
-
收藏及足迹页主要代码
- wxml
<!--pages/list/list.wxml--> <!-- 加载界面 --> <view class="loading" hidden="{{isLoaded}}"> <image src="/imgs/satellite.png" width="widthFix"></image> <view class="slogan">我们的征程是星辰大海</view> </view> <view class="list"> <view hover-class="click" wx:for='{{list}}' wx:key='id' bindtap="gotoDetails" data-val='{{item}}'> <view class="listItem"> <text>{{item.tit}}</text> </view> <view class='plus'>{{item.type}} {{item.date}}</view> </view> </view>
- js
// pages/list/list.js Page({ /** * 页面的初始数据 */ data: { type: "0" }, /** * 生命周期函数--监听页面加载 */ onLoad: function (options) { var type = options.type this.showList(type) }, onShow: function(options) { var type = options.type this.showList(type) }, // 生成列表 showList: function(type) { let barTit = "浏览历史" // 获取模式 this.setData({type: type}) let info = wx.getStorageInfoSync() let keys = info.keys let list = [] if (type == 1) { barTit = "我的收藏" } // 获取收藏 for (var i = 1; i < keys.length; i++) { let obj = wx.getStorageSync(keys[i]) // 略过属于收藏的浏览历史 if (type == 1 && keys[i].substring(0,1) == "0") { continue; } list.push(obj) } this.setData({list: list}) //设置标题栏 wx.setNavigationBarTitle({ title: barTit }); }, // 前往详情页 gotoDetails: function(choice) { this.setData({isLoaded: false}) // 传递数组 wx.navigateTo({ url: '/pages/details/details?obj='+JSON.stringify(choice.currentTarget.dataset.val) }) // console.log(choice.currentTarget.dataset.val) }, /** * 生命周期函数--监听页面显示 */ onShow: function () { this.setData({isLoaded: true}) } })
三、全局设置
- app.wxss
/**app.wxss**/
page {
background-color: #f4f4f4;
}
.container {
height: 100%;
}
/* 轮播图 */
swiper, swiper image {
height: 400rpx;
width: 100%;
}
/* 模块点击效果: 背景灰度 */
.click {
background: #eee;
}
/* 加载效果 */
.loading {
display: flex;
justify-content: center;
align-items: center;
z-index: 2;
width: 100%;
height: 100vh;
flex-direction: column;
}
.loading image {
width: 50rpx;
height: 50rpx;
animation: rotate 2s linear infinite;
margin-bottom: 50rpx;
}
@keyframes rotate {
from {transform: rotate(0deg)} to {transform: rotate(360deg)}
}
/* 字体样式 */
.slogan, .nav, .tit, .list {
font-family: "华文新魏";
}
/* 列表 */
.list {
margin: 20rpx;
background: #fff;
box-shadow: 0px 3px 10px 1px #e7e7e7;
}
.listItem {
height: 50rpx;
padding: 10rpx;
display: flex;
align-items: center;
}
/* 列表中备注类型和日期样式 */
.plus {
height: 20rpx;
width: 100%;
color: #aeaeae;
border-bottom: 1px solid #eee;
text-align: right;
font-size: 20rpx;
}
- app.json
{
"pages":[
"pages/index/index",
"pages/viewer/index",
"pages/user/index",
"pages/introduction/introduction",
"pages/details/details",
"pages/list/list",
"pages/logs/logs"
],
"window":{
"backgroundTextStyle":"light",
"navigationBarBackgroundColor": "#003472",
"navigationBarTitleText": "观星者",
"navigationBarTextStyle":"white"
},
"tabBar": {
"list": [{
"pagePath": "pages/index/index",
"text": "主页",
"iconPath": "/imgs/home1.png",
"selectedIconPath": "/imgs/home2.png"
},{
"pagePath": "pages/viewer/index",
"text": "浏览",
"iconPath": "imgs/viewer1.png",
"selectedIconPath": "/imgs/viewer2.png"
},{
"pagePath": "pages/user/index",
"text": "我的",
"iconPath": "imgs/user1.png",
"selectedIconPath": "imgs/user2.png"
}]
},
"style": "v2",
"sitemapLocation": "sitemap.json"
}
- app.js
//app.js
App({
onLaunch: function () {
// 展示本地存储能力
var logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
// 获取用户信息
wx.getSetting({
success: res => {
if (res.authSetting['scope.userInfo']) {
// 已经授权,可以直接调用 getUserInfo 获取头像昵称,不会弹框
wx.getUserInfo({
success: res => {
// 可以将 res 发送给后台解码出 unionId
this.globalData.userInfo = res.userInfo
// 由于 getUserInfo 是网络请求,可能会在 Page.onLoad 之后才返回
// 所以此处加入 callback 以防止这种情况
if (this.userInfoReadyCallback) {
this.userInfoReadyCallback(res)
}
}
})
}
}
})
},
globalData: {
userInfo: null,
// 服务端后台地址
url: "",
arcticl: ""
}
})