|
@@ -1,402 +0,0 @@
|
|
|
-<!--
|
|
|
- * @Description: 生成图片组件
|
|
|
- * @Version: 1.0.0
|
|
|
- * @Autor: hch
|
|
|
- * @Date: 2020-08-07 14:48:41
|
|
|
- * @LastEditors: Please set LastEditors
|
|
|
- * @LastEditTime: 2021-07-31 18:11:35
|
|
|
- * 保存图片按钮和关闭按钮 在html代码中写出来 绑定点击方法然后透明 再用canvas 覆盖
|
|
|
--->
|
|
|
-
|
|
|
-<template>
|
|
|
- <view class="canvas-content" v-show="canvasShow" :style="'width:' + system.w + 'px; height:' + system.h + 'px;'">
|
|
|
- <!-- 遮罩层 -->
|
|
|
- <view class="canvas-mask"></view>
|
|
|
- <!-- 图片 -->
|
|
|
- <!-- :width="system.w" :height="system.h" 支付宝必须要这样设置宽高才有效果 -->
|
|
|
- <canvas class="canvas" canvas-id="myCanvas" id="myCanvas"
|
|
|
- :style="'width:' + system.w + 'px; height:' + system.h + 'px;'" :width="system.w"
|
|
|
- :height="system.h"></canvas>
|
|
|
- <view class="button-wrapper">
|
|
|
- <!-- 保存图片按钮 -->
|
|
|
- <!-- #ifndef MP-QQ -->
|
|
|
- <!-- cover-view 标签qq小程序有问题 -->
|
|
|
- <cover-view class="save-btn" @tap="handleSaveCanvasImage">保存</cover-view>
|
|
|
- <cover-view class="save-btn cancel-btn" @tap="handleCanvasCancel">取消</cover-view>
|
|
|
- <!-- #endif -->
|
|
|
- <!-- #ifdef MP-QQ -->
|
|
|
- <view class="save-btn" @tap="handleSaveCanvasImage">保存</view>
|
|
|
- <view class="save-btn cancel-btn" @tap="handleCanvasCancel">取消</view>
|
|
|
- <!-- #endif -->
|
|
|
- </view>
|
|
|
- </view>
|
|
|
-</template>
|
|
|
-
|
|
|
-<script>
|
|
|
- import {
|
|
|
- drawSquarePic,
|
|
|
- drawTextReturnH,
|
|
|
- getSystem
|
|
|
- } from './utils'
|
|
|
- export default {
|
|
|
- data() {
|
|
|
- return {
|
|
|
- system: {},
|
|
|
- canvasShow: false
|
|
|
- }
|
|
|
- },
|
|
|
- props: {
|
|
|
- posterData: {
|
|
|
- type: Object,
|
|
|
- default: () => {
|
|
|
- return {}
|
|
|
- }
|
|
|
- }
|
|
|
- },
|
|
|
- computed: {
|
|
|
- /**
|
|
|
- * @description: 计算图片背景数据
|
|
|
- * @param {*}
|
|
|
- * @return {*}
|
|
|
- * @author: hch
|
|
|
- */
|
|
|
- poster() {
|
|
|
- let data = this.posterData
|
|
|
- let system = this.system
|
|
|
- let posterBg = {
|
|
|
- url: data.poster.url,
|
|
|
- r: data.poster.r * system.scale,
|
|
|
- w: data.poster.w * system.scale,
|
|
|
- h: data.poster.h * system.scale,
|
|
|
- x: (system.w - data.poster.w * system.scale) / 2,
|
|
|
- y: (system.h - data.poster.h * system.scale) / 2,
|
|
|
- p: data.poster.p * system.scale
|
|
|
- }
|
|
|
- return posterBg
|
|
|
- },
|
|
|
- /**
|
|
|
- * @description: 计算图片头部主图
|
|
|
- * @param {*}
|
|
|
- * @return {*}
|
|
|
- * @author: hch
|
|
|
- */
|
|
|
- square3() {
|
|
|
- let data = this.posterData
|
|
|
- let system = this.system
|
|
|
- let posterMain = {
|
|
|
- r: data.square3.r * system.scale,
|
|
|
- w: data.square3.w * system.scale,
|
|
|
- h: data.square3.h * system.scale,
|
|
|
- x: (system.w - data.square3.w * system.scale) / 2,
|
|
|
- y: this.poster.y + data.poster.p + data.square3.mt * system.scale,
|
|
|
- color: '#E96737'
|
|
|
- }
|
|
|
- return posterMain
|
|
|
- },
|
|
|
-
|
|
|
- title() {
|
|
|
- let data = this.posterData
|
|
|
- let system = this.system
|
|
|
- let posterTitle = data.title
|
|
|
- posterTitle.x = this.square3.x
|
|
|
- posterTitle.y = this.square3.y + 30 * system.scale
|
|
|
- return posterTitle
|
|
|
- },
|
|
|
-
|
|
|
- num() {
|
|
|
- let data = this.posterData
|
|
|
- let system = this.system
|
|
|
- let posterTitle = data.num
|
|
|
- posterTitle.x = this.square3.x
|
|
|
- posterTitle.y = this.square3.y + 100 * system.scale
|
|
|
- return posterTitle
|
|
|
- },
|
|
|
-
|
|
|
- txt() {
|
|
|
- let data = this.posterData
|
|
|
- let system = this.system
|
|
|
- let posterTitle = data.txt
|
|
|
- posterTitle.x = this.square3.x
|
|
|
- posterTitle.y = this.square3.y + 150 * system.scale
|
|
|
- return posterTitle
|
|
|
- },
|
|
|
- },
|
|
|
- created() {
|
|
|
- // 获取设备信息
|
|
|
- this.system = getSystem()
|
|
|
- },
|
|
|
- methods: {
|
|
|
- /**
|
|
|
- * @description: 展示图片
|
|
|
- * @param {type}
|
|
|
- * @return {type}
|
|
|
- * @author: hch
|
|
|
- */
|
|
|
- posterShow() {
|
|
|
- this.canvasShow = true
|
|
|
- this.creatPoster()
|
|
|
- },
|
|
|
- /**
|
|
|
- * @description: 生成图片
|
|
|
- * @author: hch
|
|
|
- */
|
|
|
- async creatPoster() {
|
|
|
- uni.showLoading({
|
|
|
- title: '生成图片中...'
|
|
|
- })
|
|
|
- const ctx = uni.createCanvasContext('myCanvas', this)
|
|
|
- this.ctx = ctx
|
|
|
- ctx.clearRect(0, 0, this.system.w, this.system.h) //清空之前的图片
|
|
|
- ctx.draw() //清空之前的图片
|
|
|
- // 根据设备屏幕大小和距离屏幕上下左右距离,及圆角绘制背景
|
|
|
- let poster = this.poster
|
|
|
- let square3 = this.square3
|
|
|
- let title = this.title
|
|
|
- let num = this.num
|
|
|
- let txt = this.txt
|
|
|
- await drawSquarePic(ctx, poster.x, poster.y, poster.w, poster.h, poster.r, poster.url)
|
|
|
- await drawSquarePic(ctx, square3.x, square3.y, square3.w, square3.h, square3.r, square3.url, square3
|
|
|
- .color)
|
|
|
- // 绘制标题 textY 绘制文本的y位置
|
|
|
- // console.log('creatPoster -> title.x', title.x)
|
|
|
- let textY = drawTextReturnH(
|
|
|
- this.ctx,
|
|
|
- title.text,
|
|
|
- title.x,
|
|
|
- title.y,
|
|
|
- this.system.w,
|
|
|
- title.fontSize,
|
|
|
- title.color,
|
|
|
- title.lineHeight,
|
|
|
- title.align
|
|
|
- )
|
|
|
-
|
|
|
- let numY = drawTextReturnH(
|
|
|
- this.ctx,
|
|
|
- num.text,
|
|
|
- num.x,
|
|
|
- num.y,
|
|
|
- this.system.w,
|
|
|
- num.fontSize,
|
|
|
- num.color,
|
|
|
- num.lineHeight,
|
|
|
- num.align
|
|
|
- )
|
|
|
-
|
|
|
- let txtY = drawTextReturnH(
|
|
|
- this.ctx,
|
|
|
- txt.text,
|
|
|
- txt.x,
|
|
|
- txt.y,
|
|
|
- this.system.w,
|
|
|
- txt.fontSize,
|
|
|
- txt.color,
|
|
|
- txt.lineHeight,
|
|
|
- txt.align
|
|
|
- )
|
|
|
-
|
|
|
- uni.hideLoading()
|
|
|
- },
|
|
|
- /**
|
|
|
- * @description: 保存到系统相册
|
|
|
- * @param {type}
|
|
|
- * @return {type}
|
|
|
- * @author: hch
|
|
|
- */
|
|
|
- handleSaveCanvasImage() {
|
|
|
- uni.showLoading({
|
|
|
- title: '保存中...'
|
|
|
- })
|
|
|
- let _this = this
|
|
|
- // 把画布转化成临时文件
|
|
|
- // #ifndef MP-ALIPAY
|
|
|
- // 支付宝小程序外,其他都是用这个方法 canvasToTempFilePath
|
|
|
- uni.canvasToTempFilePath({
|
|
|
- x: this.poster.x,
|
|
|
- y: this.poster.y,
|
|
|
- width: this.poster.w, // 画布的宽
|
|
|
- height: this.poster.h, // 画布的高
|
|
|
- destWidth: this.poster.w * 5,
|
|
|
- destHeight: this.poster.h * 5,
|
|
|
- canvasId: 'myCanvas',
|
|
|
- success(res) {
|
|
|
- //保存图片至相册
|
|
|
- // #ifndef H5
|
|
|
- // 除了h5以外的其他端
|
|
|
- uni.saveImageToPhotosAlbum({
|
|
|
- filePath: res.tempFilePath,
|
|
|
- success(res) {
|
|
|
- uni.hideLoading()
|
|
|
- uni.showToast({
|
|
|
- title: '图片保存成功',
|
|
|
- duration: 2000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- _this.handleCanvasCancel()
|
|
|
- _this.handleCanvasConfirm()
|
|
|
- },
|
|
|
- fail() {
|
|
|
- uni.showToast({
|
|
|
- title: '保存失败,稍后再试',
|
|
|
- duration: 2000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- uni.hideLoading()
|
|
|
- }
|
|
|
- })
|
|
|
- // #endif
|
|
|
-
|
|
|
- // #ifdef H5
|
|
|
- // h5的时候
|
|
|
- uni.showToast({
|
|
|
- title: '请长按保存',
|
|
|
- duration: 3000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- _this.handleCanvasCancel()
|
|
|
- _this.$emit('previewImage', res.tempFilePath)
|
|
|
- // #endif
|
|
|
- },
|
|
|
- fail(res) {
|
|
|
- // console.log('fail -> res', res)
|
|
|
- uni.showToast({
|
|
|
- title: '保存失败,稍后再试',
|
|
|
- duration: 2000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- uni.hideLoading()
|
|
|
- }
|
|
|
- },
|
|
|
- this
|
|
|
- )
|
|
|
- // #endif
|
|
|
- // #ifdef MP-ALIPAY
|
|
|
- // 支付宝小程序条件下 toTempFilePath
|
|
|
- this.ctx.toTempFilePath({
|
|
|
- x: this.poster.x,
|
|
|
- y: this.poster.y,
|
|
|
- width: this.poster.w, // 画布的宽
|
|
|
- height: this.poster.h, // 画布的高
|
|
|
- destWidth: this.poster.w * 5,
|
|
|
- destHeight: this.poster.h * 5,
|
|
|
- success(res) {
|
|
|
- //保存图片至相册
|
|
|
- my.saveImage({
|
|
|
- url: res.apFilePath,
|
|
|
- showActionSheet: true,
|
|
|
- success(res) {
|
|
|
- uni.hideLoading()
|
|
|
- uni.showToast({
|
|
|
- title: '图片保存成功',
|
|
|
- duration: 2000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- _this.handleCanvasCancel()
|
|
|
- },
|
|
|
- fail() {
|
|
|
- uni.showToast({
|
|
|
- title: '保存失败,稍后再试',
|
|
|
- duration: 2000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- uni.hideLoading()
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- fail(res) {
|
|
|
- // console.log('fail -> res', res)
|
|
|
- uni.showToast({
|
|
|
- title: '保存失败,稍后再试',
|
|
|
- duration: 2000,
|
|
|
- icon: 'none'
|
|
|
- })
|
|
|
- uni.hideLoading()
|
|
|
- }
|
|
|
- },
|
|
|
- this
|
|
|
- )
|
|
|
- // #endif
|
|
|
- },
|
|
|
- /**
|
|
|
- * @description: 取消图片
|
|
|
- * @param {type}
|
|
|
- * @return {type}
|
|
|
- * @author: hch
|
|
|
- */
|
|
|
- handleCanvasCancel() {
|
|
|
- this.canvasShow = false
|
|
|
- this.$emit('cancel', true)
|
|
|
- },
|
|
|
-
|
|
|
- handleCanvasConfirm() {
|
|
|
- this.$emit('canvasConfirm')
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
-</script>
|
|
|
-
|
|
|
-<style lang="scss">
|
|
|
- .content {
|
|
|
- height: 100%;
|
|
|
- text-align: center;
|
|
|
- }
|
|
|
-
|
|
|
- .canvas-content {
|
|
|
- position: absolute;
|
|
|
- top: 0;
|
|
|
-
|
|
|
- .canvas-mask {
|
|
|
- position: fixed;
|
|
|
- top: 0;
|
|
|
- right: 0;
|
|
|
- bottom: 0;
|
|
|
- left: 0;
|
|
|
- z-index: 200;
|
|
|
- width: 100%;
|
|
|
- height: 100%;
|
|
|
- background: rgba(0, 0, 0, 0.5);
|
|
|
- }
|
|
|
-
|
|
|
- .canvas {
|
|
|
- z-index: 200;
|
|
|
- }
|
|
|
-
|
|
|
- .button-wrapper {
|
|
|
- position: fixed;
|
|
|
- bottom: 80rpx;
|
|
|
- z-index: 200;
|
|
|
- display: flex;
|
|
|
- width: 100%;
|
|
|
- height: 72rpx;
|
|
|
- justify-content: space-around;
|
|
|
- }
|
|
|
-
|
|
|
- .save-btn {
|
|
|
- z-index: 16;
|
|
|
- width: 40%;
|
|
|
- height: 100%;
|
|
|
- font-size: 30rpx;
|
|
|
- line-height: 72rpx;
|
|
|
- color: #fff;
|
|
|
- text-align: center;
|
|
|
- background: $uni-btn-color;
|
|
|
- border-radius: 45rpx;
|
|
|
- border-radius: 36rpx;
|
|
|
- }
|
|
|
-
|
|
|
- .cancel-btn {
|
|
|
- color: $uni-btn-color;
|
|
|
- background: #fff;
|
|
|
- }
|
|
|
-
|
|
|
- .canvas-close-btn {
|
|
|
- position: fixed;
|
|
|
- top: 30rpx;
|
|
|
- right: 0;
|
|
|
- z-index: 12;
|
|
|
- width: 60rpx;
|
|
|
- height: 60rpx;
|
|
|
- padding: 20rpx;
|
|
|
- }
|
|
|
- }
|
|
|
-</style>
|