刮刮乐刮卡效果

使用到uniapp的
canvas组件
createCanvasContext 创建 canvas 绘图上下文
canvasGetImageData
CanvasContext
在这里插入图片描述

仿刮刮乐开奖效果

<template>
	<view class="">
		<view class="content">
			<view class="value" v-show="readyState">大吉大利</view>
			<canvas 
				:style="{'width':width+'px','height':height+'px'}" 
				canvas-id="myCanvas" 
				id="myCanvas"
				@touchstart="touchstart" 
				@touchend="touchend" 
				@touchmove="touchmove">
			</canvas>
		</view>
		<button @click="reset">重置</button>
	</view>
	
</template>

<script>
	export default {
		data() {
			return {
				ctx: null,
				width: 0,
				height: 0,
				
				disabled: false, // 是否禁止刮卡
				readyState: false, // 是否开始绘制
				endState: false, // 结束刮卡状态

				watermark: '刮一刮', // 水印文字
				watermarkColor: '#c5c5c5', // 水印文字颜色
				watermarkSize: 14, // 水印文字大小

				title: '刮一刮开奖', // 提示文字
				titleColor: '#888', // 提示文字颜色
				titleSize: 24, // 提示文字大小

				startX: 0, // 触摸x轴位置
				startY: 0, // 触摸y轴位置
				touchSize: 20, // 触摸画笔大小
				percentage: 50, // 刮开百分之多少的时候开奖

			}
		},
		onShow() {
			this.$nextTick(() => {
				let content = uni.createSelectorQuery().select(".content");
				content.boundingClientRect((data) => {
					this.width = data.width;
					this.height = data.height;
					this.ctx = uni.createCanvasContext('myCanvas', this);
					setTimeout(e => {
						this.init();
					}, 20);
				}).exec()
			})

		},
		methods: {
			init() {
				this.endState = false;
				this.readyState = false;
				this.ctx.clearRect(0, 0, this.width, this.height); // 清除画布上在该矩形区域内的内容(x,y,宽,高)。
				this.ctx.setFillStyle('#ddd'); // 填充颜色
				this.ctx.fillRect(0, 0, this.width, this.height); // 填充区域(x,y,宽,高)


				/**
				 * 绘制文字水印
				 */
				var width = this.watermark.length * this.watermarkSize;
				this.ctx.save(); // 保存当前的绘图上下文。
				this.ctx.rotate(-10 * Math.PI / 180); // 以原点为中心,原点可以用 translate方法修改。顺时针旋转当前坐标轴。多次调用rotate,旋转的角度会叠加。
				let x = 0;
				let y = 0;
				let i = 0;
				while ((x <= this.width * 5 || y <= this.height * 5) && i < 300) {
					this.ctx.setFillStyle(this.watermarkColor); // 填充颜色
					this.ctx.setFontSize(this.watermarkSize); // 设置字体的字号
					this.ctx.fillText(this.watermark, x, y); // 填充的文本(文字,x,y)
					x += width + width * 1.6;
					if (x > this.width && y <= this.height) {
						x = -Math.random() * 100;
						y += this.watermarkSize * 3;
					}
					i++;
				}
				this.ctx.restore(); // 恢复之前保存的绘图上下文。

				/**
				 * 绘制标题
				 */
				this.ctx.setTextAlign("center"); // 用于设置文字的对齐
				this.ctx.setTextBaseline("middle"); // 用于设置文字的水平对齐
				this.ctx.setFillStyle(this.titleColor); // 填充颜色
				this.ctx.setFontSize(this.titleSize); // 设置字体的字号
				this.ctx.fillText(this.title, this.width / 2, this.height / 2); // 填充的文本(文字,x,y)

				this.ctx.draw(); // 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中。
				this.readyState = true; // 完成绘制
			},


			// 手指触摸动作开始
			touchstart(e) {
				if (this.disabled || this.endState) {
					return;
				}
				this.startX = e.touches[0].x;
				this.startY = e.touches[0].y;
			},
			// 手指触摸后移动
			touchmove(e) {
				if (this.disabled || this.endState) {
					return;
				}
				this.ctx.clearRect(this.startX, this.startY, this.touchSize, this.touchSize); // 清除画布上在该矩形区域内的内容(x,y,宽,高)。
				this.ctx.draw(true); // false:本次绘制是否接着上一次绘制,true:保留当前画布上的内容
				//记录移动点位
				this.startX = e.touches[0].x;
				this.startY = e.touches[0].y;
			},
			// 手指触摸动作结束
			touchend(e) {
				if (this.disabled || this.endState) {
					return;
				}
				// 返回一个数组,用来描述 canvas 区域隐含的像素数据,在自定义组件下,第二个参数传入自定义组件实例 this,以操作组件内 <canvas> 组件。
				uni.canvasGetImageData({
					canvasId: 'myCanvas',
					x: 0,
					y: 0,
					width: this.width,
					height: this.height,
					success: (res) => {
						console.log(res);
						let pixels = res.data;
						let transPixels = [];
						for (let i = 0; i < pixels.length; i += 4) {
							if (pixels[i + 3] < 128) {
								transPixels.push(pixels[i + 3]);
							}
						}
						var percent = (transPixels.length / (pixels.length / 4) * 100).toFixed(2);
						if (percent >= this.percentage) {
							this.success();
						}
					},
					fail: (e) => {
						console.log(e);
					},
				}, this);
			},

			// 成功,清除所有图层
			success: function(e) {
				if (this.endState) {
					return;
				}
				this.endState = true;
				this.ctx.moveTo(0, 0); // 把路径移动到画布中的指定点,不创建线条。用 stroke() 方法来画线条。
				this.ctx.clearRect(0, 0, this.width, this.height); // 清除画布上在该矩形区域内的内容(x,y,宽,高)。
				this.ctx.stroke(); // 画出当前路径的边框。默认颜色色为黑色。
				this.ctx.draw(true);
				uni.showToast({
					icon: 'none',
					title: '开奖完成',
				});
			},
			
			// 重置
			reset(){
				this.init();
			},
		}
	}
</script>

<style scoped lang="scss">
	.content {
		width: 300rpx;
		height: 120rpx;
		margin: auto ;
		position: relative;
		display: flex;
		align-items: center;
		justify-content: center;

		.value {
			color: red;
			font-size: 32rpx;
			font-weight: bold;
			position: absolute;
			left: 0;
			top: 0;
			width: 100%;
			height: 100%;
			display: flex;
			align-items: center;
			justify-content: center;
		}
	}
</style>

  • 3
    点赞
  • 8
    收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunly_

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值