华为手机长按图片无法下载

此篇博客详细阐述了在使用UniApp开发H5推广海报时,如何解决华为手机长按图片无法下载的问题,通过make_canvas函数实现图片压缩并提供下载。关键代码展示了如何创建canvas,调整图片大小,并在适当时机将canvas转换为可供下载的Base64格式。
摘要由CSDN通过智能技术生成

手机浏览器图片长按无法下载之华为手机的限制问题(uniapp实现的H5推广海报图片点击下载问题)
直接上代码
解决问题的核心代码

  make_canvas(img01, img02, scale) {
      img02.tempFilePath = this.qrcode;
      const query = uni.createSelectorQuery().in(this);
      var system_info = this.system_info;
      let ww = system_info.windowWidth; //准确的宽高
      var rpx = system_info.windowWidth / 375;
      var rpx1 = system_info.windowHeight / 667;
      var ctx = uni.createCanvasContext('myCanvas'); //绑定画布
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, ww, this.hh);
      ctx.drawImage(img01.tempFilePath, 10, 10, this.ww, this.hh - 150); //填充进图片
      // ctx.drawImage(img01.tempFilePath, 0, 0,ww,hh); //填充进图片
      ctx.drawImage(this.logo, 0.68 * ww, 0.81 * this.hh, 100 * rpx, 35 * rpx); //填充进图片'../../static/img/矢量智能对象 拷贝@2x.png'
      ctx.drawImage(img02.tempFilePath, 0.05 * ww, this.hh * 0.825, 100 * rpx, 100 * rpx); //填充进图片
      ctx.setFillStyle('#41B1E6'); //设置内容1的文字样式
      ctx.setTextAlign('right'); //设置对于坐标点的对齐方式
      ctx.setFontSize(rpx * 16);
      ctx.fillText(this.title, ww - 14, this.hh * 0.9);
      ctx.setFontSize(rpx * 14);
      ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式
      ctx.fillText(this.info1, ww - 14, this.hh * 0.938);
      ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式
      ctx.fillText(this.info2, ww - 14, this.hh * 0.968);
      ctx.draw(); //输出到画布中
      uni.showLoading({
        //增加loading等待效果
        mask: true,
        title: '海报生成中',
      });
      setTimeout(() => {
        //不加延迟的话,base64有时候会赋予undefined
        uni.canvasToTempFilePath({
          canvasId: 'myCanvas',
          destWidth: devicePixelRatio * (scale || 1) * ww,
          destHeight: devicePixelRatio * (scale || 1) * this.hh,
          success: res => {
            /* 
				解决图片过大时, 部分手机浏览器不识别问题 
			*/
            const size = this.dataURLtoBlob(res.tempFilePath).size / 1024 / 1024;
            if (size > 1.4) {
              this.make_canvas(img01, img02, 1.4 / size);
            } else {
              this.base64 = res.tempFilePath;
              this.canvasShow = false;
            }
          },
        });
        uni.hideLoading();
      }, 500);
    },

生成海报的全部代码 promotionPoster.vue 文件

<template>
  <view>
    <navator :iconStyle="iconStyle" :navStyle="navStyle">
      <text>我的推广海报</text>
    </navator>
    <view class="index" :style="{ height: hh * 0.6 + 'px' }">
      <view style="margin: 0 auto" :style="{ height: 90 + '%', width: 95 + '%' }">
        <canvas canvas-id="qrcode" class="qrcode" style="width: 400rpx; height: 400rpx" />
        <canvas canvas-id="myCanvas" v-show="canvasShow" id="sss" :style="{ height: hh + 'px' }"></canvas>
        <view>
          <img :src="base64" mode="scaleToFill" v-if="!canvasShow" class="immm" />
        </view>
      </view>
    </view>
    <view :style="{ 'margin-top': hh * 0.38 + 'px' }">
      <view style="text-align: center; font-size: 28upx; font-weight: 400; color: #ffffff">
        长按上方图片保存,分享给朋友
      </view>
      <view class="img-box" :style="{ width: phoneWidth * 0.94 + 'px' }">
        <img v-for="(item, index) in imgList" :key="index" class="rec" :src="item" alt="" @click="selectImg(item)" />
      </view>
    </view>
  </view>
</template>

<script>
import uQRCode from '../../common/uqrcode.js';
import gaussBlur from '../../utils/guessBlur.js';
import '../../utils/screen';
const StackBlur = require('stackblur-canvas');
export default {
  data() {
    return {
      iconStyle: 'white',
      navStyle: 'default1',
      phoneHeight: 0,
      phoneWidth: 0,
      w: 700,
      title: '我是智教',
      info1: '重新定义未来智慧教育',
      info2: '课桌先生不止是一张简单的课桌',
      qrcode: '',
      code: '',
      nickName: '',
      sceneStr: '',
      link: '',
      canvasShow: true,
      header: '',
      rpx: 0,
      base64: '',
      baseURL: '',
      imgList: [
        '../../static/img/1-1.png',
        '../../static/img/1-2.png',
        '../../static/img/1-3.png',
        '../../static/img/1-4.png',
        '../../static/img/1-5.png',
      ],
      ewm: '',
      logo: '../../static/img/矢量智能对象 拷贝@2x.png',
      bg_img: '../../static/img/1-1.png', //线上图片
      system_info: [], //系统信息
      hh: '',
      ww: '',
    };
  },
  onLoad(option) {
    if (!uni.getStorageSync('token')) {
      uni.navigateTo({
        url: '/pages/login/index',
      });
    } else {
      this.link = option.link;
      this.code = option.code;
      this.nickName = option.nickName;
      if (this.nickName.length > 6) {
        this.title = this.title + this.nickName.substring(0, 8) + '...';
      } else {
        this.title = this.title + this.nickName;
      }
      // 获取屏幕尺寸
      this.system_info = uni.getSystemInfoSync(); //屏幕宽高
      this.phoneWidth = this.system_info.windowWidth; //:style="{'height': phoneHeight + 'upx'}":style="{'height':phoneHeight*0.8+'px'}"
      this.phoneHeight = this.system_info.windowHeight;
      this.rpx = this.windowWidth / 375;
      // 获取图片的宽高
      var img = new Image();
      img.src = this.imgList[0];
      var h = 942;
      var w = 658;
      this.ww = this.phoneWidth - 20;
      var ration = w / h;
      this.hh = this.ww / ration + 150;
    }
},
   onLoad(option) {
	    if (!uni.getStorageSync("token")) {
		   uni.navigateTo({
			   url: '/pages/login/index'
		   })
	   }else{
	   this.link=option.link +'?upperCode=' + option.code ;
	  this.code = option.code;
	  this.nickName =option.nickName;
	  console.log('link', this.link)
	  if(this.nickName.length>6){
        this.title = this.title+this.nickName.substring(0,8)+'...';
	  }else{
		this.title = this.title+this.nickName
	  }  
	    // 获取屏幕尺寸
        this.system_info = uni.getSystemInfoSync(); //屏幕宽高
                this.phoneWidth =this.system_info.windowWidth;//:style="{'height': phoneHeight + 'upx'}":style="{'height':phoneHeight*0.8+'px'}"
                this.phoneHeight =this.system_info.windowHeight;
				this.rpx  = this.windowWidth /375;
	    // 获取图片的宽高
	   var img = new Image();
	   img.src = this.imgList[0];
		var h=942;
	    var w=658;
		this.ww =this.phoneWidth-20;
	     var ration =w/h;
		this.hh =this.ww/ration+150;	
	   }
			
      },
    onShow(){
		
	},
	
   async mounted(){
	this.getPromoteLink();
	if (uni.getStorageSync("token")) {
	  await this.getQRcode(this.link)
       this.$myRequest.get('/posters/page-list')
        .then(res => {
          if (res.code === '0' || res.code === 0) {
          } else {
            uni.showToast({ title: res.message, icon: 'none', duration: 2000 });
          }
        })
        .catch(err => {
          console.log(err);
        });
    } else {
      uni.navigateTo({
        url: '/pages/login/index',
      });
    }
  },
  methods: {
    // 获取推广链接
    getPromoteLink() {
      this.$myRequest
        .get('/mobile/promotersbindrules/promotersurl')
        .then(res => {
          if (res.code === '0' || res.code === 0) {
          } else {
            uni.showToast({ title: res.message, icon: 'none', duration: 2000 });
          }
        })
        .catch(err => {
          console.log(err);
        });
    },
    // 获取图片的宽高
    getImgProps() {
      var img_url = '../../static/img/kaka_bg.png';
      var img = new Image();
      img.src = img_url;
      //加载完成执行
      img.onload = function () {
        // 打印
        alert('width:' + img.width + ',height:' + img.height);
      };
    },
    async selectImg(value) {
      this.canvasShow = true;
      this.bg_img = value;
      this.ewm = value;
      await this.getQRcode(this.link);
    },
    // 生成验证码
    async getQRcode(v) {
      this.qrcode = await uQRCode.make({
        canvasId: 'qrcode',
        componentInstance: this,
        //二维码内容
        text: v,
        size: 160,
        margin: 5,
        backgroundColor: '#ffffff',
        foregroundColor: '#000000',
        //生成的图片类型
        fileType: 'png',
        errorCorrectLevel: uQRCode.errorCorrectLevel.H,
      });
      this.getImg();
    },
    getImg() {
      var that = this;
      //这里等promise执行,避免拿不到图片临时路径,只能绘制本地图片,所以要先下载,下载本地图片页不影响
      const promise1 = new Promise((resolve, reject) => {
        uni.downloadFile({
          url: that.bg_img,
          // header: {
          // 	  'content-type': 'application/jpg'
          // },
          success: res => {
            resolve(res);
          },
          fail: err => {
            uni.showLoading({
              //增加loading等待效果
              mask: true,
              title: '失败1',
            });
            console.log(err);
          },
        });
      });
      //TODO 二维码图片获取接口使用返回图片类型接口直接获取
      const promise2 = new Promise((resolve, reject) => {
        uni.downloadFile({
          url: that.ewm,
          //根据需要看是否要配置
          // header: {
          // 	 'content-type': 'application/jpg'
          // },
          success: res => {
            resolve(res);
          },
          fail: err => {
            uni.showLoading({
              //增加loading等待效果
              mask: true,
              title: '失败2',
            });
          },
        });
      });
      Promise.all([promise1, promise2]).then(values => {
        this.make_canvas(values[0], values[1]);
      });
    },
    make_canvas(img01, img02, scale) {
      img02.tempFilePath = this.qrcode;
      const query = uni.createSelectorQuery().in(this);
      var system_info = this.system_info;
      let ww = system_info.windowWidth; //准确的宽高
      var rpx = system_info.windowWidth / 375;
      var rpx1 = system_info.windowHeight / 667;
      var ctx = uni.createCanvasContext('myCanvas'); //绑定画布
      ctx.fillStyle = 'white';
      ctx.fillRect(0, 0, ww, this.hh);
      ctx.drawImage(img01.tempFilePath, 10, 10, this.ww, this.hh - 150); //填充进图片
      // ctx.drawImage(img01.tempFilePath, 0, 0,ww,hh); //填充进图片
      ctx.drawImage(this.logo, 0.68 * ww, 0.81 * this.hh, 100 * rpx, 35 * rpx); //填充进图片'../../static/img/矢量智能对象 拷贝@2x.png'
      ctx.drawImage(img02.tempFilePath, 0.05 * ww, this.hh * 0.825, 100 * rpx, 100 * rpx); //填充进图片
      ctx.setFillStyle('#41B1E6'); //设置内容1的文字样式
      ctx.setTextAlign('right'); //设置对于坐标点的对齐方式
      ctx.setFontSize(rpx * 16);
      ctx.fillText(this.title, ww - 14, this.hh * 0.9);
      ctx.setFontSize(rpx * 14);
      ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式
      ctx.fillText(this.info1, ww - 14, this.hh * 0.938);
      ctx.setFillStyle('#7F7F7F'); //设置内容2的文字样式
      ctx.fillText(this.info2, ww - 14, this.hh * 0.968);
      ctx.draw(); //输出到画布中
      uni.showLoading({
        //增加loading等待效果
        mask: true,
        title: '海报生成中',
      });
      setTimeout(() => {
        //不加延迟的话,base64有时候会赋予undefined
        uni.canvasToTempFilePath({
          canvasId: 'myCanvas',
          destWidth: devicePixelRatio * (scale || 1) * ww,
          destHeight: devicePixelRatio * (scale || 1) * this.hh,
          success: res => {
            /* 
				解决图片过大时, 部分手机浏览器不识别问题 
			*/
            const size = this.dataURLtoBlob(res.tempFilePath).size / 1024 / 1024;
            if (size > 1.4) {
              this.make_canvas(img01, img02, 1.4 / size);
            } else {
              this.base64 = res.tempFilePath;
              this.canvasShow = false;
            }
          },
        });
        uni.hideLoading();
      }, 500);
    },
    dataURLtoBlob(dataurl) {
      var arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    },
    bcFn() {
      //uniapp不支持哦
      uni.saveImageToPhotosAlbum({
        //保存图片
        filePath: this.base64,
        success: res => {
          uni.showToast({
            title: '保存成功',
          });
        },
        fail(r) {
          uni.showToast({
            title: '保存失败',
          });
        },
      });
    },
  },
};
</script>

<style lang="scss" scoped>
.img-box {
  padding-top: 5%;
  padding-bottom: 5%;
  height: 230upx;
  overflow-x: scroll;
  margin: 0 auto;
  white-space: nowrap;
}
page {
  background-image: url(../../static/img/bg23.png);
  background-size: 100% 100%;
  background-color: #ffab43;
  background-repeat: no-repeat;
}
.rec {
  width: 20%;
  height: 220upx;
  margin-right: 20upx;
  border-radius: 4px;
}
.index {
  text-align: center;
  padding-top: 30upx;
}
#sss {
  position: absolute;
  width: 100%;
  top: -99999999rpx;
  left: -99999999rpx;
  z-index: 1;
  /* background-color: #18B566; */
}
.immm {
  position: relative;
  width: 100%;
  height: 100%;
  z-index: 9999;
  border-radius: 10upx;
  -webkit-touch-callout: default;
}

.qrcode {
  position: absolute;
  top: -999rpx;
  left: -999rpx;
  z-index: 1;
}
</style>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值