温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

最后一个页面:构建电影详情页面

发布时间:2020-03-03 12:53:37 来源:网络 阅读:2029 作者:ZeroOne01 栏目:移动开发

笔记内容:最后一个页面:构建电影详情页面
笔记日期: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" >
      <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,
    });
  },

所有的代码编写完成后,运行效果如下:
最后一个页面:构建电影详情页面


到目前为止,整个小程序的开发就告一段落了,这个笔记的目的也只是为了记录一下开发的过程,所以其中对细节没有过多的介绍,不过基本上代码也都注释了,也是为了方便以后遇到类似的功能可以参考实现思路,毕竟像我这种代码写完就忘的人。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI