「趣学前端」来逛逛数字博物馆
- 2022 年 9 月 07 日 北京
本文字数:21364 字
阅读完需:约 70 分钟

前言
每到一个城市,我喜欢逛当地的博物馆,这些博物馆里既有优秀的历史文物,也记载了一座城市从古至今的变迁。记得前几年百度推出了数字博物馆,我体验之后,不禁感叹做的有意思。今年春节,不知道能不能回家过年,但是数字博物馆的想法出现在我脑海里,于是我想不如在我自己的小程序里面仿照百度实现一个数字博物馆,让家人也体验一把不出门,就能逛博物馆的感觉。
举世闻名的曾侯乙编钟
很多年前去武汉旅游,参观了湖北省博物馆,曾侯乙编钟就陈列在一楼,封闭展示,四周是玻璃,可以让游客驻足观赏。
湖北省博物馆很大,有很多藏品,但是给我留下映象最深的还是曾侯乙编钟,因为它是我见过的最大的青铜器。参观完我还去听了演奏节目。
如果今后有机会去武汉,我还会再去一趟湖北省博物馆,因为每次看到曾侯乙编钟,即使是在图片上,我还是感到很震撼。
百度数字博物馆的精妙之处
我作为一个旅游和历史爱好者,由衷佩服百度能把线上博物馆做的这么有趣。
以往,我们从网络上了解一个博物馆或者一件文物,都是通过图文介绍,有时候文字太长,可能看不进去,或者看完记不住。
百度的数字博物馆,加了设计的交互,让原本的图文变的生动了很多。其中曾侯乙编钟作为专题,交互更加细致。它将曾侯乙编钟进行了拆分,每个知识点用不同的交互进行演示,让观看的人有种身临其境的感觉。
复刻与创造
既然感到有意思,不免心痒手痒,加上因为疫情春节也没法出去旅游,于是决定在自己的小程序里面复刻一个数字博物馆。当然了博物馆很庞大,我决定从喜爱的文物着手,首先想到的是曾侯乙编钟。
UI
页面配色是由厚重的黑色、编钟原有的红色、百搭的白色以及高亮的黄色共同组成。
页面布局由中间醒目的编钟完整图片和上线两排导航组成。
页面交互主要是每个导航点击触发文字高亮和展示/关闭导航模块内容的过渡动画,而每个导航模块中的交互也各不相同,下面会详细介绍。
框架设计
每个导航的切换方式、内容结果和关闭交互都是一致的。
整体的设计如下图:
逐步完成
因为是同一个页面,所以我在做结构设计的时候,对每一个模块设置对应的 key 值,用来区分当前展示内容。
初始模块
zenghouyi.wxml
1、我将不同模块的展示放到了 wxs 中进行统一处理,根据当前展示模块的 key 和代码中的 key 值是否一致来判断是否展示。pageType:当前展示的模块 key 值
2、导航列表分上下两列,通过定位进行展示处理;
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home" style="display:{{ script.getDisplayVal(pageType, 'home') }}"> <view wx:for="{{ navList }}" wx:key="navIndex" wx:for-item="navItem" class="home-item" bindtap="getItemShow" data-item="{{ navItem }}" style="top:{{ navItem.top ? navItem.top + 'px' : '' }};bottom:{{ navItem.bottom ? navItem.bottom + 'px' : '' }};left:{{ navItem.left + '%' }};"> <view class="home-item-box"> <view class="home-item-title" hover-class="home-item-title-curr" style="bottom:{{ navItem.id < 5 ? '32rpx' : '52rpx' }}">{{ navItem.name }}</view> <image src="../../images/zenghouyi/nav-bg-up.png" class="home-item-bg" wx-if="{{ navItem.id < 5 }}"></image> <image src="../../images/zenghouyi/nav-bg-down.png" class="home-item-bg" wx-if="{{ navItem.id > 4 }}"></image> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E7%BC%96%E9%92%9F%E6%8A%A0%E5%9B%BE.jpg" class="home-main"></image> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { pageType: 'home', // 页面type值 区分展示模块 navList: [ // 主模块-导航列表 { id: 1, name: '结构', top: 10, left: 5, key: 'jiegou', }, { id: 2, name: '细节', top: 10, left: 30, key: 'xijie', }, { id: 3, name: '译文', top: 10, left: 55, key: 'yiwen', }, { id: 4, name: '奏乐', top: 10, left: 80, key: 'zouyue', }, { id: 5, name: '钮钟', bottom: 10, left: 5, key: 'niuzhong', }, { id: 6, name: '甬钟', bottom: 10, left: 30, key: 'yongzhong', }, { id: 7, name: '镈钟', bottom: 10, left: 55, key: 'bozhong', }, { id: 8, name: '分享', bottom: 10, left: 80, key: 'fenxiang', }, ], // 主模块-导航数组 },
/** * 导航点击事件-切换当前需要展示的模块内容 */ getItemShow(e) { let item = e.currentTarget.dataset.item; // =>true: 设置细节当前展示的item项 if (item.key === 'xijie') { let { xijie, xijieFlag } = this.data; this.setData({ xijieItem: xijie.enum[xijieFlag], }); } else if (item.key === 'zouyue') { // =>true: 设置奏乐当前展示的item项 let { zouyue, zouyueFlag } = this.data; this.setData({ zouyueItem: zouyue.enum[zouyueFlag], }); } this.setData({ pageType: item.key, }); },});
zenghouyi.wxss
.container { height: 100vh; background: rgb(58, 58, 58); padding-top: 40rpx; position: relative;}.container-bg { position: absolute; top: 0; left: 0; height: 100vh; width: 100%; z-index: 10;}.home { width: 100%; height: 800rpx; position: relative; z-index: 99; animation: homeTwinkle 0.5s linear 0s 1 forwards;}@keyframes homeTwinkle { 100% { opacity: 1; } 0% { opacity: 0; }}.home-close { position: absolute; top: 10rpx; right: 10rpx; width: 50rpx; height: 50rpx; z-index: 999;}.home-center { margin: 0 30rpx; padding-top: 80rpx; height: 100%; position: relative;}.home-item { position: absolute; width: 76rpx; height: 175rpx;}.home-item-box { position: relative;}.home-item-title { position: absolute; left: 0; color: #fff; font-size: 32rpx; writing-mode: vertical-lr; line-height: 76rpx; letter-spacing: 18rpx; font-weight: 600;}.home-item-title-curr { color: #e9d27b;}.home-item-bg { width: 76rpx; height: 175rpx;}.home-main { width: 100%; height: 288rpx; margin-top: 260rpx;}
结构模块
UI
尺寸展示
结构展示
zenghouyi.wxml
1、结构模块的导航分为尺寸和结构,默认选中尺寸,展示编钟尺寸数值。切换结构之后,会展示结构下的上层、中层、下层这三个位置导航;位置导航切换时,会高亮编钟对应位置,其中下层中间位置的镈钟做了一个闪烁的动效;
2、上中下三层位置的高亮通过 css 中的 box-shadow 实现;
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home jiegou" style="display:{{ script.getDisplayVal(pageType, 'jiegou') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="jiegou"></image> <view class="jiegou-image"> <view class="jiegou-image-box"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/10%E9%92%9F%E6%9E%B6%E9%A1%B5_%E5%B0%BA%E5%AF%B8%E7%BA%BF.png" class="jiegou-image-sizeTag" wx-if="{{ jiegouFlag === 'size' }}"></image> <view class="jiegou-image-topHighlight" wx-if="{{ jiegouTextFlag === 'structureTop' }}"></view> <view class="jiegou-image-middleHighlight" wx-if="{{ jiegouTextFlag === 'structureMiddle' }}"></view> <view class="jiegou-image-bottomHighlight" wx-if="{{ jiegouTextFlag === 'structureBottom' }}"></view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/10%E9%92%9F%E6%9E%B6%E9%A1%B5_%E9%95%88%E9%92%9F%E9%97%AA-%E5%9B%BE.png" class="jiegou-image-structureTwinkle" wx-if="{{ jiegouTextFlag === 'structure' || jiegouTextFlag === 'structureBottom' }}"></image> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/10%E9%92%9F%E6%9E%B6%E9%A1%B5_%E7%BC%96%E9%92%9F%E5%AE%8C%E6%95%B4.jpg" class="jiegou-image-all"></image> </view> <view class="jiegou-image-text">{{ jiegou.text[jiegouTextFlag] }}</view> </view> <!-- 结构导航 --> <view class="jiegou-structure-nav" wx-if="{{ jiegouFlag === 'structure' }}"> <view wx:for="{{ jiegou.structureList }}" wx:key="navIndex" wx:for-item="navItem" class="jiegou-structure-item" bindtap="jiegouStructureNavChange" data-item="{{ navItem }}"> <view class="jiegou-structure-item-box {{ navItem.key === jiegouTextFlag ? 'jiegou-structure-item-curr' : '' }}"> <view class="jiegou-structure-nav-title">{{ navItem.name }}</view> </view> </view> </view> <view class="jiegou-nav"> <view wx:for="{{ jiegou.list }}" wx:key="navIndex" wx:for-item="navItem" class="jiegou-item" bindtap="jiegouNavChange" data-item="{{ navItem }}"> <view class="jiegou-item-box"> <view class="jiegou-item-title {{ navItem.key === jiegouFlag ? 'jiegou-item-title-curr' : '' }}">{{ navItem.name }}</view> <image src="../../images/zenghouyi/title-bg.png" class="jiegou-item-bg"></image> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { jiegouFlag: 'size', // 结构-展示内容的flag值 jiegouTextFlag: 'size', // 结构-结构分类-展示内容的flag值 jiegou: { // 结构-数据对象 flag: 'size', list: [ { key: 'size', name: '尺 寸', }, { key: 'structure', name: '结 构', }, ], structureList: [ { key: 'structureTop', name: '上 层', }, { key: 'structureMiddle', name: '中 层', }, { key: 'structureBottom', name: '下 层', }, ], text: { size: '曾侯乙编钟,长7.48米,宽3.35米,高2.73米。重2567公斤。', structure: '钟架分三层八组悬挂着65件青铜钟。', structureTop: '上层分三组钮钟,19件。', structureMiddle: '中层分三组甬钟,33件。', structureBottom: '下层为两组大型长枚甬钟,12件。下层正中悬挂的是楚惠王送给曾侯乙的意见镈钟。', }, }, }, /** * 展示主页内容 */ getHome(e) { let key = e.currentTarget.dataset.key; // 重置变量值 if (key === 'jiegou') { this.setData({ jiegouFlag: 'size', jiegouTextFlag: 'size', }); } this.setData({ pageType: 'home', }); }, /** * 结构-切换底部导航 */ jiegouNavChange(e) { let item = e.currentTarget.dataset.item; let jiegouFlag = item.key; let jiegouTextFlag = item.key; this.setData({ jiegouFlag: jiegouFlag, jiegouTextFlag: jiegouTextFlag, }); }, /** * 结构-结构-切换导航 */ jiegouStructureNavChange(e) { let item = e.currentTarget.dataset.item; let jiegouTextFlag = item.key; this.setData({ jiegouTextFlag: jiegouTextFlag, }); },});
zenghouyi.wxss
.jiegou { padding-top: 30rpx;}.jiegou-image { width: 100%; height: 480rpx; margin-bottom: 20rpx; position: relative;}.jiegou-image-text { font-size: 20rpx; color: #fff; text-align: center; margin-top: 10rpx; font-weight: 300; position: absolute; bottom: 20rpx; z-index: 999; width: 100%;}.jiegou-image-box { width: 100%; height: 380rpx; position: relative;}.jiegou-image-sizeTag { width: 730rpx; height: 320rpx; display: block; position: absolute; top: 0; left: 10rpx; z-index: 30;}.jiegou-image-topHighlight { width: 494rpx; height: 46rpx; display: block; position: absolute; top: 69rpx; left: 97rpx; z-index: 50; box-shadow: 0 0 0 195rpx rgb(0, 0, 0, 0.6);}.jiegou-image-middleHighlight { width: 539rpx; height: 50rpx; display: block; position: absolute; top: 118rpx; left: 94rpx; z-index: 50; box-shadow: 0 0 0 150rpx rgb(0, 0, 0, 0.6);}.jiegou-image-bottomHighlight { width: 509rpx; height: 73rpx; display: block; position: absolute; top: 199rpx; left: 102rpx; z-index: 50; box-shadow: 0 0 0 135rpx rgb(0, 0, 0, 0.6);}.jiegou-image-structureTwinkle { width: 45rpx; height: 67rpx; display: block; position: absolute; bottom: 115rpx; left: 362rpx; z-index: 50; animation: structureTwinkle 1s linear 0s infinite forwards;}@keyframes structureTwinkle { 100% { opacity: 1; } 50% { opacity: 0; } 0% { opacity: 1; }}.jiegou-image-all { position: absolute; top: 10rpx; left: 20rpx; width: 700rpx; height: 300rpx; z-index: 20;}
.jiegou-nav { display: flex; justify-content: space-between; padding: 10rpx 140rpx;}.jiegou-item { width: 154rpx; height: 88rpx;}.jiegou-item-bg { width: 154rpx; height: 88rpx;}.jiegou-item-box { width: 154rpx; height: 88rpx; position: relative;}.jiegou-item-title { position: absolute; left: 50%; top: 50%; margin-left: -40rpx; margin-top: -22rpx; color: #fff; font-size: 30rpx; font-weight: 600; width: 80rpx; height: 44rpx;}.jiegou-item-title-curr { color: #e9d27b; font-size: 300;}.jiegou-structure-nav { display: flex; justify-content: flex-end; flex-direction: column; align-items: flex-end; padding: 0 155rpx;}.jiegou-structure-item-box { border: 2px solid #56080a; height: 40rpx; width: 120rpx; margin-bottom: 8rpx; text-align: center; display: flex; align-items: center; justify-content: center;}.jiegou-structure-item-curr { border-color: #920000;}.jiegou-structure-nav-title { width: 110rpx; height: 30rpx; background: #56080a; color: #fff; font-size: 20rpx;}.jiegou-structure-item-curr .jiegou-structure-nav-title { background: #920000;}
细节模块
UI
zenghouyi.wxml
细节模块的导航为标音铭文、记事铭文、钟架、配件四项;切换展示不同图片和文案介绍。
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home xijie" style="display:{{ script.getDisplayVal(pageType, 'xijie') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="xijie"></image> <view class="home-center"> <view class="xijie-nav"> <view wx:for="{{ xijie.list }}" wx:key="navIndex" wx:for-item="navItem" class="xijie-item" bindtap="xijieGetItemShow" data-item="{{ navItem }}"> <view class="xijie-item-box {{ navItem.key === xijieFlag ? 'xijie-item-curr' : '' }}"> <view class="xijie-item-title">{{ xijie.enum[navItem.key].name }}</view> </view> </view> </view> <view class="xijie-content"> <view class="xijie-content-img"> <image src="{{ xijieItem.src }}"></image> </view> <view class="xijie-introduce"> <view class="xijie-introduce-title">{{ xijieItem.name }}</view> <view class="xijie-introduce-text">{{ xijieItem.introduce }}</view> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { xijieFlag: 'bymw', // 细节-展示内容的flag值 xijie: { // 细节-数据对象 list: [ { key: 'bymw', }, { key: 'jsmw', }, { key: 'zj', }, { key: 'pj', }, ], enum: { bymw: { name: '标音铭文', introduce: '钟架、钟钩、钟体上共有铭文3755字,内容为编号、记事、标音和乐律理论、铭文多数错金。标音铭文标示了钟的悬挂位置或敲击部位及其所发音的名称。', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E6%A0%87%E9%9F%B3%E5%9B%BE1.jpg', }, jsmw: { name: '记事铭文', introduce: '全部甬钟的记事铭文均有 “曾侯乙作持”5字,标明钟的制作和享用者是曾侯乙。曾侯乙,姓姬名乙。“曾”是国名,“侯”是爵位,“乙”是名字,“曾侯乙”即战国时期曾国一位名叫“乙”的君主。', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E8%AE%B0%E4%BA%8B%E5%9B%BE1.jpg', }, zj: { name: '钟架', introduce: '由六个青铜佩剑', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E9%92%9F%E6%9E%B6%E5%9B%BE1.jpg', }, pj: { name: '配件', introduce: '钟架、钟钩、钟体上共有铭文3755字,内容为编号、记事、标音和乐律理论、铭文多数错金。标音铭文标示了钟的悬挂位置或敲击部位及其所发音的名称。', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E9%85%8D%E4%BB%B6%E5%9B%BE1.jpg', }, }, }, xijieItem: {}, // 细节-当前选中的对象变量 }, /** * 展示主页内容 */ getHome(e) { let key = e.currentTarget.dataset.key; // 重置变量值 if (key === 'xijie') { this.setData({ xijieItem: {}, xijieFlag: 'bymw', }); } this.setData({ pageType: 'home', }); }, /** * 细节-切换导航 */ xijieGetItemShow(e) { let item = e.currentTarget.dataset.item; let xijie = this.data.xijie; this.setData({ xijieFlag: item.key, xijieItem: xijie.enum[item.key], }); },});
zenghouyi.wxss
.xijie-nav { position: absolute; top: 80rpx; left: 0; z-index: 99; height: 380rpx; display: flex; flex-direction: column; justify-content: space-between;}.xijie-item-box { width: 80rpx; height: 80rpx; border: 2rpx solid #851a11; background: #211211; display: flex; align-items: center; justify-content: center;}.xijie-item-title { width: 60rpx; height: 60rpx; padding: 2rpx; border: 2rpx solid #811911; background: #430906; color: #fff; font-size: 24rpx; text-align: center; display: flex; align-items: center; justify-content: center;}.xijie-item-curr .xijie-item-title { color: #ebd273;}.xijie-content { position: absolute; top: 80rpx; left: 0; z-index: 59; width: 100%;}.xijie-content-img { display: flex; justify-content: flex-end; align-items: center; height: 366rpx; margin-bottom: 60rpx;}.xijie-content-img image { width: 560rpx; height: 360rpx; border: 4rpx solid #fff;}.xijie-introduce { width: 100%; color: #fff;}.xijie-introduce-title { height: 60rpx; border-bottom: 1px solid #fff; text-align: left; font-size: 32rpx; padding-left: 30rpx;}
.xijie-introduce-text { width: 80%; margin: 0 auto; font-size: 28rpx; line-height: 1.5; margin-top: 30rpx; font-weight: 300;}
译文模块
UI
zenghouyi.wxml
译文的古文和现代对照通过图片翻转效果实现,翻转效果由 transform 的旋转属性实现。
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home yiwen" style="display:{{ script.getDisplayVal(pageType, 'yiwen') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="yiwen"></image> <view class="home-center"> <view class="yiwen-top"> <view class="yiwen-top-box {{ yiwenFlag === 'old' ? 'yiwen-top-curr-old' : 'yiwen-top-curr-new' }}" bindtap="yiwenChange"> <image src="{{ yiwen.old }}" class="yiwen-top-img yiwen-top-old"></image> <image src="{{ yiwen.new }}" class="yiwen-top-img yiwen-top-new"></image> </view> <view class="yiwen-top-text"> {{ yiwen.text }} </view> </view> <view class="yiwen-introduce"> <view class="xijie-introduce-title">{{ yiwen.name }}</view> <view class="yiwen-introduce-text"> <view wx:for="{{ yiwen.introduce }}" wx:key="navIndex" wx:for-item="navTextItem" class="yiwen-introduce-item"> {{ navTextItem }} </view> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { yiwenFlag: 'old', yiwen: { text: '点击铭文图片查看古文对照', // 译文-对象变量 old: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/8%E9%95%88%E9%92%9F%E9%A1%B5_%E9%93%AD%E6%96%87%E6%94%BE%E5%A4%A7%E5%9B%BE-%E9%93%AD.jpg', new: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/8%E9%95%88%E9%92%9F%E9%A1%B5_%E9%93%AD%E6%96%87%E6%94%BE%E5%A4%A7%E5%9B%BE-%E8%AF%91.jpg', name: '现代译文', introduce: ['这篇铭文告诉我们,这件镈钟是楚惠王熊章为曾侯乙制作的一套宗庙祭器之一,放置在西阳,其铭文纪年为楚惠王五十六年,即公元前433年。', '也有学者认为,古书中“返”与“报”两字常互相代用,“报”即报丧的意思。铭文中的“返自西阳”应解释为从西阳得到曾侯乙去世的消息后,楚惠王为曾侯乙制作了镈钟这件祭器。'], }, }, /** * 展示主页内容 */ getHome(e) { let key = e.currentTarget.dataset.key; // 重置变量值 if (key === 'yewei') { this.setData({ yeweiFlag: 'old', }); } this.setData({ pageType: 'home', }); }, /** * 译文-按钮点击 */ yiwenChange() { let yiwenFlag = this.data.yiwenFlag; yiwenFlag = yiwenFlag === 'new' ? 'old' : 'new'; this.setData({ yiwenFlag: yiwenFlag, }); },});
zenghouyi.wxss
.yiwen-top { height: 529rpx; display: flex; align-items: center; padding-left: 200rpx;}.yiwen-top-box { position: relative; width: 288rpx; height: 529rpx; transition: transform 1s; transform-style: preserve-3d;}.yiwen-top-curr-old { transform: rotateY(0);}.yiwen-top-curr-new { transform: rotateY(180deg);}.yiwen-top-img { position: absolute; top: 0; left: 0; width: 288rpx; height: 529rpx; z-index: 99; backface-visibility: hidden;}.yiwen-top-new { transform: rotateY(180deg);}.yiwen-introduce { color: #fff; position: absolute; bottom: 0; left: 0; font-size: 24rpx;}.yiwen-top-text { width: 50rpx; background: #211211; color: #fff; margin-left: 30rpx; font-size: 28rpx;}.yiwen-introduce-text { margin-top: 30rpx; font-weight: 300; font-size: 24rpx;}
奏乐模块
UI
zenghouyi.wxml
微信小程序提供了媒体组件 video,具体使用可以参考官方文档
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home zouyue" style="display:{{ script.getDisplayVal(pageType, 'zouyue') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="zouyue"></image> <view class="home-center"> <view class="zouyue-top"> <view class="zouyue-top-img"> <image src="{{ zouyueItem.src }}"></image> </view> <view class="zouyue-introduce"> <view class="zouyue-introduce-title">{{ zouyue.name }}</view> <view class="zouyue-introduce-text">{{ zouyue.introduce }}</view> </view> </view> <view class="zouyue-video"> <video controls="true" id="video" src="{{ zouyueItem.video }}" bindplay="onVideoPlay" object-fit="cover" poster="{{ zouyueItem.src }}"></video> </view> <view class="zouyue-nav"> <view wx:for="{{ zouyue.list }}" wx:key="navIndex" wx:for-item="navItem" class="zouyue-item" bindtap="zouyueGetItemShow" data-item="{{ navItem }}"> <view class="zouyue-item-box {{ navItem.key === zouyueFlag ? 'zouyue-item-curr' : '' }}"> <view class="zouyue-item-title">{{ zouyue.enum[navItem.key].name }}</view> </view> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { zouyueFlag: 'cs', // 奏乐-展示内容的flag值 zouyue: { // 奏乐-对象变量 name: '奏乐', introduce: '编钟音域宽广,跨越五个半八度,只比现代钢琴少一个八度,中心音域12个半音齐全。', list: [ { key: 'cs', }, { key: 'gs', }, { key: 'cjhyy', }, { key: 'dfg', }, ], enum: { cs: { name: '楚商', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E6%A5%9A%E5%95%86.jpg', video: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E6%A5%9A%E5%95%86%E7%89%87%E6%AE%B5.mp3', }, gs: { name: '国殇', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%9B%BD%E6%AE%87.jpg', video: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%9B%BD%E6%AE%87%E7%89%87%E6%AE%B5.mp3', }, cjhyy: { name: '春江花月夜', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E6%98%A5%E6%B1%9F.jpg', video: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E6%98%A5%E6%B1%9F%E8%8A%B1%E6%9C%88%E5%A4%9C%E7%89%87%E6%AE%B5.mp3', }, dfg: { name: '东方红', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E4%B8%9C%E6%96%B9.jpg', video: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E4%B8%9C%E6%96%B9%E7%BA%A2.mp3', }, }, }, zouyueItem: {}, // 奏乐-当前选中的对象变量 }, /** * 展示主页内容 */ getHome(e) { let key = e.currentTarget.dataset.key; // 重置变量值 if (key === 'zouyue') { let { zouyue } = this.data; let zouyueFlag = 'cs'; this.setData({ zouyueItem: zouyue.enum[zouyueFlag], zouyueFlag: 'cs', }); } this.setData({ pageType: 'home', }); }, /** * 奏乐-切换导航 */ zouyueGetItemShow(e) { let item = e.currentTarget.dataset.item; let zouyue = this.data.zouyue; this.setData({ zouyueFlag: item.key, zouyueItem: zouyue.enum[item.key], }); }, /** * 奏乐-播放 */ onVideoPlay() { //播放 disabled.ispay = true; },});
zenghouyi.wxss
.zouyue-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 30rpx;}.zouyue-top-img { width: 347rpx; border: 2rpx solid #851a11; background: #211211; height: 324rpx; display: flex; align-items: center; justify-content: center;}.zouyue-top-img image { width: 317rpx; height: 294rpx; display: block;}.zouyue-introduce { width: 48%; color: #fff; margin-left: 20rpx;}.zouyue-introduce-title { height: 60rpx; border-bottom: 1px solid #fff; text-align: left; font-size: 32rpx; padding-left: 30rpx;}
.zouyue-introduce-text { width: 80%; margin: 30rpx auto 0; font-size: 28rpx; color: #fff; line-height: 1.5; font-weight: 300;}.zouyue-nav { display: flex; justify-content: space-between; margin-top: 30rpx;}.zouyue-item-box { width: 140rpx; height: 70rpx; border: 2rpx solid #851a11; background: #211211; display: flex; align-items: center; justify-content: center;}.zouyue-item-title { width: 120rpx; height: 50rpx; padding: 2rpx; border: 2rpx solid #811911; background: #430906; color: #fff; font-size: 24rpx; text-align: center; display: flex; align-items: center; justify-content: center;}.zouyue-item-curr .zouyue-item-title { color: #ebd273;}.zouyue-video video { width: 700rpx; height: 300rpx; margin: 0 auto;}
钮钟模块
UI
zenghouyi.wxml
页面顶部的每个钮钟都可以点击,点击之后有左右晃动的动态交互。
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home niuzhong" style="display:{{ script.getDisplayVal(pageType, 'niuzhong') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="niuzhong"></image> <view class="home-center"> <view class="niuzhong-top"> <view wx:for="{{ niuzhong.list }}" wx:key="navIndex" wx:for-item="navItem" class="niuzhong-item {{ navItem.className }} {{ niuzhongImgIndex === navItem.id ? 'niuzhong-item-animation' : '' }}" bindtap="niuzhongGetImgIndex" data-item="{{ navItem }}"> <image src="{{ navItem.src }}"></image> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_%E9%92%9F%E6%9E%B6.png" class="niuzhong-top-bg"></image> </view> <view class="niuzhong-introduce"> <view class="zouyue-introduce-title">{{ niuzhong.name }}</view> <view class="niuzhong-introduce-box"> <view wx:for="{{ niuzhong.introduce }}" wx:key="navIndex" wx:for-item="navItem" class="niuzhong-introduce-item"> <view class="niuzhong-introduce-title">{{ navItem.title }}:</view> <view class="niuzhong-introduce-text"> <view wx:for="{{ navItem.text }}" wx:key="navIndex" wx:for-item="navTextItem" class="niuzhong-introduce-text-item"> {{ navTextItem }} </view> </view> </view> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { niuzhongImgIndex: null, niuzhong: { // 钮钟-对象变量 name: '钮钟', list: [ { id: 0, className: 'niuzhong-item1', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_1.png', }, { id: 1, className: 'niuzhong-item2', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_2.png', }, { id: 2, className: 'niuzhong-item3', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_3.png', }, { id: 3, className: 'niuzhong-item4', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_4.png', }, { id: 4, className: 'niuzhong-item5', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_5.png', }, { id: 5, className: 'niuzhong-item6', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_6.png', }, { id: 6, className: 'niuzhong-item7', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/3%E9%92%AE%E9%92%9F%E9%A1%B5_7.png', }, ], introduce: [ { title: '结构', text: ['共三组19件,钟体素面无纹饰,皆铸有铭文。'], }, { title: '尺寸', text: ['上层三组1号钟最小,通高20.2厘米,重2.4千克。', '上层三组7号钟最大,通高39.9厘米,重11.4千克。'], }, ], }, }, /** * 展示主页内容 */ getHome(e) { let key = e.currentTarget.dataset.key; // 重置变量值 if (key === 'niuzhong') { this.setData({ niuzhongImgIndex: null, }); } this.setData({ pageType: 'home', }); }, /** * 钮钟-点击图片 */ niuzhongGetImgIndex(e) { let item = e.currentTarget.dataset.item; this.setData({ niuzhongImgIndex: item.id, }); },});
zenghouyi.wxss
.niuzhong-introduce { color: #fff;}.niuzhong-introduce-box { display: flex; justify-content: space-between; width: 100%; margin-top: 20rpx;}.niuzhong-introduce-item { width: 45%; display: flex;}.niuzhong-introduce-item { display: flex; font-size: 28rpx; font-weight: 300;}.niuzhong-introduce-title { width: 100rpx;}.niuzhong-introduce-text { flex: 1;}.niuzhong-introduce-text-item { margin-bottom: 20rpx;}.niuzhong-top { position: relative; height: 300rpx;}.niuzhong-top-bg { position: absolute; top: 0; left: 0; width: 700rpx; height: 178rpx; z-index: 59;}.niuzhong-item { position: absolute; top: 60rpx; z-index: 99;}.niuzhong-item-animation { animation: niuzhongTwinkle 1.5s linear 0s 1 forwards;}@keyframes niuzhongTwinkle { 100% { transform: translate(0rpx, 0rpx); } 60% { transform: translate(-6rpx, 0rpx); } 50% { transform: translate(6rpx, 0rpx); } 42.5% { transform: translate(-3rpx, 0rpx); } 37.5% { transform: translate(3rpx, 0rpx); } 32.5% { transform: translate(0rpx, 0rpx); } 0% { transform: translate(0rpx, 0rpx); } 72.5% { transform: translate(0rpx, 0rpx); }}.niuzhong-item1 { left: 96rpx;}.niuzhong-item1 image { width: 47rpx; height: 72rpx;}.niuzhong-item2 { left: 142rpx;}.niuzhong-item2 image { width: 57rpx; height: 87rpx;}.niuzhong-item3 { left: 198rpx;}.niuzhong-item3 image { width: 64rpx; height: 96rpx;}.niuzhong-item4 { left: 260rpx;}.niuzhong-item4 image { width: 69rpx; height: 108rpx;}.niuzhong-item5 { left: 311rpx;}.niuzhong-item5 image { width: 91rpx; height: 115rpx;}.niuzhong-item6 { left: 405rpx;}.niuzhong-item6 image { width: 96rpx; height: 130rpx;}.niuzhong-item7 { left: 486rpx;}.niuzhong-item7 image { width: 103rpx; height: 137rpx;}
甬钟模块
UI
zenghouyi.wxml
幹、枚、鼓三个位置的交互为,点击展示详细的介绍,再次点击介绍收起。
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home yongzhong" style="display:{{ script.getDisplayVal(pageType, 'yongzhong') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="yongzhong"></image> <view class="home-center"> <view class="yongzhong-nav"> <view wx:for="{{ yongzhong.list }}" wx:key="navIndex" wx:for-item="navItem" class="yongzhong-item" style="top:{{ navItem.top + 'rpx' }};left:{{ navItem.left + 'rpx' }};"> <view class="yongzhong-item-box" bindtap="yongzhongGetItemShow" data-item="{{ navItem }}"> <view class="yongzhong-item-title">{{ navItem.name }}</view> </view> <view class="yongzhong-item-introduce" wx-if="{{ navItem.show }}" style="top:{{ navItem.introduceTop + 'rpx' }};left:{{ navItem.introduceLeft + 'rpx' }};width:{{ navItem.introduceWidth + 'rpx' }};"> <view class="yongzhong-item-introduce-title">“{{ navItem.name }}”</view> <view class="yongzhong-item-introduce-text">{{ navItem.introduce }}</view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/7%E7%94%AC%E9%92%9F%E9%A1%B5_%E7%BA%BF%E9%92%9F.png" class="yongzhong-nav-bg"></image> </view> <view class="xijie-introduce"> <view class="xijie-introduce-title">{{ yongzhong.name }}</view> <view class="zouyue-introduce-size"> <view class="zouyue-introduce-size-title">结构:</view> <view class="zouyue-introduce-size-text">{{ bozhong.introduce }}</view> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { yongzhong: { // 甬钟-对象变量 name: '甬钟', introduce: '最大的钟通高153.4厘米,重253.6公斤;最小的钟通高20.2厘米,重2.4公斤。中层一组为短枚钟,共十一件;中层二组为无枚钟,共十二件;中层三组为长枚钟,共十件;下层一组三件,下层二组九件亦为长枚钟,因其形体甚大,亦称大型长枚甬钟。', list: [ { id: 1, key: 'gan', name: '幹', introduce: '用于承挂钟钩,使甬钟能侧向钩挂于钟架上。', show: false, left: 206, top: 122, introduceLeft: -200, introduceTop: -140, introduceWidth: 168, }, { id: 2, key: 'gu', name: '枚', introduce: '用于抑制钟声中的高频成分,调节钟声音色。', show: false, top: 228, left: 120, introduceLeft: -120, introduceTop: 84, introduceWidth: 168, }, { id: 3, key: 'gu', name: '鼓', introduce: '是钟的发声部位“正鼓”底部口沿,正中央的部位。', show: false, left: 468, top: 416, introduceLeft: 40, introduceTop: -296, introduceWidth: 164, }, ], }, }, /** * 展示主页内容 */ getHome(e) { let key = e.currentTarget.dataset.key; // 重置变量值 if (key === 'yongzhong') { let yongzhong = this.data.yongzhong; yongzhong.list.map(item => { item.show = false; }); this.setData({ yongzhong: yongzhong, }); } this.setData({ pageType: 'home', }); }, /** * 甬钟-切换导航 */ yongzhongGetItemShow(e) { let item = e.currentTarget.dataset.item; let yongzhong = this.data.yongzhong; let list = yongzhong.list; let itemNew = list[item.id - 1]; itemNew.show = !itemNew.show; this.setData({ yongzhong: yongzhong, }); },});
zenghouyi.wxss
.yongzhong-nav { position: relative; height: 700rpx;}.yongzhong-nav-bg { width: 319rpx; height: 569rpx; position: absolute; top: 0; left: 50%; margin-left: -160rpx; z-index: 50;}.yongzhong-item { position: absolute; z-index: 99;}.yongzhong-item-box { width: 60rpx; height: 60rpx; border: 4rpx solid #9e1f15; color: #9e1f15; font-size: 40rpx; border-radius: 50%; display: flex; justify-content: center; align-items: center; font-weight: 600;}.yongzhong-item-introduce { color: #9e1f15; border: 3rpx solid #9e1f15; position: absolute; padding: 10rpx; font-size: 24rpx; line-height: 1.5; border-radius: 4rpx; animation: yongzhongTwinkle 0.5s linear 0s 1 forwards;}@keyframes yongzhongTwinkle { 100% { opacity: 1; } 0% { opacity: 0; }}.yongzhong-item-introduce-title { font-size: 30rpx; line-height: 1.2; margin-bottom: 10rpx;}
镈钟模块
UI
zenghouyi.wxml
<!-- wxs展示处理--><wxs module="script"> var getDisplayVal = function(pageType,type) { var val = pageType == type ? 'block' : 'none'; return val; }; module.exports.getDisplayVal = getDisplayVal;</wxs><view class="container"> <view class="home bozhong" style="display:{{ script.getDisplayVal(pageType, 'bozhong') }}"> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/%E5%85%B3%E9%97%AD%E6%8C%89%E9%92%AE.png" class="home-close" bindtap="getHome" data-key="bozhong"></image> <view class="home-center"> <view class="zouyue-top"> <view class="bozhong-top-img"> <image src="{{ bozhong.src }}"></image> </view> <view class="zouyue-introduce bozhong-introduce"> <view class="zouyue-introduce-title">{{ bozhong.name }}</view> <view class="zouyue-introduce-size"> <view class="zouyue-introduce-size-title">尺寸:</view> <view class="zouyue-introduce-size-text">{{ bozhong.sizeText }}</view> </view> <view class="zouyue-introduce-text bozhong-introduce-text">{{ bozhong.introduce }}</view> </view> </view> </view> </view> <image src="https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/1%E5%AF%BC%E8%88%AA%E9%A1%B5_%E5%BA%95%E7%BA%B9.jpg" class="container-bg"></image></view>
zenghouyi.js
Page({ /** * 页面的初始数据 */ data: { bozhong: { // 镈钟-对象变量 name: '镈钟', sizeText: '高92.5厘米,口径60.5X46.2厘米,重134.8公斤。', introduce: '曾侯乙编钟的钟梁上刻有表示悬挂位置的律名,与钟体上的标音铭文相对应。与钟体铭文对照发现,这套编钟的部分钟体发生了位移,缺少了一件最大的甬钟。取代它的,是一件圆形的镈钟,乃是楚惠王赠送给曾侯乙的礼物。因曾楚两国此时关系融洽,曾国十分重视这件礼物,故将镈钟挂在全套编钟最显眼的位置,伴随曾侯乙长眠地下。', src: 'https://baikebcs.bdimg.com/baike-other/digital_museum/zenghouyi/resources/8%E9%95%88%E9%92%9F%E9%A1%B5_%E9%8E%9B%E9%92%9F%E4%B8%BB%E4%BD%93.jpg', }, }, /** * 展示主页内容 */ getHome() { this.setData({ pageType: 'home', }); },});
zenghouyi.wxss
.bozhong-top-img { width: 277rpx; height: 462rpx; display: flex; align-items: center; justify-content: center;}.bozhong-top-img image { width: 277rpx; height: 462rpx; display: block;}.zouyue-introduce.bozhong-introduce { width: 55%; margin-left: 0;}.zouyue-introduce-text.bozhong-introduce-text { margin: 30rpx 0 0 80rpx; font-size: 24rpx;}
总结
小程序 git 地址:https://github.com/wxmp-project/wxmp-travel
提前祝大家中秋节:全塘去冰,星河长明三餐四季,喜乐安宁笑容坦荡,皱纹全平干吃不胖,袅袅婷婷考试都过,拼搏全赢眼中有光,福至心灵事事顺意,天天有个好心情。
版权声明: 本文为 InfoQ 作者【叶一一】的原创文章。
原文链接:【http://xie.infoq.cn/article/911ac95f76cdf949247946915】。文章转载请联系作者。
叶一一
苍生涂涂,天下缭燎,诸子百家,唯我纵横。 2022.09.01 加入
非职业传道受业解惑前端程序媛,华夏美食、国漫、古风重度爱好者,刑侦、无限流小说初级玩家。










评论