• 小程序项目文字与电影(二)


    一,电影页面功能

     功能分析,1.点击搜索关键字,搜索电影

    2.点击更多按钮,跳转到更多电影页面

    3.点击电影图片,跳转到电影详情页

    逻辑分析,1.在movies页面分别发送三个请求,获取正在上映的,不久上映的,top250的数据,传递给电影列表movie-list子组件

    2.从lin-ui映入搜索组件l-search-bar, 

     3.点击更多,跳转到更多页面

    4.引入movie-list组件

    pages-->movies->movies

    movies.wxml

    在movie-lilst设置组件外链样式类

    <l-search-bar bind:lincancel="onSearchCancel" bind:linconfirm="onConfirm" l-class="ex-search-bar" placeholder="盗梦空间、你的名字"/>
    
    <view wx:if="{{!searchResult}}">
    电影列表 <movie-list data-type="in_theaters" bind:tap="onGotoMore" movies="{{inTheaters}}" title="正在热映" f-class="movie-list" /> <movie-list data-type="coming_soon" bind:tap="onGotoMore" movies="{{comingSoon}}" title="即将上映" f-class="movie-list" /> <movie-list data-type="top250" bind:tap="onGotoMore" movies="{{top250}}" title="豆瓣Top250" f-class="movie-list" /> </view> <!-- 搜索的结构 ,默认遍历每项为item--> <view class="search-container" wx:else> <block wx:for="{{searchData}}" wx:key="index"> <movie class="movie" movie="{{item}}" /> </block> </view>

    movies.wxss

    /* pages/movies/movies.wxss */
    //movie-list组件的外链样式 .movie-list{ margin-bottom: 30rpx; /* background-color: teal !important; */ } //组件外链样式 .ex-search-bar{ height: 90rpx !important; } .search-container{ display: flex; flex-direction: row;
    //换行,开启flex,不会自动换行 flex
    -wrap: wrap; padding: 30rpx 28rpx; justify-content: space-between; } /* 解决两端对齐的bug 每个电影图像宽200rpx*/ .search-container::after{ content:''; 200rpx; } page{ background-color: #f2f2f2; /* background-color: teal; */ }

    movies.js, 从app.js中引入全局变量app.gBaseUrl,

    ongotomore函数,跳转到更多页面,把电影类型参数传递到more-movie页面
    // pages/movies/movies.js
    
    const app = getApp()
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        // 正在上映数据
        inTheaters:[],
        // 不就上映数据
        comingSoon:[],
        // top250数据
        top250:[],
        // 搜索状态,影响结构
        searchResult:false,
        // 搜索后的数据
        searchData:[]
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        // 不可用async, await,默认get请求,类型in_theaters(正在上映)
        wx.request({
          url: app.gBaseUrl + 'in_theaters',
          // 请求参数,第0条开始加载,三条数据,问号?后的参数
          data:{
            start:0,
            count:3
          },
          // 箭头函数,this指向
          success:(res)=>{
            this.setData({
              inTheaters:res.data.subjects
            })
          }
        })   
      
        wx.request({
          // 类型coming_soon(不久上映)
          url: app.gBaseUrl + 'coming_soon',
          data:{
            start:0,
            count:3
          },
          success:(res)=>{
            this.setData({
              comingSoon:res.data.subjects
            })
          }
        })
        wx.request({
          // 类型top250(top250)
          url: app.gBaseUrl + 'top250',
          data:{
            start:0,
            count:3
          },
          success:(res)=>{
            this.setData({
              top250:res.data.subjects
            })
          }
        })
      },
    
      // 去更多电影页面
      onGotoMore(event){
        console.log(event)
        // 获取自定义属性,作为参数
        const type = event.currentTarget.dataset.type
        wx.navigateTo({
          url: '/pages/more-movie/more-movie?type=' + type,
        })
      },
    
      // 真实机型输入框点击确定触发,小程序模拟器enter键触发,kin-ui的事件,event.detail.value可获取到输入字
      onConfirm(event){
        // 正在搜索
        this.setData({
          searchResult:true
        })
        wx.request({
          url: app.gBaseUrl + 'search',
          // 查询参数,?后的参数
          data:{
            q:event.detail.value
          },
          success:(res)=>{
            this.setData({
              searchData:res.data.subjects
            })
          },
        })
      },
    
      // 取消搜索触发,
      onSearchCancel(event){
        this.setData({
          searchResult:false
        })
      },
    
    
    })

    注册movies-list子组件,movies.json

    {
      "usingComponents": {
        "movie-list":"/components/movie-list/index",
        "l-search-bar":"/miniprogram_npm/lin-ui/search-bar/index"
      },
      "navigationBarTitleText":"光与影"
    }

    部分电影数据

    {
    "count": 20,
    "start": 0,
    "subjects": [
    {
        "casts": [
            {
                "avatars": {
                    "large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p230.jpg"
                },
                "name": "弗兰克·德拉邦特"
            },
            {
                "avatars": {
                    "large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p17525.jpg"
                },
                "name": "蒂姆·罗宾斯"
            },
            {
                "avatars": {
                    "large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p34642.jpg"
                },
                "name": "摩根·弗里曼"
            }
        ],
        "comments_count": 222527,
        "countries": [
            "美国"
        ],
        "directors": [
            {
                "avatars": {
                    "large": null
                },
                "name": "弗兰克·德拉邦特"
            }
        ],
        "genres": [
            "剧情",
            "犯罪"
        ],
        "id": 3,
        "images": {
            "large": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.jpg"
        },
        "original_title": "肖申克的救赎 The Shawshank Redemption",
        "rating": {
            "average": 9.6,
            "max": 10,
            "min": 0,
            "stars": "50"
        },
        "reviews_count": 5794,
        "summary": "",
        "title": "肖申克的救赎 The Shawshank Redemption",
        "warning": "数据来源于网络整理,仅供学习,禁止他用。如有侵权请联系公众号:小楼昨夜又秋风。我将及时删除。",
        "wish_count": 98814,
        "year": 1994
    }

    引入movie-list组件,电影列表 

    components--> movie-llist-->movie-llist

    <view class="container f-class">
      <view class="title-container">
        <text>{{title}}</text>
        <text class="more-text">更多 ></text>
      </view>
      <view class="movie-container">
        <block wx:for="{{movies}}" wx:key="index">
          <movie movie="{{item}}" />
        </block>
      </view>
    </view>
    /* components/movie-list/index.wxss */
    
    .container{
      padding: 36rpx 36rpx;
      background-color: #ffffff;
    }
    
    .title-container{
      display: flex;
      flex-direction: row;
      justify-content: space-between;
      margin-bottom: 28rpx;
    }
    
    .movie-container{
      display: flex;
      flex-direction: row;
      justify-content: space-between;
    }
    
    .more-text{
      color: #1f4ba5;
    }

    movie-lilst.js

    // components/movie-list/index.js
    Component({
      /**
       * 组件的属性列表
       */
      // 设置组件外链样式类
      externalClasses:['f-class'],
    
      properties: {
        title:String,
        movies:Array
      },
    
      /**
       * 组件的初始数据
       */
      data: {
    
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
    
      }
    })

    注册movie组件

    movie-list.json

    {
      "component": true,
      "usingComponents": {
        "movie": "/components/movie/index"
      }
    }

    引入movie组件,电影卡片

    components--> movie-->movie

    <view catch:tap="onGoToDetail" class="container">
        <image class="poster" src="{{movie.images.large}}"></image>
        <text class="title">{{movie.title}}</text>
        <view class="rate-container">
        <l-rate disabled="{{true}}" size="22" score="{{movie.rating.stars/10}}" />
    
        <text class="score">{{movie.rating.average}}</text>
        </view>
    </view>
    .container{
      display: flex;
      flex-direction: column;
       200rpx;
    }
    
    .poster{
       100%;
      height: 270rpx;
      margin-bottom: 22rpx;
    }
    
    .title{
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
      word-break: break-all;
    }
    
    .rate-container{
      margin-top:6rpx;
      display: flex;
      flex-direction: row;
      /* 基线对齐 */
      align-items: baseline;
    }
    
    .score{
      margin-left:20rpx;
      font-size:24rpx;
    }

    movie.js

    点击电影卡片,跳转到电影详情页面,携带id参数

    // components/movie/index.js
    Component({
      /**
       * 组件的属性列表
       */
    
    
      properties: {
        movie:Object
      },
    
      /**
       * 组件的初始数据
       */
      data: {
    
      },
    
      /**
       * 组件的方法列表
       */
      methods: {
        onGoToDetail(event){
          // console.log(this.properties.movie)
          const mid = this.properties.movie.id
          wx.navigateTo({
            url: '/pages/movie-detail/movie-detail?mid=' + mid
          })
        }
      }
    })

    跳转到更多电影页面

    pages-->more-movie-->more-movie

    <view class="container">
        <block wx:for="{{movies}}" wx:key="index">
            <movie class="movie" movie="{{item}}" />
        </block>
    </view>
    /* pages/more-movie/more-movie.wxss */
    
    .container{
      display: flex;
      flex-direction: row;
      /* 换行,用flex布局不会自动换行 */
      flex-wrap: wrap;
      padding: 30rpx 28rpx;
      justify-content: space-between;
    }
    
    .movie{
      margin-bottom: 30rpx;
    }

    more-movie.js

    1.触顶下拉加载数据动画,要在json文件中引入enablePullDownRefresh属性,然后在函数中,调用小程序的方法wx.showNavigationBarLoading()

    2.不同类型的更多电影,顶部标题不一样,需要在onready中动态设置,调用小程序的 wx.setNavigationBarTitle函数
     
    3.触底上拉一次,加载12条数据,是个追加过程,每次下拉,还有个动态加载状态,小程序调用wx.hideNavigationBarLoading()函数
     
     
    // pages/more-movie/more-movie.js
    const app = getApp()
    
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        movies:[],
        _type:''
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        // 获取自定义type属性,作为请求路劲
        const type = options.type
        this.data._type = type
        wx.request({
          url: app.gBaseUrl + type,
          // 从第0条开始加载,请求12条数据
          data:{
            start:0,
            count:12
          },
          success:(res)=>{
            console.log(res)
            this.setData({
              movies:res.data.subjects
            })
          }
        }) 
      },
    
      /**
       * 生命周期函数--监听页面初次渲染完成
       */
      onReady: function () {
        let title = '电影'
        switch(this.data._type){
          case 'in_theaters':
            title='正在热映'
            break
          case 'coming_soon':
            title = '即将上映'
            break
          case 'top250':
            title = '豆瓣Top250'
            break
        }
        // 动态设置顶部标题
        wx.setNavigationBarTitle({
          title: title,
        })
      },
    
      /**
       * 生命周期函数--监听页面显示
       */
      onShow: function () {
    
      },
    
      /**
       * 生命周期函数--监听页面隐藏
       */
      onHide: function () {
       
      },
    
      /**
       * 生命周期函数--监听页面卸载
       */
      onUnload: function () {
    
      },
    
      /**
       * 页面相关事件处理函数--监听用户下拉动作
       */
      onPullDownRefresh: function () {
        wx.request({
          url: app.gBaseUrl + this.data._type,
          // 页面下拉,获取最新的12条数据
          data:{
            start:0,
            count:12,
          },
          success:(res)=>{
            this.setData({
              movies:res.data.subjects
            })
            // 下拉效果停止
            wx.stopPullDownRefresh()
          }
        })
      },
    
      /**
       * 页面上拉触底事件的处理函数
       */
      onReachBottom: function () {
        // [1,2,3...... 12,13,]
        // [0,1,2....11] + [12,13....23] + [24...35] + [36...47]
    //每次上拉加载出来加载动画
    wx.showNavigationBarLoading() wx.request({ url: app.gBaseUrl + this.data._type, // 从每次请求数据的最后一条开始加载,12条数据 data:{ start: this.data.movies.length, count:12 }, success:(res)=>{ console.log(res) this.setData({ // 数组追加合并 movies:this.data.movies.concat(res.data.subjects) }) // 每次追加数据后,顶部添加加载转圈效果 wx.hideNavigationBarLoading() } }) }, /** * 用户点击右上角分享 */ onShareAppMessage: function () { } })

    json文件

    {
      "usingComponents": {
        "movie":"/components/movie/index"
      },
      "enablePullDownRefresh":true
    }

    跳转到电影详情页面

    实现影人中图片左右滚动效果,引入小程序组件scroll-view组件,但是会放flex布局失效,需要添加enable-flex 让其生效,并且会是容器留有很大高度,给容器高度重新设置下

    图片的mode模式,给image标签添加mode="aspectFill"缩放模式,官网https://developers.weixin.qq.com/miniprogram/dev/component/image.html

    给图片添加模糊效果,-webkit-filter:blur(20px); 

     

    pages-->movie-detail-->movie-detail

    <view class="container">
      <image mode="aspectFill" class="head-img" src="{{movie.image}}"></image>
      <view class="head-img-hover">
        <text class="main-title">{{movie.title}}</text>
        <text class="sub-title">{{movie.subtitle}}</text>
        <view class="like">
          <text class="highlight-font">{{movie.wishCount}}</text>
          <text class="plain-font">人喜欢</text>
          <text class="highlight-font">{{movie.commentsCount}}</text>
          <text class="plain-font">条评论</text>
        </view>
        <image bind:tap="onViewPost" class="movie-img" src="{{movie.image}}"></image>
      </view>
      <view class="summary">
        <view class="original-title">
          <text>{{movie.title}}</text>
        </view>
        <view class="flex-row">
          <text class="mark">评分</text>
          <view class="score-container">
            <l-rate disabled="{{true}}" size="22" score="{{movie.rating}}" />
            <text class="average">{{movie.average}}</text>
          </view>
        </view>
        <view class="flex-row">
          <text class="mark">导演</text>
          <text>{{movie.directors}}</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.genres}}</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="casts">
        <text class="cast-font">影人</text>
        <scroll-view enable-flex scroll-x class="casts-container">
          <block wx:for="{{movie.castsInfo}}" wx:key="index">
            <view class="cast-container">
              <image class="cast-img" src="{{item.img}}"></image>
              <text>{{item.name}}</text>
            </view>
            <view class="cast-container">
              <image class="cast-img" src="{{item.img}}"></image>
              <text>{{item.name}}</text>
            </view>
            <view class="cast-container">
              <image class="cast-img" src="{{item.img}}"></image>
              <text>{{item.name}}</text>
            </view>
          </block>
        </scroll-view>
      </view>
    </view>
    .container{
      display: flex;
      flex-direction: column;
    }
    
    .head-img{
       100%;
      height: 320rpx;
      /* 图片模糊效果 */
      -webkit-filter:blur(20px); 
    }
    
    .head-img-hover{
       100%;
      height: 320rpx;
      position: absolute;
      display: flex;
      flex-direction: column;
    }
    
    .main-title{
      font-size:38rpx;
      color:#fff;
      font-weight:bold;
      letter-spacing: 2px;
      margin-top: 50rpx;
      margin-left: 40rpx;
    }
    
    .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;
       175rpx;
      position: absolute;
      top:160rpx;
      right: 30rpx;
    }
    
    .summary{
      margin-left:40rpx;
      margin-top: 40rpx;
      color: #777777;
    }
    
    .original-title{
      color: #1f3463;
      font-size: 24rpx;
      font-weight: bold;
      margin-bottom: 40rpx;
    }
    
    .flex-row{
      display: flex;
      flex-direction: row;
      align-items: baseline;
      margin-bottom: 10rpx;
    }
    
    .mark{
      margin-right: 30rpx;
      white-space:nowrap;
      color: #999999;
    }
    
    .score-container{
      display: flex;
      flex-direction: row;
      align-items: baseline;
    }
    
    .average{
      margin-left:20rpx;
      margin-top:4rpx;
    }
    
    .hr{
      margin-top:45rpx;
       100%;
      height: 1px;
      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;
    }
    
    .casts{
      display: flex;
      flex-direction: column;
      margin-top:50rpx;
      margin-left:40rpx;
    }
    
    .cast-font{
      color: #999;
      margin-bottom: 40rpx;
    }
    
    .cast-img{
       170rpx;
      height: 210rpx;
      margin-bottom: 10rpx;
    }
    
    .casts-container{
      display: flex;
      flex-direction: row;
      margin-bottom: 50rpx;
      margin-right: 40rpx;
      height: 300rpx;
    }
    
    .cast-container{
      display: flex;
      flex-direction: column;
      align-items: center;
      margin-right: 40rpx;
    }

    movie-detail.js

    请求获取的电影详情数据,需要预处理

    {
        "casts": [
            {
                "avatars": {
                    "large": "https://img1.doubanio.com/view/celebrity/s_ratio_celebrity/public/p1470662353.8.jpg"
                },
                "name": "约翰·卡尼"
            },
            {
                "avatars": {
                    "large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p49301.jpg"
                },
                "name": "格伦·汉塞德"
            },
            {
                "avatars": {
                    "large": "https://img3.doubanio.com/view/celebrity/s_ratio_celebrity/public/p40505.jpg"
                },
                "name": "玛可塔·伊尔格洛娃"
            }
        ],
        "comments_count": 61027,
        "countries": [
            "爱尔兰"
        ],
        "directors": [
            {
                "avatars": {
                    "large": null
                },
                "name": "约翰·卡尼"
            }
        ],
        "genres": [
            "剧情",
            "爱情",
            "音乐"
        ],
        "id": 1,
        "images": {
            "large": "https://img3.doubanio.com/view/photo/s_ratio_poster/public/p2173720203.jpg"
        },
        "original_title": "曾经 Once",
        "rating": {
            "average": 8.3,
            "max": 10,
            "min": 0,
            "stars": "40"
        },
        "reviews_count": 2232,
        "summary": "",
        "title": "曾经 Once",
        "warning": "数据来源于网络整理,仅供学习,禁止他用。如有侵权请联系公众号:小楼昨夜又秋风。我将及时删除。",
        "wish_count": 96885,
        "year": 2007
    }

    1. 点击电影图片,有放大效果,调用小程序wx.previewImage预览函数

     
    // pages/movie-detail/movie-detail.js
    import {convertToCastString, convertToCastInfos} from '../../utils/util.js'
    const app = getApp()
    Page({
    
      /**
       * 页面的初始数据
       */
      data: {
        movie:{}
      },
    
      /**
       * 生命周期函数--监听页面加载
       */
      onLoad: function (options) {
        const mid = options.mid
        wx.request({
          url: app.gBaseUrl + 'subject/' + mid,
          success:(res)=>{
            console.log(res.data)
            this.processMovieData(res.data)
            // this.setData({
            //   movie:res.data
            // })
          }
        })
      },
    
      processMovieData(movie){
        const data = {}
        // 前端字段与后台字段映射,数据预处理
        // 处理小明 / 小红 / 小李 这种字符串,movie.directors是个数组
        data.directors = convertToCastString(movie.directors)
        // movie.casts是个数组
        data.casts = convertToCastString(movie.casts)
        data.image = movie.images.large
        data.title = movie.title
        data.subtitle = movie.countries[0]+'·'+movie.year
        data.wishCount = movie.wish_count
        data.commentsCount = movie.comments_count
        data.rating = movie.rating.stars/10
        data.average = movie.rating.average
        // movie.genres是个数组,join() 方法用于把数组中的所有元素放入一个字符串,元素是通过指定的分隔符进行分隔的
        data.genres = movie.genres.join('')
        data.summary = movie.summary
        // movie.casts是个数组
        data.castsInfo = convertToCastInfos(movie.casts)
        this.setData({
          movie:data
        })
      },
    
      // 点击图片放大功能
      onViewPost(event){
        wx.previewImage({
          urls: [this.data.movie.images.large],
        })
      },
    
    
    })

    引入的utils.js工具

    function convertToCastString(casts){
      var castsjoin = "";
      for (var idx in casts) {
        castsjoin = castsjoin + casts[idx].name + " / ";
      }
      // substring() 方法用于提取字符串中介于两个指定下标之间的字符。
      return castsjoin.substring(0, castsjoin.length - 2);
    }
    
    function convertToCastInfos(casts) {
      var castsArray = []
      for (var idx in casts) {
        // 过滤掉原来的avatars属性
        var cast = {
          img: casts[idx].avatars ? casts[idx].avatars.large : "",
          name: casts[idx].name
        }
        castsArray.push(cast);
      }
      return castsArray;
    }
    
    export {
      convertToCastString,
      convertToCastInfos
    }
  • 相关阅读:
    word2vec的Java源码【转】
    将博客搬至CSDN
    去掉中英文符号
    搜索引擎原理和简单过程【转】
    写国际会议论文和期刊的一些注意事项
    Java中Map根据键值(key)或者值(value)进行排序实现
    solr 查询获取数量getCount()
    【solr filter 介绍--转】http://blog.csdn.net/jiangchao858/article/details/54989025
    将中文数字转为数字
    java.util.Properties类的介绍-配置文件的读写【-Z-】
  • 原文地址:https://www.cnblogs.com/fsg6/p/14464168.html
Copyright © 2020-2023  润新知