首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >最后一个页面:构建电影详情页面

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

作者头像
端碗吹水
发布2020-09-23 12:47:37
5910
发布2020-09-23 12:47:37
举报

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

所有的代码编写完成后,运行效果如下:

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

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

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-02-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 电影搜索页面构建
  • 编写电影详情页面
相关产品与服务
云开发 CloudBase
云开发(Tencent CloudBase,TCB)是腾讯云提供的云原生一体化开发环境和工具平台,为200万+企业和开发者提供高可用、自动弹性扩缩的后端云服务,可用于云端一体化开发多种端应用(小程序、公众号、Web 应用等),避免了应用开发过程中繁琐的服务器搭建及运维,开发者可以专注于业务逻辑的实现,开发门槛更低,效率更高。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档