序文
各エンドには各エンドの管理ルールがあり、技術レベルでユニアプリによって平滑化することはできません。
- たとえば、H5 側のブラウザにはクロスドメイン制限があります。
- たとえば、WeChat アプレットは https リンクを強制し、インターネットに接続するすべてのサーバー ドメイン名を WeChat のホワイトリストに割り当てる必要があります。
- たとえば、アプリ側では、iOS はプライバシー管理と仮想支払い管理に非常に厳格です。
- たとえば、アプリ側、Android、国内のROMの間にはさまざまな互換性の違いがあり、特にGoogleサービスがブロックされているため、プッシュやポジショニングなどの混沌とした開発ピットが発生しています。
1 デバイスステータスバーの高さ statusBarHeight
statusBarHeight: uni.getSystemInfoSync().statusBarHeight // CSS 変数よりも高い精度
2 ジャンプ ページにはオブジェクト パラメータが含まれているため、encodeURIComponent
コーディングする必要があります -> アプレットと互換性があります。(パラメーターに含まれる ?、& などの特殊記号)
uni.navigateTo({
url: 'chooseShopGood?shopInfo=' + encodeURIComponent(JSON.stringify(this.shopInfo))
})
そうでない場合 encodeURIComponent,微信小程序就报错了!
受信側は decodeURIComponent をデコードします
onLoad(options) {
if (options.shopInfo) {
this.shopInfo = JSON.parse(decodeURIComponent(options.shopInfo))
this.shopId = this.shopInfo.shopId
}
},
? や & などの特殊記号がパラメータに含まれている場合は、エンコードとデコードを忘れずに行う必要があります。
3 キャンバス描画
DrawImage には画像の問題はありません: ローカル画像を使用してクロスドメインを解決します: H5 および WeChat アプレット
ネットワーク イメージの場合は、uni.getImageInfo(OBJECT) が必要です。アプレットでネットワーク イメージ情報を取得するには、まずダウンロード ドメイン名のホワイトリストを構成して有効にする必要があります。返される res.path は、drawImage のイメージ アドレスです (getImageInfo が静的アドレスを使用するのは間違ったパス (サブパッケージ) であるため、ネットワーク アドレスを使用するのが最善です)
画像ビュー効果
<image :src="inviteCodePosterImagePath" :style="{幅:100+'px',高さ:100+'px'}" />
ctx.setFillStyle('transparent'); 透明に設定することはできません。透明に設定しないと、画像が表示されません。
以下のコードは参考用です。プラグインには角丸長方形のフレームがあるため、最終的にはプラグインをダウンロードする必要があります。
handlePoster(type) {
let that = this
if(this.inviteCodePosterImagePath) {
uni.hideLoading()
if (type === 1) {
this.saveImage(this.inviteCodePosterImagePath)
} else if (type === 2) {
// #ifdef H5
uni.showToast({
icon: 'none',
title: '请下载APP使用此功能'
});
// #endif
// #ifdef APP-PLUS
uni.share({
provider: 'weixin',
scene: 'WXSceneSession',
type: 2,
imageUrl: that.inviteCodePosterImagePath,
success: function(res) {
console.log('success:' + JSON.stringify(res));
},
fail: function(err) {
console.log('fail:' + JSON.stringify(err));
}
});
// #endif
// #ifdef MP-WEIXIN
console.log('分享')
wx.showShareImageMenu({
path: that.inviteCodePosterImagePath,
complete: function(res) {
console.log(res);
}
})
// #endif
}
} else {
//#ifdef MP-WEIXIN
uni.showLoading({
title: '图片生成中'
});
uni.getImageInfo({
src: 'https://jhoss.zgtgex.com/static/assets/images/user/22-200.png',
success: function (image) {
if(image.path) {
that.canvasPoster(type,image.path)
} else {
uni.showToast({
title: '失败',
icon: 'none'
});
}
}
});
//#endif
//#ifdef H5 || APP-PLUS
that.canvasPoster(type,'/static/assets/images/user/22-200.png')
//#endif
}
},
canvasPoster(type,posterBgImgPath) {
console.log('canvasPoster')
let that = this
let ctx = uni.createCanvasContext('inviteCode', this);
ctx.setFillStyle("#ffffff");
ctx.fillRect(0, 0, 200, 340); // fillRect(x,y,宽度,高度)
ctx.drawImage(posterBgImgPath, 0, 0, 200, 340);
ctx.restore();
ctx.setFontSize(16); // 字号
ctx.setFillStyle('#fff'); // 颜色
ctx.fillText('面对面扫码邀请', 44, 30); // (文字,x,y)
ctx.setFontSize(14); // 字号
ctx.setFillStyle('#333'); // 颜色
ctx.fillText('扫描二维码进行注册', 36, 280); // (文字,x,y)
ctx.setFontSize(16); // 字号
ctx.setFillStyle('#333'); // 颜色
ctx.fillText('我的邀请码:' + this.userInfo.inviteCode, 30, 310); // (文字,x,y)
ctx.rect(15, 70, 170, 170);
ctx.setFillStyle('#ffffff');
ctx.fill();
ctx.drawImage(this.codeBase64, 25, 80, 150, 150);
ctx.draw(true, ret => {
setTimeout(()=>{
uni.canvasToTempFilePath({
width: 200,
height: 340,
canvasId: 'inviteCode',
quality: 1,
complete: res => {
that.inviteCodePosterImagePath = res.tempFilePath
that.handlePoster(type)
}
},this);
},500)
},500);
},
4 Wechat アプレット画像共有 (キャンバス描画の共有)
// #ifdef MP-WEIXIN
console.log('分享')
wx.showShareImageMenu({
path: that.inviteCodePosterImagePath,
complete: function(res) {
console.log(res);
}
})
// #endif
5 写真をカメラロールに保存する
saveImage(path) {
// #ifdef H5
var oA = document.createElement('a');
oA.download = '邀请码'; // 设置下载的文件名,默认是'下载'
oA.href = path;
document.body.appendChild(oA);
oA.click();
oA.remove(); // 下载之后把创建的元素删除
return;
// #endif
// #ifndef H5
uni.saveImageToPhotosAlbum({
filePath: path,
success: function() {
uni.showToast({
title: '保存成功',
icon: 'success',
duration: 2000
});
}
});
// #endif
},
6 アプレットの右側のカプセルのサイズ情報
let menuButtonInfo = {};
let systemInfo = uni.getSystemInfoSync();
// 如果是小程序,获取右上角胶囊的尺寸信息,避免导航栏右侧内容与胶囊重叠(支付宝小程序非本API,尚未兼容)
// #ifdef MP-WEIXIN || MP-BAIDU || MP-TOUTIAO || MP-QQ
menuButtonInfo = uni.getMenuButtonBoundingClientRect();
this.rightButtonWidth = systemInfo.windowWidth - menuButtonInfo.left;
// #endef
7 ポップアップウィンドウによる共有(ダイレクト共有、ポスター共有)
8 スクロールして先頭に戻る
<scroll-view scroll-y="true" class="sv" :style="{'height': 'calc(100% - ' + scrollHeight+'px)' }"
:scroll-into-view="topItem" @scroll="scroll" scroll-with-animation @scrolltolower="searchListMore">
<view id="all"></view>
<view class="list-box" v-for="(item, index) in dataList" :key="index" @click="Util.goto(`/pages/goods/info?goods_id=${item.goods_id_}`, 'navigateTo')">
</view>
</scroll-view>
data() {
return {
topItem: '', // 初始一定要为空,scroll-into-view才不受影响
}
},
methods: {
scroll(e) {
this.topItem = '' // 滚动以后就置空,这样每一次的topItem = 'all',才会生效!
},
// 列表接口: 主要是第一页的时候,要置顶
searchList() {
if (this.searchForm.page == 1) {
this.dataList = []
this.$nextTick(() => {
this.topItem = 'all'
});
}
},
}
9 請求書を表示するための Douyin アプレット
invoiceShow(){ // 查看发票
var that = this
tt.downloadFile({
url: 'https://xxxxx.pdf',
success: function (res) {
const filePath = res.tempFilePath
tt.openDocument({
filePath: filePath,
success: function (res) {
console.log("打开文档成功")
},
})},
})
},
// 微信也有wx.openDocument