1***@qq.com
1***@qq.com
  • 发布:2025-12-23 11:59
  • 更新:2025-12-23 15:15
  • 阅读:45

刮刮卡组件app-nvue不显示涂层

分类:nvue

在项目中nvue页面调用刮刮卡组件wed端没问题,移动端遮盖涂层不显示。vue页面就没任何问题,怎么调整能让他再移动端正常显示。
<template>
<!-- #ifdef APP-PLUS-NVUE -->
<view class="base-cloud">
<view class="father">
<view class="container-wrapper">
<view :class="{op0 : !ready}" class="prize-container">
<slot></slot>
</view>
<canvas :style="{width: width+'px', height: height+'px'}" class="abs" :disable-scroll="true" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove" canvas-id="scratch-card"></canvas>
</view>
</view>
</view>
<!-- #endif -->

<!-- #ifndef APP-PLUS-NVUE -->  
<view class="base-cloud">  
    <view class="father" id="canvas">  
        <view :class="{op0 : !ready}">  
            <slot></slot>  
        </view>  
        <canvas :style="{width: width+'px', height : height+'px'}" class="abs" :disable-scroll="true" @touchstart="touchstart" @touchend="touchend" @touchmove="touchmove" canvas-id="scratch-card"></canvas>  
    </view>  
</view>  
<!-- #endif -->  

</template>

<script>
export default {
name : "scratch-card" ,
props:{
percentage : { //刮开百分之多少的时候开奖
type : Number ,
default : 20
},
touchSize : { //触摸画笔大小
type : Number ,
default : 20
},
fillColor : { //未刮开图层时的填充色
type : String ,
default : '#ddd'
},
watermark : { //水印文字
type : String ,
default : '刮一刮'
},
watermarkColor : { //水印文字颜色
type : String ,
default : '#c5c5c5'
},
watermarkSize : { //水印文字大小
type : Number ,
default : 14
},
title : { //提示文字
type : String ,
default : '刮一刮开奖'
},
titleColor : { //提示文字颜色
type : String ,
default : '#888'
},
titleSize : { //提示文字大小
type : Number ,
default : 24
},
disabled : { //是否禁止刮卡
type : Boolean ,
default : false
}
},
data() {
return {
width : 0 ,
height : 0 ,
startX : null ,
startY : null ,
computing : false ,
complete : false ,
reset : false ,
ready : false ,
storePoints:[],
touchCount: 0, // 触摸次数计数器,用于nvue平台估算刮开百分比
ctx: null // 将ctx移到组件实例内部
};
},
mounted() {
// 根据平台使用不同的canvas上下文创建方式
// #ifdef APP-PLUS-NVUE
// nvue平台使用getContext获取canvas上下文
this.ctx = uni.createCanvasContext("scratch-card" , this) ;
// #endif

        // #ifndef APP-PLUS-NVUE  
        // 其他平台使用原方式  
        this.ctx = uni.createCanvasContext("scratch-card" , this) ;  
        // #endif  

        this.getRect();  
    },  
    methods:{  

getRect:function(e){
// 针对 nvue 平台,使用更兼容的方式获取尺寸
// #ifdef APP-PLUS-NVUE
// nvue平台获取设备像素比,将rpx转换为像素
const sysInfo = uni.getSystemInfoSync();
const pixelRatio = sysInfo.pixelRatio;
const screenWidth = sysInfo.screenWidth;

        // 页面容器尺寸为600rpx x 300rpx  
        // 将rpx转换为像素:1rpx = screenWidth / 750 px  
        this.width = Math.round((600 / 750) * screenWidth);  
        this.height = Math.round((300 / 750) * screenWidth);  
        setTimeout(() => {  
            this.init();  
        }, 20);  
        // #endif  

        // 针对其他平台使用原方法  
        // #ifndef APP-PLUS-NVUE  
        const query = uni.createSelectorQuery().in(this);  
        query.select('#canvas').boundingClientRect(data => {  
            this.width = data.width;  
            this.height = data.height;  
            setTimeout(e => {  
                this.init();  
            },20);  
        }).exec();  
        // #endif  
    },  

        init : function(e){  
        this.computing = false ;  
        this.complete = false ;  
        this.reset = false ;  
        this.ready = false ;  
        this.touchCount = 0; // 重置触摸次数计数器  

        // #ifdef APP-PLUS-NVUE  
        // nvue 平台的绘制方式  
        // 清除画布  
        this.ctx.clearRect(0, 0, this.width, this.height);  
        // 重置绘制状态  
        this.ctx.setFillStyle(this.fillColor);  
        this.ctx.fillRect(0, 0, this.width, this.height);  
        //绘制文字水印  
        this.fillWatermark();  
        //绘制标题  
        this.fillTitle();  
        // nvue平台需要立即绘制  
        this.ctx.draw();  
        // #endif  

        // #ifndef APP-PLUS-NVUE  
        // 其他平台的绘制方式  
        this.ctx.clearRect(0, 0, this.width, this.height);  
        this.ctx.setFillStyle(this.fillColor);  
        this.ctx.fillRect(0, 0, this.width, this.height);  
        //绘制文字水印  
        this.fillWatermark();  
        //绘制标题  
        this.fillTitle();  
        this.ctx.draw();  
        // #endif  

        this.ready = true ;  
    },  

        /**  
         * 绘制文字水印  
         */  
        fillWatermark : function(e){  
            if (!this.watermark) {  
                return ;  
            }  
            var width = this.watermark.length * this.watermarkSize ;  
            this.ctx.save() ;  
            this.ctx.rotate(-10 * Math.PI / 180);  
            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 += width + width * 1.6 ;  
                if (x > this.width && y <= this.height ) {  
                    x = -Math.random()*100 ;  
                    y += this.watermarkSize * 3 ;  
                }  
                i++ ;  
            }  
            this.ctx.restore();  
        },  

        /**  
         * 绘制标题  
         */  
        fillTitle : function(e){  
            if (!this.title) {  
                return ;  
            }  
            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 );  
        },  

        touchstart : function(e){  
            if (this.disabled) {  
                return ;  
            }  
            this.startX = e.touches[0].x;  
            this.startY = e.touches[0].y;  
        },  

        touchend : function(e){  
            this.getFilledPercentage();  
        },  

        touchmove : function(e){  
        if(this.complete || this.disabled ){  
            return ;  
        }  
        // 获取当前触摸点相对于canvas的坐标  
        const currentX = e.touches[0].x;  
        const currentY = e.touches[0].y;  

        // #ifdef APP-PLUS-NVUE  
        // nvue 平台的处理方式  
        this.ctx.save();  
        this.ctx.beginPath();  
        // 使用圆形刮开效果,与其他平台保持一致  
        this.ctx.arc(currentX, currentY, this.touchSize / 2, 0, Math.PI * 2);  
        this.ctx.clip();  
        this.ctx.clearRect(  
            currentX - this.touchSize / 2,  
            currentY - this.touchSize / 2,  
            this.touchSize,  
            this.touchSize  
        );  
        this.ctx.restore();  
        this.ctx.draw(true);  
        // #endif  

        // #ifndef APP-PLUS-NVUE  
        // 其他平台的处理方式  
        this.ctx.beginPath();  
        this.ctx.globalCompositeOperation = 'destination-out';  
        this.ctx.arc(this.startX, this.startY, this.touchSize / 2, 0, Math.PI * 2);  
        this.ctx.fill();  
        this.ctx.globalCompositeOperation = 'source-over';  
        this.ctx.draw(true);  
        // #endif  

        //记录移动点位  
        this.startX = currentX;  
        this.startY = currentY;  
    },  

        getFilledPercentage:function(e){  
        if (this.computing) {  
            return ;  
        }  
        this.computing = true ;  

        // #ifdef APP-PLUS-NVUE  
        // nvue 平台不支持 canvasGetImageData,使用触摸次数来估算刮开百分比  
        // 初始化触摸次数计数器  
        if (!this.touchCount) {  
            this.touchCount = 0;  
        }  

        // 每次触摸增加计数  
        this.touchCount++;  

        // 根据触摸次数和画布大小估算刮开百分比  
        // 假设每次触摸刮开约1%的面积  
        const estimatedPercent = Math.min((this.touchCount / (this.width * this.height / (this.touchSize * this.touchSize))) * 100, 100);  

        if (estimatedPercent >= this.percentage) {  
            this.success();  
        }  
        this.computing = false;  
        // #endif  

        // #ifndef APP-PLUS-NVUE  
        // 其他平台使用原方法  
        uni.canvasGetImageData({  
            canvasId: 'scratch-card' ,  
            x: 0,  
            y: 0,  
            width: this.width ,  
            height: this.height ,  
            success: (res) => {  
                let pixels = res.data;  
                let transPixels = 0;  
                let totalPixels = pixels.length / 4;  
                for (let i = 0; i < pixels.length; i += 4) {  
                    // 检查像素是否透明  
                    if (pixels[i + 3] < 128) {  
                        transPixels++;  
                    }  
                }  
                var percent = (transPixels / totalPixels * 100).toFixed(2);  
                if( percent >= this.percentage ){                         
                    this.success();  
                }  
                this.computing = false ;  
                console.log(percent)  
            },  
            fail : function(e){  
                console.log(e);  
                // 如果 canvasGetImageData 失败(例如在某些平台上),尝试其他方法  
                this.computing = false ;  
            },  
        }, this);  
        // #endif  
    },  

        success : function(e){  
            this.complete = true ;  
            if (this.reset) {  
                return ;  
            }  
            this.reset = true ;  
            this.ctx.moveTo(0, 0);  
            this.ctx.clearRect(0,0, this.width, this.height);  
            this.ctx.stroke() ;  
            this.ctx.draw(true);  
            this.$emit("complete",{});  
        },  
    }  
}  

</script>

<style>
/ 基础样式,适用于所有平台 /
.base-cloud {
position: relative;
display: flex;
width: 100%;
height: 100%;
}

.father {
position: relative;
width: 100%;
height: 100%;
overflow: hidden;
}

.abs {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 10;
}

.op0 {
opacity: 0;
}

.prize-container {
position: relative;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
}

/ #ifdef APP-PLUS-NVUE /
/ nvue平台特定样式 /
.base-cloud {
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
}

.father {
flex-direction: column;
justify-content: center;
align-items: center;
position: relative;
width: 100%;
height: 100%;
}

.container-wrapper {
position: relative;
flex-direction: column;
justify-content: center;
align-items: center;
overflow: hidden;
}

.abs {
position: absolute;
top: 0;
left: 0;
z-index: 10;
}

.prize-container {
position: relative;
display: flex;
justify-content: center;
align-items: center;
z-index: 1;
}

/ #endif /
</style>

2025-12-23 11:59 负责人:无 分享
已邀请:
爱豆豆

爱豆豆 - 办法总比困难多

你好 可以发一个完整可运行的demo吗?

  • 1***@qq.com (作者)

    上传了,麻烦看一下

    2025-12-23 15:16

1***@qq.com

1***@qq.com (作者)

可运行的demo,手机端有问题

要回复问题请先登录注册