最後一個頁面:構建電影詳情頁面
筆記日期:2018-02-02
電影搜索頁面構建
我們想要有一個搜索電影的功能,需要在電影資訊頁面頂部編寫一個搜索框,當我們的鼠標焦點位於該搜索框時,就會顯示出電影搜索頁面,而點擊搜索框的關閉圖標時,需要隱藏電影搜索頁面。所以這個電影搜索頁面不是一個單獨的頁面文件,而是用隱/顯的方式來做。
搜索框效果圖:
要實現這個搜索框,我們首先需要一個表單組件:input,該組件的官方說明文檔地址如下:
https://mp.weixin.qq.com/debug/wxadoc/dev/component/input.html
然後還需要用到icon組件,該組件的官方說明文檔地址如下:
https://mp.weixin.qq.com/debug/wxadoc/dev/component/icon.html
1.編輯movies.wxml代碼如下:
<import src="movie-list/movie-list-template.wxml" /> <import src="movie-grid/movie-grid-template.wxml" /> <view class="search"> <icon type=‘search‘ class=‘search-img‘ size=‘13‘ color=‘#405f80‘></icon> <input type=‘text‘ placeholder=‘{{placeholder}}‘ placeholder-class=‘placeholder‘ bindfocus=‘onBindFocus‘ bindconfirm=‘onBindFirm‘ value="{{cleanValue}}" /> <image wx:if=‘{{searchPanelShow}}‘ src=‘/images/icon/xx.png‘ class=‘xx-img‘ catchtap=‘onCancelImgTap‘></image> </view> <view class=‘container‘ wx:if=‘{{containerShow}}‘> <view> <template is="movieListTemplate" data=‘{{...inTheaters}}‘ /> </view> <view> <template is="movieListTemplate" data=‘{{...comingSoon}}‘ /> </view> <view> <template is="movieListTemplate" data=‘{{...top250}}‘ /> </view> </view> <view class=‘search-panel‘ wx:if=‘{{searchPanelShow}}‘> <template is=‘movieGridTemplate‘ data=‘{{...searchResult}}‘ /> </view>
2.編輯movies.wxss代碼如下:
@import "movie-list/movie-list-template.wxss"; @import "movie-grid/movie-grid-template.wxss"; .container{ background-color: #f2f2f2; } .container view{ margin-bottom: 30rpx; } .search{ background-color: #f2f2f2; height: 80rpx; width: 100%; display: flex; flex-direction: row; } .search-img{ margin: auto 0 auto 20rpx; } .search input{ height: 100%; width: 600rpx; margin-left: 20px; font-size: 28rpx; } .placeholder{ font-size: 14px; color: #d1d1d1; margin-left: 20rpx; } .search-panel{ position: absolute; top: 80rpx; } .xx-img{ height: 30rpx; width: 30rpx; margin: auto 0 auto 10rpx; }
3.編輯movies.js代碼如下:
var app = getApp();
var util = require(‘../../utils/util.js‘);
Page({
data: {
// 需要有一個初始值
inTheaters: {},
comingSoon: {},
top250: {},
searchResult: {},
containerShow: true,
searchPanelShow: false,
},
onLoad: function (event) {
var inTheatersUrl = app.globalData.doubanBase + ‘/v2/movie/in_theaters?start=0&count=3‘;
var comingSoonUrl = app.globalData.doubanBase + ‘/v2/movie/coming_soon?start=0&count=3‘;
var top250Url = app.globalData.doubanBase + ‘/v2/movie/top250?start=0&count=3‘;
this.getMovieListData(inTheatersUrl, "inTheaters", "正在熱映");
this.getMovieListData(comingSoonUrl, "comingSoon", "即將上映");
this.getMovieListData(top250Url, "top250", "豆瓣電影Top250");
},
// 跳轉到更多電影頁面
onMoreTap: function (event) {
// 獲得電影類型
var category = event.currentTarget.dataset.category;
wx.navigateTo({
// 通過參數把電影類型傳遞過去
url: ‘more-movie/more-movie?category=‘ + category,
});
},
// 請求API的數據
getMovieListData: function (url, settedkey, categoryTitle) {
var that = this;
// 通過reques來發送請求
wx.request({
url: url,
method: ‘GET‘,
header: {
"Content-Type": "application/json"
},
success: function (res) {
that.processDoubanData(res.data, settedkey, categoryTitle);
},
fail: function () {
console.log("API請求失敗!請檢查網絡!");
}
});
},
// 關閉電影搜索頁面
onCancelImgTap: function (event) {
this.setData({
containerShow: true,
searchPanelShow: false,
searchResult: {},
cleanValue: ‘‘,
});
},
// 顯示電影搜索頁面
onBindFocus: function (event) {
this.setData({
containerShow: false,
searchPanelShow: true,
});
},
// 搜索電影數據
onBindFirm: function (event) {
var text = event.detail.value;
var searchUrl = app.globalData.doubanBase + "/v2/movie/search?q=" + text;
this.getMovieListData(searchUrl, "searchResult", "");
},
// 處理API返回的數據
processDoubanData: function (moviesDouban, settedkey, categoryTitle) {
// 存儲處理完的數據
var movies = [];
for (var idx in moviesDouban.subjects) {
var subject = moviesDouban.subjects[idx];
var title = subject.title;
// 處理標題過長
if (title.length >= 6) {
title = title.substring(0, 6) + "...";
}
var temp = {
stars: util.convertToStarsArray(subject.rating.stars),
title: title,
average: subject.rating.average,
coverageUrl: subject.images.large,
movieId: subject.id
};
movies.push(temp);
}
if (categoryTitle == ‘正在熱映‘) {
this.setData({
placeholder: movies[0][‘title‘]
});
}
// 動態賦值
var readyData = {};
readyData[settedkey] = {
categoryTitle: categoryTitle,
movies: movies
};
this.setData(readyData);
},
})
運行效果:
編寫電影詳情頁面
以上我們已經完成了大部分的頁面了,現在我們來完成最後一個影詳情頁面,我們希望在電影資訊頁面上點擊某一部電影時,要能跳轉到該電影的詳情頁面,所以這是一個新的頁面,我們首先要做的事情就是創建這個頁面的目錄及文件:
然後首先是在movie-template.wxml文件中加上一個點擊事件:
<import src=‘../stars/stars-template.wxml‘ />
<template name=‘movieTemplate‘>
<view class=‘movie-container‘ catchtap=‘onMovieTap‘ data-movieId=‘{{movieId}}‘ style=‘margin:0‘>
<image class=‘movie-img‘ src=‘{{coverageUrl}}‘></image>
<text class=‘movie-title‘>{{title}}</text>
<template is=‘starsTemplate‘ data="{{stars:stars, score: average}}" />
</view>
</template>
接著在movies.js文件中編寫一段跳轉頁面的邏輯代碼:
// 跳轉到電影詳情頁面
onMovieTap:function(event){
// 獲得電影的id
var movieId = event.currentTarget.dataset.movieid;
wx.navigateTo({
// 通過參數把電影的subject id傳遞過去
url: ‘movie-detail/movie-detail?id=‘ + movieId,
});
},
然後在movie-detail.js裏接收id參數,向API請求數據,把服務器返回的數據在控制臺中打印出來:
var app = getApp();
var util = require(‘../../../utils/util.js‘);
Page({
data: {
},
onLoad: function (options) {
var movieId = options.id;
var url = app.globalData.doubanBase + "/v2/movie/subject/" + movieId;
util.http(url, this.processDoubanData);
},
processDoubanData:function(data){
console.log(data)
},
})
確定能正常獲取到數據後,就可以開始處理數據了,主要的邏輯是做數據的篩選及判空容錯,編寫movie-detail.js代碼如下:
var app = getApp();
var util = require(‘../../../utils/util.js‘);
Page({
data: {
movie: {},
},
onLoad: function (options) {
var movieId = options.id;
var url = app.globalData.doubanBase + "/v2/movie/subject/" + movieId;
util.http(url, this.processDoubanData);
},
// 處理API返回的數據
processDoubanData: function (data) {
// 初始一些數據的默認值
var director = {
avatar: "",
name: "",
id: ""
}
// 處理可能會出現的空值
if (data.directors[0] != null) {
if (data.directors[0].avatars != null) {
director.avatar = data.directors[0].avatars.large;
}
director.name = data.directors[0].name;
director.id = data.directors[0].id;
}
// 填充數據
var movie = {
movieImg: data.images ? data.images.large : "", // 處理可能會出現的空值
country: data.countries[0],
title: data.title,
originalTitle: data.original_title,
wishCount: data.wish_count,
commentCount: data.comments_count,
year: data.year,
generes: data.genres.join("、"), // 把數組轉化成用 、分割的字符串
stars: util.convertToStarsArray(data.rating.stars),
score: data.rating.average,
director: director,
casts: util.convertToCastString(data.casts),
castsInfo: util.convertToCastInfos(data.casts),
summary: data.summary,
}
console.log(movie)
// 綁定數據
this.setData({
movie: movie
});
},
})
接著util.js代碼如下:
// 以上代碼略
// 把演員的名字用斜杠分割
function convertToCastString(casts) {
var castsjoin = "";
for (var idx in casts) {
castsjoin = castsjoin + casts[idx].name + "/";
}
return castsjoin.substring(0, castsjoin.length - 2);
}
// 處理演員的名稱與照片
function convertToCastInfos(casts) {
var castsArray = []
for (var idx in casts) {
var cast = {
img: casts[idx].avatars ? casts[idx].avatars.large : "", // 處理可能會出現的空值
name: casts[idx].name
}
castsArray.push(cast);
}
return castsArray;
}
module.exports = {
convertToStarsArray: convertToStarsArray,
http: http,
convertToCastString: convertToCastString,
convertToCastInfos: convertToCastInfos
}
然後編譯運行看看控制臺裏是否有正常打印出數據。
以上我們完成了數據獲取以及處理,現在我們就可以開始編寫頁面上的代碼了。首先編寫電影詳情頁面的骨架代碼,這個頁面的代碼還挺多的,不過並不復雜:
movie-detail.wxml骨架代碼:
<import src=‘../stars/stars-template.wxml‘ />
<view class=‘container‘>
<image class=‘head-img‘ src=‘{{movie.movieImg}}‘ mode=‘aspectFill‘ />
<view class=‘head-img-hover‘>
<text class=‘main-title‘>{{movie.title}}</text>
<text class=‘sub-title‘>{{movie.country + " . " + movie.year}}</text>
<view class=‘like‘>
<text class=‘highlight-font‘>
{{movie.wishCount}}
</text>
<text class=‘plain-font‘>
人喜歡
</text>
<text class=‘highlight-font‘>
{{movie.commentCount}}
</text>
<text class=‘plain-font‘>
條評論
</text>
</view>
</view>
<image class=‘movie-img‘ src=‘{{movie.movieImg}}‘ data-src="{{movie.movieImg}}" catchtap=‘viewMoviePostImg‘ />
<view class=‘summary‘>
<view class=‘original-title‘>
<text>{{movie.originalTitle}}</text>
</view>
<view class="flex-row">
<text class="mark">評分</text>
<template is="starsTemplate" data="{{stars:movie.stars, score:movie.score}}" />
</view>
<view class="flex-row">
<text class="mark">導演</text>
<text>{{movie.director.name}}</text>
</view>
<view class="flex-row">
<text class="mark">影人</text>
<text>{{movie.casts}}</text>
</view>
<view class="flex-row">
<text class="mark">類型</text>
<text>{{movie.generes}}</text>
</view>
</view>
<view class="hr"></view>
<view class="synopsis">
<text class="synopsis-font">劇情簡介</text>
<text class="summary-content">{{movie.summary}}</text>
</view>
<view class="hr"></view>
<view class="cast">
<text class="cast-font"> 影人</text>
<scroll-view class="cast-imgs" scroll-x="true" style="width:100%">
<block wx:for="{{movie.castsInfo}}" wx:for-item="item">
<view class="cast-container">
<image class="cast-img" src="{{item.img}}"></image>
<text class="cast-name">{{item.name}}</text>
</view>
</block>
</scroll-view>
</view>
</view>
movie-detail.wxss樣式代碼:
@import "../stars/stars-template.wxss";
.container {
display: flex;
flex-direction: column;
}
.head-img {
width: 100%;
height: 320rpx;
/* 圖片模糊效果 */
-webkit-filter: blur(20px);
}
.head-img-hover {
width: 100%;
height: 320rpx;
position: absolute;
top: 0;
left: 0;
display: flex;
flex-direction: column;
}
.main-title {
font-size: 19px;
color: #fff;
font-weight: bold;
margin-top: 50rpx;
margin-left: 40rpx;
letter-spacing: 2px;
}
.sub-title {
font-size: 28rpx;
color: #fff;
margin-left: 40rpx;
margin-top: 30rpx;
}
.like {
display: flex;
flex-direction: row;
margin-top: 30rpx;
margin-left: 40rpx;
}
.highlight-font {
color: #f21146;
font-size: 22rpx;
margin-right: 10rpx;
}
.plain-font {
color: #666;
font-size: 22rpx;
margin-right: 30rpx;
}
.movie-img {
height: 238rpx;
width: 175rpx;
position: absolute;
top: 160rpx;
right: 30rpx;
}
.summary {
margin-left: 40rpx;
margin-top: 40rpx;
color: #777;
}
.original-title {
color: #1f3463;
font-size: 24rpx;
font-weight: bold;
margin-bottom: 40rpx;
}
.flex-row {
display: flex;
flex-direction: row;
margin-bottom: 10rpx;
}
.mark {
margin-right: 30rpx;
white-space: nowrap;
color: #999;
}
.hr {
margin-top: 45rpx;
height: 1px;
width: 100%;
background-color: #d9d9d9;
}
.synopsis {
margin-left: 40rpx;
display: flex;
flex-direction: column;
margin-top: 50rpx;
}
.synopsis-font {
color: #999;
}
.summary-content {
margin-top: 20rpx;
margin-right: 40rpx;
line-height: 40rpx;
letter-spacing: 1px;
}
.cast {
margin-left: 40rpx;
display: flex;
flex-direction: column;
margin-top: 50rpx;
}
.cast-font {
color: #999;
margin-bottom: 40rpx;
}
.cast-container {
display: inline-flex;
flex-direction: column;
margin-bottom: 50rpx;
margin-right: 40rpx;
width: 170rpx;
text-align: center;
/* 正常換行 */
white-space: normal;
}
.cast-imgs {
/* 禁止自動換行 */
white-space: nowrap;
}
.cast-img {
width: 170rpx;
height: 210rpx;
}
.cast-name {
margin: 10rpx auto 0;
}
movie-detail.js裏增加以下代碼:
// 查看圖片
viewMoviePostImg: function (event) {
var src = event.currentTarget.dataset.src;
wx.previewImage({
current: src, // 當前顯示圖片的http鏈接
urls: [src], // 需要預覽的圖片的http鏈接
})
},
其中用到的image組件的官方說明文檔地址如下:
https://mp.weixin.qq.com/debug/wxadoc/dev/component/image.html
然後我們希望更多電影頁面中也能夠跳轉到電影詳情頁,所以需要在more-movie.js文件中增加以下代碼:
// 跳轉到電影詳情頁面
onMovieTap: function (event) {
// 獲得電影的id
var movieId = event.currentTarget.dataset.movieid;
wx.navigateTo({
// 通過參數把電影的subject id傳遞過去
url: ‘../movie-detail/movie-detail?id=‘ + movieId,
});
},
所有的代碼編寫完成後,運行效果如下:
到目前為止,整個小程序的開發就告一段落了,這個筆記的目的也只是為了記錄一下開發的過程,所以其中對細節沒有過多的介紹,不過基本上代碼也都註釋了,也是為了方便以後遇到類似的功能可以參考實現思路,畢竟像我這種代碼寫完就忘的人。
最後一個頁面:構建電影詳情頁面