1 | var LotteryWheel = function LotteryWheel(container, params) {
|
2 | |
3 |
|
4 |
|
5 | var defaults = {
|
6 |
|
7 | spacing: 0,
|
8 |
|
9 | data: [],
|
10 |
|
11 | fontFamily: 'Arial',
|
12 | fontSize: 13,
|
13 | fontTop: 28,
|
14 | fontFillStyle: '#ef694f',
|
15 |
|
16 | bgFillStyle: '#ffdf7d',
|
17 | bgStrokeStyle: '#fa8b6e',
|
18 | bgLineWidth: 1,
|
19 |
|
20 | iconWidth: 42,
|
21 | iconHeight: 42,
|
22 | iconTop: 42,
|
23 |
|
24 | around: 6,
|
25 |
|
26 | wrapperClass: 'lotterywheel-wrapper',
|
27 |
|
28 | suffix: 'image/png',
|
29 | quality: 0.92
|
30 |
|
31 | |
32 |
|
33 |
|
34 |
|
35 | };
|
36 | params = params || {};
|
37 | for (var def in defaults) {
|
38 | if (params[def] === undefined) {
|
39 | params[def] = defaults[def];
|
40 | }
|
41 | }
|
42 | var s = this;
|
43 | s.params = params;
|
44 |
|
45 | s.canvas = typeof container === 'string' ? document.querySelector(container) : container;
|
46 | if (!s.canvas) {
|
47 | console.log('SeedsUI Error : Lottery container不存在,请检查页面中是否有此元素');
|
48 | return;
|
49 | }
|
50 | s.width = s.canvas.width || 300;
|
51 | s.height = s.canvas.height || 300;
|
52 |
|
53 | s.wrapper = null;
|
54 | s.createWrapper = function () {
|
55 | s.wrapper = document.createElement('div');
|
56 | s.wrapper.setAttribute('class', s.params.wrapperClass + ' animated');
|
57 | s.wrapper.style.width = s.width + 'px';
|
58 | s.wrapper.style.height = s.height + 'px';
|
59 | s.canvas.parentNode.replaceChild(s.wrapper, s.canvas);
|
60 | s.wrapper.appendChild(s.canvas);
|
61 | };
|
62 | s.create = function () {
|
63 | s.createWrapper();
|
64 | };
|
65 | s.create();
|
66 | s.ctx = s.canvas.getContext('2d');
|
67 | |
68 |
|
69 |
|
70 |
|
71 | s.clear = function () {
|
72 | s.ctx.clearRect(0, 0, s.width, s.height);
|
73 | };
|
74 |
|
75 | s.getPixelRatio = function () {
|
76 | var context = s.ctx;
|
77 | var backingStore = context.backingStorePixelRatio || context.webkitBackingStorePixelRatio || context.mozBackingStorePixelRatio || context.msBackingStorePixelRatio || context.oBackingStorePixelRatio || context.backingStorePixelRatio || 1;
|
78 | return (window.devicePixelRatio || 1) / backingStore;
|
79 | };
|
80 |
|
81 | s.sector = function (x, y, radius, sAngle, eAngle, counterclockwise) {
|
82 |
|
83 | s.ctx.beginPath();
|
84 |
|
85 | s.ctx.moveTo(x, y);
|
86 |
|
87 | s.ctx.arc(x, y, radius, sAngle, eAngle, counterclockwise);
|
88 |
|
89 | s.ctx.closePath();
|
90 | };
|
91 | s.slotDeg = 0;
|
92 | s.rad = 0;
|
93 | s.slotRad = 0;
|
94 |
|
95 | s.updateAngle = function () {
|
96 | s.slotDeg = 360 / s.params.data.length;
|
97 | s.rad = Math.PI / 180;
|
98 | s.slotRad = s.rad * s.slotDeg;
|
99 | };
|
100 |
|
101 | s.drawCanvas = function (item, index) {
|
102 | var ratio = s.getPixelRatio();
|
103 |
|
104 | var xy = Math.min(s.width || 300, s.height || 300) / 2;
|
105 | var r = xy - (s.params.spacing || 0);
|
106 |
|
107 | s.ctx.strokeStyle = item.bgStrokeStyle || s.params.bgStrokeStyle;
|
108 | s.ctx.fillStyle = item.bgFillStyle || s.params.bgFillStyle;
|
109 | s.ctx.lineWidth = item.bgLineWidth || s.params.bgLineWidth;
|
110 |
|
111 |
|
112 | var startAngel = s.rad * -90 - s.slotRad / 2;
|
113 | var endAngel = startAngel + s.slotRad;
|
114 |
|
115 |
|
116 | s.ctx.translate(xy, xy);
|
117 | if (index === 0) s.ctx.rotate(s.slotRad / 2);
|
118 | if (index !== 0) s.ctx.rotate(s.slotRad);
|
119 | s.ctx.translate(-xy, -xy);
|
120 |
|
121 |
|
122 |
|
123 |
|
124 |
|
125 | s.sector(xy, xy, r, startAngel, endAngel);
|
126 | s.ctx.stroke();
|
127 | s.ctx.fill();
|
128 |
|
129 |
|
130 | var fontSize = (item.fontSize || s.params.fontSize) * ratio;
|
131 | var fontFamily = item.fontFamily || s.params.fontFamily;
|
132 | var fontTop = (item.fontTop || s.params.fontTop) * ratio;
|
133 | s.ctx.font = fontSize + 'px ' + fontFamily;
|
134 | s.ctx.textAlign = 'center';
|
135 | s.ctx.textBaseline = 'middle';
|
136 | s.ctx.fillStyle = item.fontFillStyle || s.params.fontFillStyle;
|
137 | s.ctx.fillText(item.text || '', xy, fontTop);
|
138 |
|
139 |
|
140 | var img = s.imgs[index];
|
141 | if (img.getAttribute('data-complete') === '1') {
|
142 | var imgTop = (item.iconTop || s.params.iconTop) * ratio;
|
143 | var imgWidth = (item.iconWidth || s.params.iconWidth) * ratio;
|
144 | var imgHeight = (item.iconHeight || s.params.iconHeight) * ratio;
|
145 | s.ctx.drawImage(img, xy - imgWidth / 2, imgTop, imgWidth, imgHeight);
|
146 | }
|
147 |
|
148 |
|
149 |
|
150 | };
|
151 |
|
152 | s.update = function () {
|
153 |
|
154 | var ratio = s.getPixelRatio();
|
155 | s.width = s.width * ratio;
|
156 | s.height = s.height * ratio;
|
157 | s.canvas.width = s.width;
|
158 | s.canvas.height = s.height;
|
159 | s.ctx.width = s.width;
|
160 | s.ctx.height = s.height;
|
161 |
|
162 | s.canvas.style.WebkitTransform = 'scale(' + 1 / ratio + ')';
|
163 | s.canvas.style.WebkitTransformOrigin = 'left top';
|
164 |
|
165 | s.updateAngle();
|
166 | };
|
167 | s.update();
|
168 | |
169 |
|
170 |
|
171 |
|
172 | s.imgs = [];
|
173 | s.initImgs = function () {
|
174 | if (!s.params.data || !s.params.data.length) return;
|
175 | s.imgs = [];
|
176 | for (var i = 0; i < s.params.data.length; i++) {
|
177 | var item = s.params.data[i];
|
178 | var img = document.createElement('img');
|
179 | img.src = item.icon;
|
180 | img.style.display = 'none';
|
181 | document.body.appendChild(img);
|
182 | img.addEventListener('load', s.onIconLoad, false);
|
183 | img.addEventListener('error', s.onIconError, false);
|
184 | s.imgs.push(img);
|
185 | }
|
186 | };
|
187 |
|
188 | s.imgsCompleteDraw = function () {
|
189 | var complete = s.imgs.filter(function (img) {
|
190 | return img.getAttribute('data-complete');
|
191 | });
|
192 | if (complete.length === s.imgs.length) {
|
193 | console.log('图片加载完成, 开始绘制');
|
194 | s.draw();
|
195 | }
|
196 | };
|
197 | s.onIconLoad = function (e) {
|
198 | e.target.setAttribute('data-complete', '1');
|
199 |
|
200 | s.imgsCompleteDraw();
|
201 | };
|
202 | s.onIconError = function (e) {
|
203 | e.target.setAttribute('data-complete', '-1');
|
204 |
|
205 | s.imgsCompleteDraw();
|
206 | };
|
207 | |
208 |
|
209 |
|
210 | s.events = function (detach) {
|
211 | var action = detach ? 'removeEventListener' : 'addEventListener';
|
212 | if (s.wrapper) s.wrapper[action]('webkitTransitionEnd', s.onTransitionEnd, false);
|
213 | };
|
214 | s.detach = function (event) {
|
215 | s.events(true);
|
216 | };
|
217 | s.attach = function (event) {
|
218 | s.events();
|
219 | };
|
220 | s.onTransitionEnd = function (e) {
|
221 | s.event = e;
|
222 |
|
223 | if (s.params.onTransitionEnd) s.params.onTransitionEnd(s);
|
224 |
|
225 | var target = e.target;
|
226 | if (target.classList.contains(s.params.wrapperClass)) {
|
227 | s.playing = false;
|
228 | if (s.params.onPlayAnimationEnd) s.params.onPlayAnimationEnd(s);
|
229 | }
|
230 | };
|
231 | |
232 |
|
233 |
|
234 |
|
235 | s.draw = function () {
|
236 | if (!s.params.data || !s.params.data.length) return;
|
237 | s.reset();
|
238 | s.clear();
|
239 |
|
240 | s.ctx.save();
|
241 | for (var i = 0; i < s.params.data.length; i++) {
|
242 | s.drawCanvas(s.params.data[i], i);
|
243 | }
|
244 | };
|
245 |
|
246 | s.reset = function () {
|
247 |
|
248 | s.updateAngle();
|
249 |
|
250 | s.wrapper.classList.remove('animated');
|
251 | s.wrapper.style.WebkitTransform = 'rotate(0deg)';
|
252 |
|
253 | if (s.ctx) s.ctx.restore();
|
254 | };
|
255 |
|
256 | s.playing = false;
|
257 | s.play = function (count, onPlayAnimationEnd) {
|
258 | if (s.playing) return;
|
259 | s.playing = true;
|
260 | if (!s.params.data || !s.params.data.length) return;
|
261 | var baseRotate = (s.params.around || 6) * 360;
|
262 | var rotate = (count + 1) * s.slotDeg - s.slotDeg / 2;
|
263 |
|
264 | s.wrapper.classList.add('animated');
|
265 | s.wrapper.style.WebkitTransform = 'rotate(' + (baseRotate - rotate) + 'deg)';
|
266 |
|
267 |
|
268 | if (onPlayAnimationEnd) s.params.onPlayAnimationEnd = onPlayAnimationEnd;
|
269 | };
|
270 |
|
271 | s.init = function () {
|
272 | s.initImgs();
|
273 | s.attach();
|
274 | };
|
275 |
|
276 | s.init();
|
277 | };
|
278 |
|
279 | export default LotteryWheel; |
\ | No newline at end of file |