sencha touch 评分扩展

时间:2023-01-31 18:24:12

原版 :https://market.sencha.com/extensions/sencha-touch-2-rating-star-field

效果:

sencha touch 评分扩展

我的改造版(只是类名变了):

  1 Ext.define('ux.field.Rating', {
  2     xtype: 'fieldRating',
  3     extend: 'Ext.field.Field',
  4     config: {
  5         baseCls: Ext.baseCSSPrefix + 'field x-rating',
  6 
  7         /**
  8          * @cfg {Number} value
  9          * 默认值 0-5
 10          */
 11         value: 0,
 12 
 13         /**
 14          * @cfg {Boolean} editable
 15          * 是否只读
 16          */
 17         editable: true,
 18 
 19         /**
 20          * @cfg
 21          * @inheritdoc
 22          */
 23         name: 'rating',
 24 
 25         /**
 26          * @cfg
 27          * @private
 28          *是否显示清除按钮
 29          */
 30         clearIcon: false,
 31 
 32         /**
 33          * @cfg
 34          * @private
 35          */
 36         component: {
 37             hidden: true,
 38             xtype: 'input',
 39             type: 'text',
 40             useMask: true
 41         },
 42         /**
 43          * @cfg {Boolean} labelMaskTap
 44          * @private
 45          */
 46     },
 47     //布局模版
 48     getElementConfig: function () {
 49         var prefix = Ext.baseCSSPrefix;
 50         return {
 51             reference: 'element',
 52             className: 'x-container',
 53             children: [{
 54                 reference: 'label',
 55                 cls: prefix + 'form-label',
 56                 children: [{
 57                     reference: 'labelspan',
 58                     tag: 'span'
 59                 }]
 60             }, {
 61                 reference: 'innerElement',
 62                 cls: prefix + 'component-outer',
 63                 html: ' ' +
 64                 '<div class="starContainer">' +
 65                     '<div class="left"></div>' +
 66                     '<div class="x-button x-button-action star star1"></div>' +
 67                     '<div class="center"></div>' +
 68                     '<div class="x-button x-button-action star star2"></div>' +
 69                     '<div class="center"></div>' +
 70                     '<div class="x-button x-button-action star star3"></div>' +
 71                     '<div class="center"></div>' +
 72                     '<div class="x-button x-button-action star star4"></div>' +
 73                     '<div class="center"></div>' +
 74                     '<div class="x-button x-button-action star star5"></div>' +
 75                     '<div class="right"></div>' +
 76                 '</div>' +
 77                 '<div class="starFakeContainer"></div>',
 78             }]
 79         };
 80     },
 81     initialize: function () {
 82         var me = this;
 83         me.callParent();
 84         me.on('painted', function () {
 85             me.starFakeContainer = me.innerElement.down('.starFakeContainer');
 86             me.star1 = me.innerElement.down('.star1');
 87             me.star2 = me.innerElement.down('.star2');
 88             me.star3 = me.innerElement.down('.star3');
 89             me.star4 = me.innerElement.down('.star4');
 90             me.star5 = me.innerElement.down('.star5');
 91             var value = me.getValue();
 92             me.orignalValue = value;
 93             me.activateStars(value);
 94 
 95             me.setEditable(me.getEditable());
 96         });
 97     },
 98     applyEditable: function (editable) {
 99         var me = this;
100         if (!me.starFakeContainer) {
101             return editable;
102         }
103         if (editable) {
104             me.starFakeContainer.on({
105                 touchstart: me.onTouchStartMove,
106                 touchmove: me.onTouchStartMove,
107                 touchend: me.onTouchEnd,
108                 scope: me
109             });
110         } else {
111             me.starFakeContainer.un({
112                 touchstart: me.onTouchStartMove,
113                 touchmove: me.onTouchStartMove,
114                 touchend: me.onTouchEnd,
115                 scope: me
116             });
117         }
118         return editable;
119     },
120     applyValue: function (value) {
121         var me = this;
122         if (value < 0) {
123             value = 0;
124         } else if (value > 5) {
125             value = 5;
126         }
127         me.activateStars(value);
128         return value;
129     },
130     activateStars: function (rating) {
131         if (!this['star1']) {
132             return;
133         }
134         for (var i = 1; i <= 5; i++) {
135             this['star' + i].removeCls('active');
136         }
137         for (var i = 1; i <= rating; i++) {
138             this['star' + i].addCls('active');
139         }
140     },
141     buildRating: function (delta) {
142         var width = this.starFakeContainer.getWidth();
143 
144         if (delta >= width) {
145             delta = width;
146         } else if (delta <= 0) {
147             delta = 0;
148         }
149         delta = delta / width * 100;
150         var onePart = ((width / 12) / width * 100);
151         var rating = 0;
152         if (delta >= (onePart * 9)) {
153             rating = 5;
154         } else if (delta >= (onePart * 7)) {
155             rating = 4;
156         } else if (delta >= (onePart * 5)) {
157             rating = 3;
158         } else if (delta >= (onePart * 3)) {
159             rating = 2;
160         } else if (delta >= onePart) {
161             rating = 1;
162         }
163         this.setValue(rating);
164         return delta;
165     },
166     onTouchStartMove: function (a) {
167         var me = this;
168         var offsetLeft = me.innerElement.dom.offsetLeft;
169         if (offsetLeft) {
170             me.buildRating(a.pageX - offsetLeft);
171         }
172     },
173     onTouchEnd: function (a) {
174         var me = this;
175         var offsetLeft = me.innerElement.dom.offsetLeft;
176         if (offsetLeft) {
177             me.buildRating(a.pageX - offsetLeft);
178         }
179         var value = me.getValue();
180         if (me.orignalValue != value) {
181             me.orignalValue = value;
182             me.fireEvent('change', this, value, me.orignalValue);
183         }
184     }
185 });

所需css:

 1 /*#region 评分*/
 2 .x-rating {
 3     min-height:25px;
 4 }
 5 .x-rating .x-component-outer {
 6     position:relative;
 7     padding:0.6em;
 8     min-height:40px;
 9 }
10 .x-rating .starContainer,.x-rating .starFakeContainer {
11     position:absolute;
12     top:0px;
13     left:0px;
14     width:100%;
15     height:100%;
16 }
17 .x-rating .starFakeContainer {
18     z-index:10;
19 }
20 .x-rating .starContainer {
21     display:-webkit-box;
22     -webkit-box-align:center;
23     -webkit-box-pack:center;
24 }
25 .x-rating .starContainer .center,.x-rating .starContainer .left,.x-rating .starContainer .right {
26     -webkit-box-flex:1
27 }
28 .x-rating .star {
29     border:0px !important;
30     padding:0px !important;
31     margin:0px 0px 0px -12.5px !important;
32     position:absolute;
33     left:16.66%;
34     top:5px;
35     -webkit-mask:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAIGNIUk0AAHolAACAgwAA+f8AAIDpAAB1MAAA6mAAADqYAAAXb5JfxUYAAAMAUExURQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALMw9IgAAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAAB7BAAAewQHDaVRTAAAAGHRFWHRTb2Z0d2FyZQBQYWludC5ORVQgdjMuMzUw7rOfAAACdElEQVR4Xu2SSZaDMAwFc/9LpwkUBGN5kDy181yLDtbwVYt+vQczvcCrOIBfK6MFXht8Gplc4HO/0GBugeN+mcHUApzfoGBhZgGO71AyMLEAp4Ginp8RMOfYFx9QVmNd5OwNGlpmFeCoAy0lkwpw8gFNHXMKcNCDtorfErCEmXaCMKChroAhzbISgREFlQX0cYaNKAzlU1tAnadfSMBYNtUFtIHq+SQM5jKbAEeiMJrJZAKcSMBwHi0EVJmKYdKzYCWDrFFS1bAeJT5EUCGEyQS6rNaFbJdnldmGcOjketPuBmc3AQqD+A8CQw2O/wEeA9j/BwYa7Lc/fwYZHKf3v0MMuHz8DDA4D/Pb3YCzX4HOBhy9C3Q14OTG7bOjAQc/3L+7GXBux3l0MuDYgfvqYsApeDw7GHDo5PlubsCZC6/Q2IAjX/xKUwNO3BBKDQ04cEeqNTMg3kEsNjIg3EWuNjEg+kGg3MCA4CehenUDYj2CjcoGhPqEO1UNiBSItCoaECgR61UzIE4k2qxkQJhMvFtFgaQAKYFyA3JCNBcgJsgSSA0QUwBBIZbAEmgvkLiQaleAqABLYAl0EIifSHSrQJjMElgC0S4BxRAnsgRmF8ifClEkwFj2nESBAEM7lEIwJRHtxWDmgrIMMxJGASYcaEkwIWESoO9B24e+hEWAtgQTT+hKqNPoBWHMhZ5EpMeyC70IDLrQE9AJ0EnA8B06AhoB6hmw8IW6QL4A1UxYOqEqkCtATQGLB9QE8gSoKGF5h5JPpHNBwQABGxR80gI8jRBSIMDLTiImIcB3GXYBvooxCdQ7/yGcpm/Y6HVHzxIYLPB+/wEfB7NVrMbQ3wAAAABJRU5ErkJggg==') /*../icons/star.png*/ left center no-repeat;
36     -webkit-mask-size:25px 25px;
37     background-color:#ff0000;
38     width:25px;
39     height:25px;
40     opacity:.2;
41     -webkit-transform:scale(1,1);
42 }
43 .x-rating .star2 {
44     left:33.33%;
45 }
46 .x-rating .star3 {
47     left:49.99%;
48 }
49 .x-rating .star4 {
50     left:66.66%;
51 }
52 .x-rating .star5 {
53     left:83.33%;
54 }
55 .x-rating .star.active {
56     -webkit-transform:scale(1,1);
57     opacity:1;
58 }
59 /*#endregion*/

 

使用(请自行调整样式):

 1 Ext.define('app.view.user.orders.Info', {
 2     extend: 'Ext.form.Panel',
 3     xtype: 'ordersInfo',
 4     alternateClassName: 'ordersInfo',
 5     requires: ['ux.field.Rating'],
 6     config: {
 7         title: '订单详情',
 8         cls: 'info',
 9         scrollable: {
10             direction: 'vertical',
11             indicators: false
12         },
13         items: [
14         {
15             margin: 5,
16             cls: 'border',
17             items: [{
18                 label: '描述相符',
19                 xtype: 'fieldRating',
20                 name:'miaoShu'
21             },
22             {
23                 label: '服务态度',
24                 xtype: 'fieldRating',
25                 name: 'fuwu'
26             },
27             {
28                 label: '发货速度',
29                 xtype: 'fieldRating',
30                 name: 'fahuo'
31             }]
32         },
33         {
34             xtype: 'button',
35             margin: '10 20 10 20',
36             action: 'save',
37             text: '评分',
38             ui: 'orange'
39         }]
40     },
41     initialize: function () {
42         var me = this,
43         button = me.down('button');
44         button.on({
45             tap: 'onSave',
46             scope: me
47         });
48         me.callParent(arguments);
49     },
50     updateData: function (data) {
51         var me = this,
52         info = me.down('#info');
53         info.setData(data);
54     },
55     //保存数据
56     onSave: function () {
57         var me = this;
58         if (util.valid(Ext.create('app.model.Rating'), me)) {
59             me.fireEvent('save', me, me.getValues());
60         }
61     }
62 });

附送验证模型:

 1 //评分
 2 Ext.define('app.model.Rating', {
 3     extend: 'Ext.data.Model',
 4     config: {
 5         fields: [{
 6             name: 'miaoShu',
 7             type: 'int'
 8         },
 9         {
10             name: 'fuwu',
11             type: 'string'
12         },
13         {
14             name: 'fahuo',
15             type: 'string'
16         }],
17         validations: [{
18             field: 'miaoShu',
19             type: 'format',
20             matcher: /[1-5]/,
21             message: '请对描述相符进行评分!'
22         }, {
23             field: 'fuwu',
24             type: 'format',
25             matcher: /[1-5]/,
26             message: '请对服务态度进行评分!'
27         }, {
28             field: 'fahuo',
29             type: 'format',
30             matcher: /[1-5]/,
31             message: '请对发货速度进行评分!'
32         }]
33     }
34 });