ミニ プログラムに画像コンポーネントを保存する機能を実装する手順を説明します。
この記事では、WeChat アプレット 保存画像コンポーネントの開発について説明します。皆さんのお役に立てれば幸いです。
多くの WeChat ミニ プログラムでは、ユーザーがポスターを保存することでアクティビティを共有し、より多くの人にミニ プログラムについて知らせることができます。私はミニ プログラムを開発しているときにこれに遭遇したはずです。バー。 [関連する学習の推奨事項: 小さなプログラム開発チュートリアル ]
今日は、会社で作成した小さなプログラムでポスターを保存する機能を共有します。まず、以前の社内のニーズがどのようなものだったのかをまず説明させていただきます。同社のオンライン ミニ プログラムは、新規ユーザーのプロモーションを長期的な目的としており、各ユーザーは独自のポスターを作成する必要があり、個人ポスターによるプロモーションは簡単な方法です。
私も課題を受けて、まずは調べ物をしようとユニバーサルインターネットに行ったのですが、先輩が「これと似たようなことをやったことがある」と教えてくれたんですが、その時は課題をこなすだけだったので、コードがとても汚かったので、彼は他のプロジェクトから始めました。私はコードを探して探して、ついに見つけました~~~しかし、私に与えられた時間は限られており、タスクは重いので、私が作らなければなりませんでしたいくつかの調整を行って最初に送信してください。その後、オンライン記事に従い、落とし穴を段階的に追跡し、ポスターを保存するためのコンポーネントを段階的に実装しました。
感想
まず、コンポーネントが uniapp を使用することを宣言しましょう。これは、具体的には、絵を描く、テキストを描く、ポスターをアルバムに保存するという基本的な機能を実装します。開発中に十分に使用されます。
キャンバスにポスターを描きます。 uni.canvasToTempFilePath
を使用して、描画されたキャンバスを画像に変換します。 uni.saveImageToPhotosAlbum
を使用して、携帯電話のアルバムへのローカル一時パスに写真を保存します。 私のアイデアは、使用されるすべてのメソッドをコンポーネントにカプセル化し、使用する必要があるメソッドを呼び出し、関連するパラメーターを調整するために親コンポーネントのみを使用することです。 具体的な使用方法については、サンプル コードをご覧ください。
キャンバスを介してポスター コンテンツを描画する順序
Promise を使用してポスター コンテンツを描画する順序を決定する物体。 promise.all()
メソッドはキャンバス ペイント操作の最後のステップを実行します context.draw()
注 uni.getImageInfo()
画像とアバターを描画するとき、コンポーネントは
uni.getImageInfo()
を通じて画像の関連情報を取得します。このメソッドの呼び出しが成功するための前提条件は、ダウンロード ドメイン名とリクエスト ドメインであることです。名前は WeChat アプレットのバックグラウンドで設定する必要がありますが、エラーを防ぐために、uploadFile ドメイン名も一緒に設定することが最善です。ただし、公式のヒントではダウンロードドメイン名のホワイトリストを設定することになっていますが、画像情報が取得できないという大きな落とし穴があります。関連する構成がない場合、デバッグ中または試用版、正式版などで vconsole デバッグ ツールが開きます。 uni.getImageInfo() は画像情報を取得できますが、vconsole を閉じると uni.getImageInfo() が失敗するという落とし穴もあります。
- canvasInfo オブジェクト (必須)
- ##canvasWidth キャンバスの幅
- canvasHeight キャンバスの高さ
- canvasId キャンバスの識別
-
true の場合、キャンバスが携帯電話画面の全画面であることを意味し、canvasInfo で設定された幅と高さは無効になります。
- デフォルトは false
- drawCanvasImage(context, src, _imageWidth, _imageHeight, dx, dy) Canvas に画像を描画します
- drawCircularAvatar(context, url, _circularX) , _circularY, _circularR) キャンバス上に円形の絵を描きます
##drawText(options) キャンバス上に単一行または複数行のテキストを描きます
- ## startDrawToImage(context 、promiseArr、callback) Draw() on Canvas
- posterToPhotosAlbum(filePath) 携帯電話のアルバムに保存
- サンプルコード コンポーネント ソース コード
<template> <view> <view class="savePosterItem"> <image v-show="tempFilePath" :src="tempFilePath"></image> <save-poster-com v-show="!tempFilePath" ref="savePoster" :canvasInfo="canvasInfo"></save-poster-com> </view> <button class="savePosterBtn" type="primary" @click="saveBtnFun">保存海报</button> </view> </template> <script> import SavePosterCom from '@/components/SavePosterCom/SavePosterCom.vue' export default { components: { SavePosterCom }, data() { return { canvasInfo: { canvasWidth: 620, canvasHeight: 950, canvasId: 'save-poster' }, tempFilePath: '', canvasBgUrl: 'https://images.pexels.com/photos/4065617/pexels-photo-4065617.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500', avatarUrl: 'https://p9-passport.byteacctimg.com/img/user-avatar/4dbf31fa6dec9c65b78a70d28d843c04~300x300.image' } }, onLoad() { let { drawCanvasImage, drawCircularAvatar, drawText } = this.$refs.savePoster.$options.methods this.$refs.savePoster.canvasInit(({ context, comThis }) => { // 获取画布宽高 let canvasWH = comThis.canvasWH // 绘制海报背景图 let promise_1 = drawCanvasImage(context, this.canvasBgUrl, canvasWH.canvasWidth, canvasWH.canvasHeight) // 必须先绘制玩海报背景图 再去操作其他绘制内容 promise_1.then(res => { let promise_2 = drawCircularAvatar(context, this.avatarUrl, canvasWH.canvasWidth / 2, canvasWH.canvasHeight / 7, 70) let promise_3 = drawText({ context: context, text: '皮皮虾仁', dx: (canvasWH.canvasWidth / 2) + 60, dy: canvasWH.canvasHeight / 4, fontSize: 30, fontColor: '#5D4037' }) let promise_4 = drawCanvasImage(context, this.avatarUrl, 150, 150, (canvasWH.canvasWidth / 2) + 85, (canvasWH.canvasHeight - 165)) this.$refs.savePoster.startDrawToImage(context, [promise_1,promise_2,promise_4], (tempFilePath) => { this.tempFilePath = tempFilePath }) }) }) }, methods: { saveBtnFun() { uni.showModal({ title: '保存海报', content: '海报将被保存至相册中', confirmText: '保存', success: (res) => { if(res.confirm) { this.$refs.savePoster.posterToPhotosAlbum(this.tempFilePath) } } }) } } } </script> <style> .savePosterItem { text-align: center; } .savePosterItem > image { width: 620rpx; height: 950rpx; } .savePosterBtn { margin-top: 40rpx; width: 80%; } </style>
ログイン後にコピー
<template> <view> <canvas :canvas-id="canvasInfo.canvasId" :style="{width: canvasWH.canvasWidth + 'px', height: canvasWH.canvasHeight + 'px'}"></canvas> </view> </template> <script> export default { name: 'savePosterCom', data() { return { userPhoneWHInfo: {}, canvasWH: { canvasWidth: 0, canvasHeight: 0 } } }, props: { // 决定保存下来的图片的宽高 canvasInfo: { type: Object, default: () => { return { canvasWidth: 0, canvasHeight: 0, canvasId: 'canvasId' } } }, // canvas画布是不是全屏,默认是false。 false时使用必须传 canvasInfo isFullScreen: Boolean }, created() { this.userPhoneWHInfo = this.getPhoneSystemInfo() if (this.isFullScreen) { // 画布全屏 this.canvasWH.canvasWidth = this.userPhoneWHInfo.windowWidth this.canvasWH.canvasHeight = this.userPhoneWHInfo.windowHeight } else { // 指定宽高 this.canvasWH.canvasWidth = this.canvasInfo.canvasWidth this.canvasWH.canvasHeight = this.canvasInfo.canvasHeight } }, mounted() {}, methods: { /** * 获取用户手机屏幕信息 */ getPhoneSystemInfo() { const res = uni.getSystemInfoSync(); return { windowWidth: res.windowWidth, windowHeight: res.windowHeight } }, /** 获取 CanvasContext实例 * @param {String} canvasId */ getCanvasContextInit(canvasId) { return uni.createCanvasContext(canvasId, this) }, /** 保存海报组件初始化 * @param {Function} callback(context) 回调函数 */ canvasInit(callback) { let context = this.getCanvasContextInit(this.canvasInfo.canvasId) if (context) { callback({ context: context, comThis: this }) } }, /** 将上诉的绘制画到画布中 并且 将画布导出为图片 * @param context 画布 * @param {Promise[]} 存放Promise的数组 * @param {Function} callback 保存图片后执行的回调函数(本地图片临时路径) */ startDrawToImage(context, promiseArr, callback) { // 将之前在绘图上下文中的描述(路径、变形、样式)画到 canvas 中 let canvasId = this.canvasInfo.canvasId let tempFilePath = '' Promise.all(promiseArr).then(res => { context.draw(false, async () => { callback(await this.canvasToImage(canvasId)) }) }) }, /** * 在canvas绘制一张图片 * @param context 画布 * @param src 图片资源 * @param _imageWidth 图片宽度 * @param _imageHeight 图片高度 */ drawCanvasImage(context, src, _imageWidth, _imageHeight, dx, dy) { return new Promise((resolve, reject) => { uni.getImageInfo({ src: src, success: res => { context.drawImage(res.path, (dx - _imageWidth), (dy - _imageHeight), _imageWidth, _imageHeight) resolve(context) }, }) }) }, /** 绘制一个圆形头像 * @param context 画布 * @param url 图片地址 * @param _circularX 圆心X坐标 * @param _circularY 圆心Y坐标 * @param _circularR 圆半径 */ drawCircularAvatar(context, url, _circularX, _circularY, _circularR) { let dx = _circularX - _circularR; let dy = _circularY - _circularR; let dwidth = _circularR * 2; let dheight = _circularR * 2 return new Promise((resolve, reject) => { uni.downloadFile({ url: url, success: res => { context.save() context.beginPath() // _circularX圆的x坐标 _circularY圆的y坐标 _circularR圆的半径 context.arc(_circularX, _circularY, _circularR, 0, 2 * Math.PI) context.clip() // dx: 图像的左上角在目标canvas上 X 轴的位置 // dy: 图像的左上角在目标canvas上 Y 轴的位置 // dwidth: 在目标画布上绘制图像的宽度,允许对绘制的图像进行缩放 // dheight: 在目标画布上绘制图像的高度,允许对绘制的图像进行缩放 context.drawImage(res.tempFilePath, dx, dy, dwidth, dheight) context.restore() // context.draw() resolve(context) } }) }) }, /** 绘制多行文本 注:, 和 空格都算一个字 * @param context 画布 * @param text 需要被绘制的文本 * @param dx 左上角x坐标 * @param dy 右上角y坐标 * @param rowStrnum 每行多少个字 (默认为text字体个数->单行) * @param fontSize 文字大小 (默认16) * @param fontColor 文字颜色 (默认black) * @param lineHeight 单行文本行高 (默认0) */ drawText(options) { let { context, text, dx, dy, rowStrnum = text.length, lineHeight = 0, fontSize = 16, fontColor = 'black' } = options return new Promise((resolve, reject) => { context.setFontSize(fontSize) context.setFillStyle(fontColor) context.setTextBaseline('middle') // 获取需要绘制的文本宽度 let textWidth = Number(context.measureText(text).width) // console.log('textWidth',textWidth) // 获取文本的字数 let textNum = text.length // 获取行数 向上取整 let lineNum = Math.ceil(textNum / rowStrnum) // console.log('textNum',textNum) // console.log('lineNum',lineNum) for (let i = 0; i < lineNum; i++) { let sliceText = text.slice(i * rowStrnum, (i + 1) * rowStrnum) // fillText 的 dx = 文字最左边的距离到屏幕政策的距离 context.fillText(sliceText, dx - textWidth, dy + i * lineHeight); } resolve(context) }) }, /** 将画布导出为图片 * @param canvasId 画布标识 */ canvasToImage(canvasId) { return new Promise((resolve, reject) => { uni.canvasToTempFilePath({ canvasId: canvasId, // 画布标识 success: res => { // 在H5平台下,tempFilePath 为 base64 resolve(res.tempFilePath) }, fail: err => { console.log('err', err) reject(err) } }, this) }) }, /** 保存生成的图片到本地相册中 * @param {String} filePath 图片临时路劲 */ posterToPhotosAlbum(filePath) { console.log('filePath',filePath) uni.showLoading({ title: '保存中...' }) uni.saveImageToPhotosAlbum({ filePath: filePath, success: (res) => { uni.showToast({ title: '保存成功,请前往手机相册中查看', mask: true, icon: 'none', duration: 2000 }) }, fail: (err) => { console.log('err',err) if (err.errMsg.includes('deny')||err.errMsg.includes('denied')) { // 用户选择拒绝 this.openSetting() } else if (err.errMsg.includes('fail cancel')) { // 用户在保存图片时 取消了 uni.showToast({ title: '已取消保存,无法保存至相册', mask: true, icon: 'none', duration: 2000 }) return } }, complete: () => { uni.hideLoading() } }) }, /** * 打开摄像头设置权限页面 */ openSetting() { uni.showModal({ title: '温馨提示', content: '保存图片至相册中,需要您同意添加访问相册权限', cancelText: '拒绝', confirmText: '同意', success: res => { if (res.confirm) { uni.openSetting({ success: settingdata => { if (settingdata.authSetting['scope.writePhotosAlbum']) { console.log('获取权限成功,给出再次点击图片保存到相册的提示。') uni.showToast({ title: '授权成功,请再次点击保存', icon: 'none', duration: 2000, }) } else { console.log('获取权限失败,给出不给权限就无法正常使用的提示') uni.showToast({ title: '需要访问相册权限', icon: 'none', duration: 2000, }) } }, fail: (res) => { console.log('err', err) } }) } else { uni.showToast({ title: '已拒绝授权,无法保存至相册', mask: true, icon: 'none', duration: 2000 }) return } } }) } } } </script> <style> </style>
プログラミング入門
をご覧ください。 !以上がミニ プログラムに画像コンポーネントを保存する機能を実装する手順を説明します。の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

Undresser.AI Undress
リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover
写真から衣服を削除するオンライン AI ツール。

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

AI Hentai Generator
AIヘンタイを無料で生成します。

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

SublimeText3 中国語版
中国語版、とても使いやすい

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

SublimeText3 Mac版
神レベルのコード編集ソフト(SublimeText3)

ホットトピック









Xianyu の公式 WeChat ミニ プログラムが静かに開始されました。ミニ プログラムでは、プライベート メッセージを投稿して購入者/販売者とコミュニケーションしたり、個人情報や注文を表示したり、商品を検索したりすることができます。プログラム、見てみましょう。 Xianyu WeChat アプレットの名前は何ですか? 回答: Xianyu、アイドル取引、中古品販売、評価、リサイクル。 1. ミニ プログラムでは、アイドル メッセージの投稿、プライベート メッセージを介した購入者/販売者とのコミュニケーション、個人情報と注文の表示、指定された商品の検索などができます。 2. ミニ プログラム ページには、ホームページ、近くに、アイドル投稿、メッセージ投稿、私の投稿 5つの機能; 3. 使用したい場合は、購入する前に WeChat 支払いを有効にする必要があります。

WeChat アプレットが画像アップロード機能を実装 モバイル インターネットの発展に伴い、WeChat アプレットは人々の生活に欠かせないものになりました。 WeChat ミニ プログラムは、豊富なアプリケーション シナリオを提供するだけでなく、画像アップロード機能などの開発者定義の機能もサポートします。この記事では、WeChat アプレットに画像アップロード機能を実装する方法と具体的なコード例を紹介します。 1. 準備作業 コードを書き始める前に、WeChat 開発者ツールをダウンロードしてインストールし、WeChat 開発者として登録する必要があります。同時に、WeChat についても理解する必要があります。

WeChat ミニ プログラムでドロップダウン メニュー効果を実装するには、特定のコード サンプルが必要です。モバイル インターネットの普及に伴い、WeChat ミニ プログラムはインターネット開発の重要な部分となり、ますます多くの人が注目し始めています。 WeChat ミニ プログラムを使用します。 WeChat ミニ プログラムの開発は、従来の APP 開発よりも簡単かつ迅速ですが、特定の開発スキルを習得する必要もあります。 WeChat ミニ プログラムの開発では、ドロップダウン メニューが一般的な UI コンポーネントであり、より良いユーザー エクスペリエンスを実現します。この記事では、WeChat アプレットにドロップダウン メニュー効果を実装し、実用的な機能を提供する方法を詳しく紹介します。

WeChat ミニ プログラムでの画像フィルター効果の実装 ソーシャル メディア アプリケーションの人気に伴い、人々は写真にフィルター効果を適用して、写真の芸術的効果や魅力を高めることがますます好まれています。画像フィルター効果は WeChat ミニ プログラムにも実装でき、より興味深く創造的な写真編集機能をユーザーに提供します。この記事では、WeChat ミニ プログラムに画像フィルター効果を実装する方法を紹介し、具体的なコード例を示します。まず、WeChat アプレットのキャンバス コンポーネントを使用して画像を読み込み、編集する必要があります。 Canvasコンポーネントはページ上で使用できます

WeChat アプレットを使用してカルーセル スイッチング効果を実現する WeChat アプレットは、シンプルで効率的な開発と使用特性を備えた軽量のアプリケーションです。 WeChat ミニ プログラムでは、カルーセル スイッチング効果を実現することが一般的な要件です。この記事では、WeChat アプレットを使用してカルーセル切り替え効果を実現する方法と、具体的なコード例を紹介します。まず、カルーセル コンポーネントを WeChat アプレットのページ ファイルに追加します。たとえば、<swiper> タグを使用すると、カルーセルの切り替え効果を実現できます。このコンポーネントでは、 b を渡すことができます。

Xianyu の公式 WeChat ミニ プログラムが静かに開始され、アイドルアイテムを簡単に公開および交換できる便利なプラットフォームをユーザーに提供します。ミニ プログラムでは、プライベート メッセージを介して購入者または販売者とコミュニケーションしたり、個人情報や注文を表示したり、欲しい商品を検索したりできます。では、WeChat ミニ プログラムでは Xianyu とはいったい何と呼ばれているのでしょうか? このチュートリアル ガイドで詳しくご紹介しますので、知りたいユーザーは、この記事に従って読み続けてください。 Xianyu WeChat アプレットの名前は何ですか? 回答: Xianyu、アイドル取引、中古品販売、評価、リサイクル。 1. ミニ プログラムでは、アイドル メッセージの投稿、プライベート メッセージを介した購入者/販売者とのコミュニケーション、個人情報と注文の表示、指定された商品の検索などができます。 2. ミニ プログラム ページには、ホームページ、近くに、アイドル投稿、メッセージ投稿、マイ投稿の5つの機能、3.

WeChat ミニ プログラムで画像回転効果を実装するには、特定のコード サンプルが必要です。WeChat ミニ プログラムは、ユーザーに豊富な機能と優れたユーザー エクスペリエンスを提供する軽量のアプリケーションです。ミニ プログラムでは、開発者はさまざまなコンポーネントと API を使用して、さまざまな効果を実現できます。その中で、画像回転効果は、ミニプログラムに興味と視覚効果を加えることができる一般的なアニメーション効果です。 WeChat ミニ プログラムで画像の回転効果を実現するには、ミニ プログラムが提供するアニメーション API を使用する必要があります。以下は、その方法を示す具体的なコード例です。

WeChat ミニ プログラムにスライディング削除機能を実装するには、特定のコード サンプルが必要です。WeChat ミニ プログラムの人気に伴い、開発者は開発プロセス中にいくつかの一般的な機能を実装する際に問題に遭遇することがよくあります。中でも、スライド削除機能は、よく使われる一般的な機能要件です。この記事では、WeChat アプレットにスライディング削除機能を実装する方法と具体的なコード例を詳しく紹介します。 1. 要件分析 WeChat ミニ プログラムでは、スライド削除機能の実装には次の点が含まれます。 リスト表示: スライドして削除できるリストを表示するには、各リスト項目に次の要素が含まれている必要があります。
