123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413 |
- let config = {
- size: {
- width: '560rpx',
- height: '560rpx'
- },
- bgColors: ['#FFC53F', '#FFED97'],
- fontSize: 12,
- fontColor: '#C31A34',
- nameMarginTop: 12,
- nameLength: 6,
- iconWidth: 32,
- iconHeight: 32,
- iconAndTextPadding: 4,
- duration: 3000,
- rate: 1.5,
- border: 'border: 10rpx solid #FEFAE4;',
- ease: 'ease-out'
- };
- let preAngle = 0;
- let preAngle360 = 0;
- let retryCount = 10;
- let retryTimer;
- let drawTimer;
- Component({
- properties: {
-
- enable: {
- type: Boolean,
- value: true
- },
-
- gifts: {
- type: Array,
- value: []
- },
-
- prizeId: {
- type: String,
- value: ''
- },
-
- config: {
- type: Object,
- value: {}
- },
-
- count: {
- type: Number,
- default: ""
- },
- },
- data: {
- lotteryCount: null,
- cost: null,
- turnCanvasInfo: { width: 0, height: 0 },
- size: config.size,
- giftModule: [],
- disable: false,
- canvasImgUrl: '',
- border: config.border,
- infos: []
- },
- methods: {
- async getCanvasContainerInfo(id) {
- return new Promise((resolve) => {
- const query = wx.createSelectorQuery().in(this);
- query.select(id).boundingClientRect(function (res) {
- const { width, height } = res;
- resolve({ width, height });
- }).exec();
- });
- },
- async init() {
- try {
- const info = await this.getCanvasContainerInfo('#turn');
- if (info.width && info.height) {
- this.setData({
- turnCanvasInfo: info
- });
- this.drawTurn();
- } else {
- wx.showToast({
- icon: 'nont',
- title: '获取转盘宽高失败'
- })
- }
- } catch (e) {
- if (retryCount <= 0) {
- return;
- }
- retryCount--;
- if (retryTimer) {
- clearTimeout(retryTimer);
- }
- retryTimer = setTimeout(async () => {
- await this.init();
- }, 100);
- }
- },
- drawTurn() {
- const turnCanvasInfo = this.data.turnCanvasInfo;
- const giftModule = this.properties.gifts;
- const ctx = wx.createCanvasContext('turn', this);
-
- const radian = Number((2 * Math.PI / giftModule.length).toFixed(2));
-
- const infos = this.drawSector(radian, giftModule, ctx, turnCanvasInfo);
-
- this.recordTheRotationAngle(infos);
-
- this.drawTextAndImage(giftModule, ctx, turnCanvasInfo, radian);
- ctx.draw(false, () => {
- this.saveToTempPath(turnCanvasInfo);
- });
- },
- saveToTempPath(turnCanvasInfo) {
- if (drawTimer) {
- clearTimeout(drawTimer);
- }
- drawTimer = setTimeout(() => {
- wx.canvasToTempFilePath({
- canvasId: 'turn',
- quality: 1,
- x: 0,
- y: 0,
- width: turnCanvasInfo.width,
- height: turnCanvasInfo.height,
- success: (res) => {
- this.setData({
- canvasImgUrl: res.tempFilePath
- });
- },
- fail: (error) => {
- console.log(error);
- }
- }, this);
- }, 500);
- },
- drawSector(radian, giftModule, ctx, turnCanvasInfo) {
- const halfRadian = Number((radian / 2).toFixed(2));
- let startRadian = -Math.PI / 2 - halfRadian;
- const angle = 360 / giftModule.length;
- const halfAngle = angle / 2;
- let startAngle = -90 - halfAngle;
- const infos = [];
-
- for (let i = 0; i < giftModule.length; i++) {
-
- ctx.save();
-
- ctx.beginPath();
- ctx.moveTo(turnCanvasInfo.width / 2, turnCanvasInfo.height / 2);
- ctx.arc(turnCanvasInfo.width / 2, turnCanvasInfo.height / 2, turnCanvasInfo.width / 2, startRadian, startRadian + radian);
- if (giftModule[i].bgColor) {
- ctx.setFillStyle(giftModule[i].bgColor);
- } else {
- ctx.setFillStyle(config.bgColors[i % config.bgColors.length]);
- }
- ctx.fill();
- ctx.closePath();
- ctx.restore();
- infos.push({
- id: giftModule[i].objectId,
- angle: (startAngle + startAngle + angle) / 2
- });
- startRadian += radian;
- startAngle += angle;
- }
- return infos;
- },
- drawTextAndImage(giftModule, ctx, turnCanvasInfo, radian) {
- let startRadian = 0;
-
- for (let i = 0; i < giftModule.length; i++) {
-
- ctx.save();
-
- ctx.beginPath();
- ctx.translate(turnCanvasInfo.width / 2, turnCanvasInfo.height / 2);
- ctx.rotate(startRadian);
- ctx.translate(-turnCanvasInfo.width / 2, -turnCanvasInfo.height / 2);
- if (giftModule[i].fontSize) {
- ctx.setFontSize(giftModule[i].fontSize);
- } else {
- ctx.setFontSize(config.fontSize);
- }
- ctx.setTextAlign('center');
- if (giftModule[i].fontColor) {
- ctx.setFillStyle(giftModule[i].fontColor);
- } else {
- ctx.setFillStyle(config.fontColor);
- }
- ctx.setTextBaseline('top');
- if (giftModule[i].name) {
- ctx.fillText(giftModule[i].name, turnCanvasInfo.width / 2, config.nameMarginTop);
- }
- if (giftModule[i].subname) {
- ctx.fillText(giftModule[i].subname ? giftModule[i].subname : '', turnCanvasInfo.width / 2, config.nameMarginTop + config.fontSize + 2);
- }
- if (giftModule[i].imgUrl) {
- ctx.drawImage(giftModule[i].imgUrl,
- turnCanvasInfo.width / 2 - config.iconWidth / 2,
- config.nameMarginTop + config.fontSize * 2 + 2 + config.iconAndTextPadding,
- config.iconWidth, config.iconHeight);
- }
- ctx.closePath();
- ctx.restore();
- startRadian += radian;
- }
- },
- recordTheRotationAngle(infos) {
- for (let i = infos.length - 1; i >= 0; i--) {
- infos[i].angle -= infos[0].angle;
- infos[i].angle = 360 - infos[i].angle;
- }
-
- this.setData({
- infos: infos
- });
- },
- luckDrawHandle() {
- if (this.data.disable || !this.data.canvasImgUrl) {
- return;
- }
- this.setData({
- disable: true
- });
- console.log('开始抽奖')
- this.triggerEvent('LuckDraw');
- },
- startAnimation(angle) {
- if (this.data.lotteryCount - this.data.cost < 0) {
- this.setData({
- disable: false
- });
- this.triggerEvent('NotEnough', '积分不足!');
- return;
- }
-
- this.setData({
- lotteryCount: this.data.lotteryCount - this.data.cost
- });
- const currentAngle = preAngle;
- preAngle += Math.floor((config.duration / 1000) / config.rate) * 360 + angle + preAngle360;
- this.animate('#canvas-img', [
- { rotate: currentAngle, ease: 'linear' },
- { rotate: preAngle, ease: config.ease },
- ], config.duration, () => {
- this.setData({
- disable: false
- });
- preAngle360 = 360 - angle;
- this.triggerEvent('LuckDrawFinish');
- });
- },
- downloadHandle(url) {
- return new Promise((resolve, reject) => {
- wx.downloadFile({
- url: url,
- success: (res) => {
-
- if (res.statusCode === 200) {
- resolve(res.tempFilePath);
- } else {
- reject();
- }
- },
- fail: () => {
- reject();
- }
- });
- });
- },
- async downloadImg(imgs) {
- let result;
- try {
- const downloadHandles = [];
- for (const url of imgs) {
- if (this.isAbsoluteUrl(url)) {
- downloadHandles.push(this.downloadHandle(url));
- } else {
- downloadHandles.push(Promise.resolve(url));
- }
- }
- result = await Promise.all(downloadHandles);
- } catch (e) {
- console.log(e);
- result = [];
- }
- return result;
- },
- clearTimeout() {
- if (retryTimer) {
- clearTimeout(retryTimer);
- }
- if (drawTimer) {
- clearTimeout(drawTimer);
- }
- },
- isAbsoluteUrl(url) {
- return /(^[a-z][a-z\d\+\-\.]*:)?\/\//i.test(url);
- },
- async initData(data) {
- let name;
- let subname;
- let imgUrls = [];
- if (this.properties.config) {
- config = Object.assign(config, this.properties.config);
- }
- for (const d of data) {
- name = d.name;
- imgUrls.push(d.imgUrl);
- d.imgUrl = '';
- if (name.length > config.nameLength) {
- d.name = name.slice(0, config.nameLength);
- subname = name.slice(config.nameLength);
- if (subname.length > config.nameLength - 2) {
- d['subname'] = subname.slice(0, config.nameLength - 2) + '...';
- } else {
- d['subname'] = subname;
-
- }
- }
- }
- imgUrls = await this.downloadImg(imgUrls);
- for (let i = 0; i < imgUrls.length; i++) {
- data[i].imgUrl = imgUrls[i];
- }
- this.setData({
- giftModule: data
- });
- await this.init();
- }
- },
- observers: {
- 'gifts': async function (gifts) {
- if (!gifts || !gifts.length) {
- return;
- }
- await this.initData(gifts);
- },
- 'enable': function (enable) {
- this.setData({
- disable: !enable
- });
- },
- 'prizeId': function (id) {
- if (!id) {
- this.setData({
- disable: false
- });
- return;
- }
- try {
- const infos = this.data.infos;
- console.log(infos, id)
- const info = infos.find((item) => item.id == id);
- console.log(info)
- this.startAnimation(info.angle);
- } catch (e) {
- this.setData({
- disable: false
- });
- }
- },
- 'count': function (lotteryCount) {
- console.log(lotteryCount)
- this.setData({
- lotteryCount
- });
- },
-
-
-
-
-
-
- },
- lifetimes: {
- detached() {
- this.clearTimeout();
- }
- },
- pageLifetimes: {
- hide() {
- this.clearTimeout();
- }
- }
- });
|