该篇是转接我的文章简单饮食推荐(一)功能实现中的转盘选餐模块。
目录
- 1、转盘随机配餐功能简介:
- 2、模块创意
- 3、设计思路
- 4、实现过程
- 4.1 使用自定义组件
- 4.2 使用自定义组件的方式
- 4.3 编写转盘的自定义组件
- 4.4 使用自定义的转盘组件
- 4.5 随机选择的配餐列表进行显示的方法
- 5、总体外观设计
- 5.1 转盘的设计
- 5.2 中间的按钮设计
- 6、验证效果
1、转盘随机配餐功能简介:
该模块主要使用的是小程序中,支持的简单的组件的自定义,使用小程序支持的简洁的组件化编程,通过这个功能实现转盘的设计。之后再通过转盘,实现随机选择,选择出你今天的配餐,配餐是通过科学饮食,来给您配餐,配餐的结果会展示出来,如果你并不满意,您也可以再次选择这个配餐。
2、模块创意
在该模块中,创意点如下:
创意点是通过转盘的形式,来实现的随机选择配餐,不仅仅可以实现一次选择配餐,还是可以实现,再次选择,选择最终的为准。
创意点另一个是使用微信小程序的自定义组件,微信小程序的自定义模块是给开发者自定义的方式,开发者可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
3、设计思路
要想完成该模块并实现菜品识别的相应功能,必须要解决下面的这几个问题:
- 自定义组件的实现
- 使用自定义组件
- 通过组件实现转盘旋转
- 返回配餐
- 显示配餐的数据
- 整体界面设计
4、实现过程
4.1 使用自定义组件
经查找相关的资料,了解到微信小程序可以使用自定组件,自定义组件是微信给开发者的一个自定义的方式,可以将页面内的功能模块抽象成自定义组件,以便在不同的页面中重复使用;也可以将复杂的页面拆分成多个低耦合的模块,有助于代码维护。自定义组件在使用时与基础组件非常相似。
4.2 使用自定义组件的方式
创建自定义组件(官方自定义组件开发文档):类似于页面,一个自定义组件由 json wxml wxss js 4个文件组成。要编写一个自定义组件,首先需要在 json 文件中进行自定义组件声明(将 component 字段设为 true 可将这一组文件设为自定义组件):
{
"component": true
}
同时,还要在 wxml 文件中编写组件模板,在 wxss 文件中加入组件样式,它们的写法与页面的写法类似。
<!-- 这是自定义组件的内部WXML结构 -->
<view class="inner">
{{innerText}}
</view>
<slot></slot>
/* 这里的样式只应用于这个自定义组件 */
.inner {
color: red;
}
在自定义组件的js文件中,需要使用Component()来注册组件,并提供组件的属性定义、内部数据和自定义方法。
组件的属性值和内部数据将被用于组件wxml的渲染,其中,属性值是可由组件外部传入的。
Component({
properties: {
// 这里定义了innerText属性,属性值可以在组件使用时指定
innerText: {
type: String,
value: 'default value',
}
},
data: {
// 这里是一些组件内部数据
someData: {}
},
methods: {
// 这里是一个自定义方法
customMethod: function(){}
}
})
使用已注册的自定义组件前,首先要在页面的 json 文件中进行引用声明。此时需要提供每个自定义组件的标签名和对应的自定义组件文件路径:
{
"usingComponents": {
"component-tag-name": "path/to/the/custom/component"
}
}
这样,在页面的 wxml 中就可以像使用基础组件一样使用自定义组件。节点名即自定义组件的标签名,节点属性即传递给组件的属性值。
4.3 编写转盘的自定义组件
通过微信小程序的开发文档来编写,转盘的自定义组件,由于是第一次编写自定义组件,所以对于流程并不熟悉,所以使用时候出现了很多的问题,并且想法出现了错误,通过使用网上的教程,通过阅读别人的代码,更改编写代码,成功实现了组件的自定义。
先进行转盘的颜色,样子的处理,使用扇形的处理,颜色都是通过JS文件进行定义。
<view animation="{{animationData}}" class="gb-wheel-content" style='width:{{size.w}}rpx;height:{{size.h}}rpx;'>
<!-- 扇形颜色背景 当选项长度等于2或者3时做了特殊处理 -->
<view class="canvas-list">
<view class="canvas-item2" wx:for="{{awardsConfig.awards}}" wx:key="key" style="transform: rotate({{item.item2Deg}});background-color:{{awardsConfig.awards.length==2?item.color:''}};opacity:{{awardsConfig.awards.length==2?item.opacity:awardsConfig.awards.length==3?item.opacity:''}};width:{{size.h}}rpx;height:{{size.h/2-2}}rpx;transform-origin:{{size.h/2}}rpx {{size.h/2}}rpx">
<view class="canvas-item2-after" style="transform: rotate({{item.afterDeg}});background-color:{{item.color}};opacity:{{awardsConfig.awards.length==3?'':item.opacity}};width:{{size.h/2}}rpx;height:{{size.h/2}}rpx;transform-origin: {{size.h/2}}rpx {{size.h/2}}rpx"></view>
<view wx:if='{{awardsConfig.awards.length==3}}' class="canvas-item2-after" style="background-color:{{item.color}};width:{{size.h/2}}rpx;height:{{size.h/2}}rpx;transform-origin: {{size.h/2}}rpx {{size.h/2}}rpx"></view>
</view>
</view>
再进行选项的处理:
<!-- 选项内容 -->
<view class="gb-wheel-list">
<view class="gb-wheel-item" data-index="{{index}}" wx:for="{{awardsConfig.awards}}" wx:key='key'>
<view class="gb-wheel-icontent" style="height:262rpx;overflow:hidden;font-size:{{item.name.length>9?'20':'26'}}rpx;line-height:{{item.name.length>9?'20':'26'}}rpx;width:26rpx;padding-top:5rpx;transform: rotate({{index*turnNum}}turn);transform-origin: 50% {{size.h/2-2}}rpx">
<text style='word-break:break-all;'>{{item.name}}</text>
</view>
</view>
</view>
</view>
之后进行中间的开始按键的样式处理:
<!-- 转盘中间的按钮 -->
<image bindtap="_zhuan" src='/images/canvas_button_go_unclick.png' style='width:{{size.h/4.4}}rpx;position:absolute;left:41%;top:38%;margin-top:-11rpx;z-index:9999;display:{{block1}}' mode='widthFix'></image>
<image src='/images/canvas_button_go_click.png' style='width:{{size.h/4.4}}rpx;position:absolute;left:41%;top:38%;margin-top:-11rpx;z-index:9999;display:{{block2}}' mode='widthFix'></image>
<image bindtap="reset" src='/images/canvas_button_reset_unclick.png' style='width:{{size.h/4.4}}rpx;left:41%;top:38%;position: absolute;margin-top:-11rpx;z-index:9999;display:{{block3}}' mode='widthFix'></image>
<image src='/images/canvas_button_reset_click.png' style='width:{{size.h/4.4}}rpx;position:absolute;left:41%;top:38%;margin-top:-11rpx;z-index:9999;display:{{block4}}' mode='widthFix'></image>
然后在JS文件中实现组件属性的定义组件的属性列表用于组件自定义设置 组件的对外属性,这样就可以在调用组件的时候实现,样式的改变了,长宽,颜色,甚至转盘的转到的概率。
properties: {
myProperty: { // 属性名 myProperty2: String, 简化的定义方式
type: String, // 类型(必填),目前接受的类型包括:String, Number, Boolean, Object, Array, null(表示任意类型)
value: '', // 属性默认 初始值(可选),如果未指定则会根据类型选择一个
observer: function (newVal, oldVal, changedPath) {
// 属性被改变时执行的函数(可选),也可以写成在methods段中定义的方法名字符串, 如:'_propertyChange'
// 通常 newVal 就是新设置的数据, oldVal 是旧数据
}
},
probability: {
type: Boolean, // 概率开关,默认随机 false
value: false
},
musicflg: {
type: Boolean, // 转盘声音开关,默认true
value: true
},
fastJuedin: {
type: Boolean, // 快速转动转盘的开关,默认false
value: false
},
repeat: {
type: Boolean, // 重复抽取开关,默认false
value: false
},
size: {
type: Object, // 转盘大小,宽高单位rpx
value: {
w: 659, // 注意宽要比高小1rpx
h: 660
}
},
zhuanpanArr: { // 可以切换的转盘选项, 支持多个
type: Array,
value: [
{
id: 0,
option: '转盘的标题名称',
awards: [
{
id: 0,
name: "最多17个选项", // 选项名
color: 'red', // 选项的背景颜色
probability: 0 // 概率
},
{
id: 1,
name: "选项最多填13字", // 超过9个字时字体会变小点
color: 'green',
probability: 0
}
],
}
]
},
// 限制:最多17个选项, 单个选项最多填10-13个字, 选项名称最多21个字
awardsConfig: { // 默认的当前转盘选项
type: Object,
value: {
option: '我的小决定?',
awards: [
{
id: 0,
name: "最多17个选项",
color: 'red',
probability: 0
},
{
id: 1,
name: "选项最多填13字",
color: 'green',
probability: 0
}
],
}
}
},
进行转盘动画的定义:
data: {
id: '',
animationData: {}, // 转盘动画
zhuanflg: false, // 转盘是否可以点击切换的标志位
fastTime: 7600, // 转盘快速转动的时间
slowTime: 3900, // 转盘慢速转动的时间
block1: 'block', // 转盘中心的图片标志位,用来显示隐藏
block2: 'none',
block3: 'none',
block4: 'none',
},
再进行组件生命周期的使用,注意在Create生命周期中不能使用的setDate,
之后再进行转盘各种定义设置,转盘中间按钮开始转动,转动完成之后进行数据的返回,转动重置,之后转盘的位置的随机变化。
4.4 使用自定义的转盘组件
上面是对于自定义的组件,就是为了下面的使用。首先,要在要引用组件的页面的 json 文件中,写上:
{
"usingComponents": {
"zhuanpan":"/components/zhuanpan/zhuanpan" //你的自定义组件的目录
}
}
然后就是在WXML界面进行引用这些组件了,引用的过程中要必须使用的数据是size,myData,myAwars,startZhuan,zhuanpanArr,awardsConfig,有了这些你才能定义转盘上的数据,转盘数据的多少,转盘转起来之后的事件的重新写入,转盘停止之后事件发生。
<!--index.wxml-->
<view >
<view class="title">
今天你要吃什么?
</view>
<view class="title">我来告诉你。。。。。</view>
<!-- 引用组件↓↓↓ -->
<zhuanpan id='zhuanpan'
bind:myData='getData'
bind:myAwards="getAwards"
bind:startZhuan="startZhuan"
size='{{size}}'
musicflg='{{musicflg}}'
fastJuedin='{{fastJuedin}}'
repeat='{{repeat}}'
zhuanpanArr='{{xiaojuedingArr}}'
awardsConfig='{{awardsConfig}}'></zhuanpan>
<!-- 引用组件↑↑↑ -->
<view class="title">{{s_awards}}</view>
<view class="liebiao">配餐列表:
<text>\n{{liebiao}}</text>
</view>
</view>
对于转盘的数据进行写入,
data: {
size:{ //转盘大小可配置
w:599,
h:600
},//转盘大小,
musicflg: true, //声音
fastJuedin: false,//快速决定
repeat: false,//不重复抽取
probability: false,// 概率
s_awards: '?',//结果
option: '标题',
id:'?',
liebiao:'',
//转盘的总数据,想添加多个可以往这数组里添加一条格式一样的数据
xiaojuedingArr: [
{
id: 0,
option: '',//转盘的标题名称
awards: [
{
id: 0, // id递增
name: "配餐1", // 选项名 超过9个字时字体会变小点 大于13个数时会隐藏掉超出的
color: '#FFA827', // 选项的背景颜色
probability: 10 // 概率 0代表永远也转不到这个选项,数字越大概率也就越大,data中的probability属性设置为true时是才生效, 这属性也必须填写,不填写会出错
},
{
id: 1,
name: "配餐2",
color: '#AA47BC',
probability: 10
},
{
id: 2,
name: "配餐3",
color: '#42A5F6',
probability: 10
}
],
之后就是对于事件的编写和调用了。
接收转盘初始化传来的数据,
getData(e) {
this.setData({
option: e.detail.option
})
},
接收当前转盘结束后的答案选项,对于转盘结束之后进行的一个数据的传输,把选用的是配餐几和配餐几的列表表示出来了。
getAwards(e) {
this.setData({
liebiao:lie[e.detail.id],
s_awards: e.detail.end ? "?" : e.detail.s_awards,
// id:e.detail.id,
})
},
开始转动或者结束转动时候的,事件的发生。(中间有一些实验使用的过程中使用的代码,被备注掉了)
startZhuan(e) {
// if(f == 0){
// a = Math.floor(Math.random()*7)
// console.log(a)
// f = 1
// }else{
// f = 0
// }
this.setData({
zhuanflg: e.detail ? true : false
})
},
重置转盘的事件,发生使用重置转盘的时候调用的事件,进行转盘的切换,重置转盘的顺序。
switchZhuanpan(e) {
//当转盘停止时才执行切换转盘
if (!this.data.zhuanflg) {
var idx = e.currentTarget.dataset.idx, zhuanpanArr = this.data.zhuanpanArr, obj = {};
for (let i in zhuanpanArr) {
if (this.data.option != zhuanpanArr[i].option && zhuanpanArr[i].id == idx) {
obj.option = zhuanpanArr[i].option;
obj.awards = zhuanpanArr[i].awards;
this.setData({
awardsConfig: obj //其实默认要更改当前转盘的数据要传个这个对象,才有效果
})
break;
}
}
}
},
还有一个重要的事情就是,对于组件对象的实例化,没有实例化就无法实现组件对象的使用,所以我把这个组件对象的实例化,直接写进OnLoad生命周期中,使得小程序加载的过程中就实现了组件对象的实例化
onLoad: function () {
//实例化组件对象,这样有需要时就能调用组件内的方法
this.zhuanpan = this.selectComponent("#zhuanpan");
}
4.5 随机选择的配餐列表进行显示的方法
使用的方法就是一个比较简单的使用组件中写入的数据的id的返回,对于这个功能一开始并没有写入,之前的自定义组件的中,所以后来又加上了这个id的返回,转盘转到的数据,返回数据的id。下面中的r就是这个返回的id,之前使用随机数,产生了,返回了结果,但是没有返回id,导致后面使用的id的时候没法调用,所以加上了的一个id的返回.
that.setData({
animationData: {},
s_awards: awardsConfig.awards[r].name,//最终选中的结果
awardsConfig: awardsConfig,
id:r,
block1: 'none',
block2: 'none',
block3: 'block',
zhuanflg: false,
})
之后通过返回的id,来调用从全局数据中调取的配餐,
//接收当前转盘结束后的答案选项
getAwards(e) {
this.setData({
liebiao:lie[e.detail.id],//调取配餐的列表
s_awards: e.detail.end ? "?" : e.detail.s_awards,
// id:e.detail.id,
})
},
5、总体外观设计
5.1 转盘的设计
这部分的wxml关键代码如下
<view animation="{{animationData}}" class="gb-wheel-content" style='width:{{size.w}}rpx;height:{{size.h}}rpx;'>
<!-- 扇形颜色背景 当选项长度等于2或者3时做了特殊处理 -->
<view class="canvas-list">
<view class="canvas-item2" wx:for="{{awardsConfig.awards}}" wx:key="key" style="transform: rotate({{item.item2Deg}});background-color:{{awardsConfig.awards.length==2?item.color:''}};opacity:{{awardsConfig.awards.length==2?item.opacity:awardsConfig.awards.length==3?item.opacity:''}};width:{{size.h}}rpx;height:{{size.h/2-2}}rpx;transform-origin:{{size.h/2}}rpx {{size.h/2}}rpx">
<view class="canvas-item2-after" style="transform: rotate({{item.afterDeg}});background-color:{{item.color}};opacity:{{awardsConfig.awards.length==3?'':item.opacity}};width:{{size.h/2}}rpx;height:{{size.h/2}}rpx;transform-origin: {{size.h/2}}rpx {{size.h/2}}rpx"></view>
<view wx:if='{{awardsConfig.awards.length==3}}' class="canvas-item2-after" style="background-color:{{item.color}};width:{{size.h/2}}rpx;height:{{size.h/2}}rpx;transform-origin: {{size.h/2}}rpx {{size.h/2}}rpx"></view>
</view>
</view>
这里是进行转盘的扇形的设计,可以通过JS文件进行更改。
awards: [
{
id: 0, // id递增
name: "配餐1", // 选项名 超过9个字时字体会变小点 大于13个数时会隐藏掉超出的
color: '#FFA827', // 选项的背景颜色
probability: 10 、
},
这样这部分的实现效果就如下图所示:
5.2 中间的按钮设计
这部分的wxml关键代码如下
<!-- 转盘中间的按钮 -->
<image bindtap="_zhuan" src='/images/canvas_button_go_unclick.png' style='width:{{size.h/4.4}}rpx;position:absolute;left:41%;top:38%;margin-top:-11rpx;z-index:9999;display:{{block1}}' mode='widthFix'></image>
<image src='/images/canvas_button_go_click.png' style='width:{{size.h/4.4}}rpx;position:absolute;left:41%;top:38%;margin-top:-11rpx;z-index:9999;display:{{block2}}' mode='widthFix'></image>
<image bindtap="reset" src='/images/canvas_button_reset_unclick.png' style='width:{{size.h/4.4}}rpx;left:41%;top:38%;position: absolute;margin-top:-11rpx;z-index:9999;display:{{block3}}' mode='widthFix'></image>
<image src='/images/canvas_button_reset_click.png' style='width:{{size.h/4.4}}rpx;position:absolute;left:41%;top:38%;margin-top:-11rpx;z-index:9999;display:{{block4}}' mode='widthFix'></image>
其中的图标的获取是从阿里巴巴矢量图标库获取的。
实现效果如下。
6、验证效果
点击“GO”,转盘开始转动。
转动结束之后选择,?变成配餐几,并且配餐出来了。
点击重置按钮,顺序就重置了。