Canvas 制作海報


  • HTML

<template>
	<view class="content">
		<view class="flex_row_c_c modalView" :class="qrShow?'show':''" @tap="hideQr()">
			<view class="flex_column">
				<view class="backgroundColor-white border_radius_10px padding1vh">
					<image :src="poster.finalPath" mode="widthFix" class="posterImage"></image>
				</view>
				<view class="flex_row marginTop2vh">
					<button type="primary" size="mini" @tap.prevent.stop="saveImage()">保存圖片</button>
					<button type="primary" size="mini" @tap.prevent.stop="share()">分享圖片</button>
				</view>
			</view>
		</view>
		
		<button type="primary" @tap="shareFc()">生成海報</button>
		<view class="hideCanvasView">
			<canvas class="hideCanvas" canvas-id="default_PosterCanvasId" :style="{width: (poster.width||0) + 'px', height: (poster.height||0) + 'px'}"></canvas>
		</view>
	</view>
</template>


  • JS

<script>
	import _app from '@/util/QS-SharePoster/app.js';
	import getSharePoster from '@/util/QS-SharePoster/QS-SharePoster.js';
	export default {
		data() {
			return {
				poster: {},
				qrShow: false,
				canvasId: 'default_PosterCanvasId'
			}
		},
		methods: {
			
			async shareFc() {
				try {
					if (!this.poster.finalPath) {
						const d = await getSharePoster({
							type: 'testShareType',
							posterCanvasId: this.canvasId,
							qrCodeArray: ({bgObj, type, bgScale}) => {
								return [{
									text: 'xiazhenjie',
									size: bgObj.width*0.25,
									dx: bgObj.width*0.05,
									dy: bgObj.height - bgObj.width*0.25 - 50
								}]
							},
							imagesArray: ({bgObj, type, bgScale}) => { //接收的第一個參數為背景圖片的信息, 第二個參數是自定義標識(感覺這里用不到), 圖片為示例圖片
								const dx = bgObj.width*0.3; 
								return [
									{
										url: '/static/good_image.jpg',
										dx:0,
										dy: 80,
										infoCallBack(imageInfo) {
											let scale = bgObj.width*0.2 / imageInfo.height;
											return {
												dWidth: bgObj.width,
												dHeight: bgObj.height*0.4,
											}
										}
									},
									{
										url: '/static/2.jpg',
										dx,
										dy: bgObj.height - bgObj.width*0.25 - 50,
										infoCallBack(imageInfo) {
											let scale = bgObj.width*0.2 / imageInfo.height;
											return {
												circleSet: {
													x: imageInfo.width * scale/2,
													y: bgObj.width*0.2/2,
													r: bgObj.width*0.2/2
												},	// 圓形圖片 , 若circleSet與roundRectSet一同設置 優先circleSet設置
												dWidth: imageInfo.width * scale,	// 因為設置了圓形圖片 所以要乘以2
												dHeight: bgObj.width*0.2,
												roundRectSet: {	// 圓角矩形
													r: imageInfo.width*0.1
												}
											}
										}
									},
								]
							},
							textArray: ({bgObj, type, bgScale}) => {
								const fontSize = bgObj.width*0.045;
								const lineHeight = bgObj.height*0.04;
								return [
									{
										// fontStyle: 'bold',
										text: '【新品】大牌來襲,香港直郵教育是護膚品2件套金和爽膚露',
										size: 15,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											_app.log('index頁面的text的infocallback ,textlength:' + textLength);
											return {
												dx: 2,
												dy: 10
											}
										}
									},
									{
										text: '200ml溫和清潔乳200ml撒嬌好多話莪個月 惡客額度金額的',
										size: 15,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: 2,
												dy: 32
											}
										}
									},
									{
										text: '話后過來的.',
										size: 15,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: 2,
												dy: 54
											}
										}
									},
									{
										text: '限時特賣 19日21:00開搶',
										size: 15,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: 120,
												dy: 345
											}
										}
									},
									{
										text: '美美的夏末的店鋪',
										size: 15,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: bgObj.width - 160,
												dy: bgObj.height - 130
											}
										}
									},
									{
										text: '美利',
										size: 12,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: bgObj.width - 160,
												dy: bgObj.height - 110
											}
										}
									},
									{
										text: '¥219.00',
										size: 15,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: bgObj.width - 260,
												dy: bgObj.height - 50
											}
										}
									},
									{
										text: '長按圖片識別 二維碼查看商品詳情',
										size: 12,
										color: '#333333',
										alpha: .5,
										textAlign: 'left',
										textBaseline: 'middle',
										infoCallBack(textLength) {
											return {
												dx: bgObj.width - 260,
												dy: bgObj.height - 30
											}
										}
									},
								]
							},
							setCanvasWH: ({bgObj, type, bgScale}) => { // 為動態設置畫布寬高的方法,
								this.poster = bgObj;
								this.poster.height = 600;
							},
							setDraw: ({Context, bgObj, type, bgScale}) => {
								Context.setFillStyle('#F5F4F9');
								Context.setGlobalAlpha(0.6);
								Context.fillRect(0, bgObj.height - bgObj.height*0.2 - 40, bgObj.width, bgObj.height*0.2 + 30);
							}
						});
						console.log('海報生成成功, 臨時路徑: ' + d.poster.tempFilePath)
						this.poster.finalPath = d.poster.tempFilePath;
					}
					this.qrShow = true;
				} catch (e) {
					_app.hideLoading();
					_app.showToast(JSON.stringify(e));
					console.log(JSON.stringify(e));
				}
			},
			
			saveImage() {
				// #ifndef H5
				uni.saveImageToPhotosAlbum({
					filePath: this.poster.finalPath,
					success(res) {
						_app.showToast('保存成功');
					}
				})
				// #endif
				// #ifdef H5
				_app.showToast('保存了');
				// #endif
			},
			
			share() {
				// #ifdef APP-PLUS
				_app.getShare(false, false, 2, '', '', '', this.poster.finalPath, false, false);
				// #endif

				// #ifndef APP-PLUS
				_app.showToast('分享了');
				// #endif
			},
			
			hideQr() {
				this.qrShow = false;
			}
			
		}
	}
</script>


  • CSS

.hideCanvasView {
		position: relative;
	}

	.hideCanvas {
		position: fixed;
		top: -99999upx;
		left: -99999upx;
		z-index: -99999;
	}

	.flex_row_c_c {
		display: flex;
		flex-direction: row;
		justify-content: center;
		align-items: center;
	}

	.modalView {
		width: 100%;
		height: 100%;
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		bottom: 0;
		opacity: 0;
		outline: 0;
		transform: scale(3);
		perspective: 2500upx;
		background: rgba(0, 0, 0, 0.6);
		transition: all .3s ease-in-out;
		pointer-events: none;
		backface-visibility: hidden;
		z-index: 999;
	}

	.modalView.show {
		opacity: 1;
		transform: scale(1);
		pointer-events: auto;
	}

	.flex_column {
		display: flex;
		flex-direction: column;
	}

	.backgroundColor-white {
		background-color: white;
	}

	.border_radius_10px {
		border-radius: 10px;
	}

	.padding1vh {
		/* padding: 1vh; */
		padding-top: 20px;
	}
	.padding1vh2{
		padding-top: 20px;
		padding-bottom: 20px;
	}

	.posterImage {
		width: 80vw;
		height: 40vw;
	}

	.flex_row {
		display: flex;
		flex-direction: row;
	}

	.marginTop2vh {
		margin-top: 2vh;
	}

參考:https://ext.dcloud.net.cn/plugin?id=471

項目地址 :https://dev.tencent.com/u/Coding-Neo/p/CanvasPoster/git


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM