生成海报:1、上传海报样式;2、自定义海报二维码位置、大小;3、实时预览

MakePoster.vue 组件代码

  1 <template>
  2   <div>
  3     <a-row>
  4       <a-col :span="12">
  5         <a-form-model
  6           ref="ruleForm"
  7           :model="form"
  8           :rules="rules"
  9           :label-col="labelCol"
 10           :wrapper-col="wrapperCol"
 11         >
 12           <a-form-model-item
 13             label="分享卡片"
 14             prop="img"
 15             extra="建议宽度:不小于 750px,png/jpg格式,2M以内"
 16           >
 17             <upload-file
 18               @uploadPic="uploadImg"
 19               :img="form.img"
 20               :imgWidth="320 / 2"
 21             ></upload-file>
 22           </a-form-model-item>
 23           <a-form-model-item
 24             label="二维码定位"
 25             prop="posX"
 26             extra="X 代表二维码左顶端的横坐标,正数,单位为像素"
 27           >
 28             <a-input
 29               v-model.number="form.posX"
 30               type="number"
 31               placeholder="X轴偏移量"
 32               addon-after="(X)"
 33             />
 34           </a-form-model-item>
 35           <a-form-model-item
 36             label="二维码定位"
 37             prop="posY"
 38             extra="Y 代表二维码左顶端的纵坐标,正数,单位为像素"
 39           >
 40             <a-input
 41               v-model.number="form.posY"
 42               type="number"
 43               placeholder="Y轴偏移量"
 44               addon-after="(Y)"
 45             />
 46           </a-form-model-item>
 47           <a-form-model-item
 48             label="二维码尺寸"
 49             prop="size"
 50             extra="最小280px,最大 1280px"
 51           >
 52             <a-input
 53               v-model.number="form.size"
 54               placeholder="二维码尺寸"
 55               type="number"
 56             />
 57           </a-form-model-item>
 58           <a-form-model-item :wrapper-col="{ span: 14, offset: 4 }">
 59             <a-button type="default" @click="cancel">
 60               取消
 61             </a-button>
 62             <a-button
 63               type="primary"
 64               @click="onSubmit"
 65               style="margin-left:20px"
 66               :loading="isLoading"
 67             >
 68               提交
 69             </a-button>
 70           </a-form-model-item>
 71         </a-form-model>
 72       </a-col>
 73       <a-col :span="12">
 74         <div>
 75           <div style="margin-bottom:10px">
 76             预览尺寸(px):{{
 77               canvasAttr
 78                 ? canvasAttr.offsetWidth + " x " + canvasAttr.offsetHeight
 79                 : ""
 80             }}(保持纵横比)。 <br />实际尺寸(px):{{
 81               canvasAttr ? canvasAttr.width + " x " + canvasAttr.height : ""
 82             }}(与分享卡片尺寸一致)。
 83             <!-- <br />{{
 84               qrSize ? "二维码实际尺寸约(px):" + qrSize : ""
 85             }}。 -->
 86           </div>
 87           <canvas ref="canvas" width="750" height="1334"></canvas>
 88         </div>
 89       </a-col>
 90     </a-row>
 91   </div>
 92 </template>
 93 
 94 <script>
 95 import uploadFile from "./UploadFile";
 96 import request from "@/utils/request";
 97 export default {
 98   components: {
 99     uploadFile
100   },
101   props: {
102     qrcode: {
103       type: String,
104       default: ""
105     },
106     form: {
107       type: Object,
108       default: () => {
109         return {
110           id: 0, //
111           img: "", // 分享卡片
112           posX: 0, // 二维码定位X
113           posY: 0, // 二维码定位Y
114           size: 280 //二维码尺寸
115         };
116       }
117     }
118   },
119   data() {
120     return {
121       qrSize: null, // 二维码实际尺寸
122       canvasAttr: null, //预览以实际尺寸
123       isLoading: false,
124       id: 0, //
125       canvas: null, // 画布
126       context: null, //context 2d
127       labelCol: { span: 4 },
128       wrapperCol: { span: 12 },
129       rules: {
130         img: [
131           {
132             required: true,
133             message: "请上传分享卡片",
134             trigger: "change"
135           }
136         ],
137         posX: {
138           pattern: /^(0|0\.0*[1-9]+[0-9]*$|[1-9]+[0-9]*\.[0-9]*[0-9]$|[1-9]+[0-9]*$)/,
139           required: true,
140           message: "请输入≥ 0 的坐标",
141           trigger: ["blur", "change"]
142         },
143         posY: {
144           pattern: /^(0|0\.0*[1-9]+[0-9]*$|[1-9]+[0-9]*\.[0-9]*[0-9]$|[1-9]+[0-9]*$)/,
145           required: true,
146           message: "请输入≥ 0 的坐标",
147           trigger: ["blur", "change"]
148         },
149         size: [
150           {
151             type: "number",
152             required: true,
153             message: "最小280px,最大1280px",
154             max: 1280,
155             min: 280,
156             trigger: ["blur", "change"]
157           }
158         ]
159       }
160     };
161   },
162   created() {
163     this.$nextTick(() => {
164       this.init(); //初始化 canvas
165     });
166   },
167   watch: {
168     form: {
169       // eslint-disable-next-line no-unused-vars
170       handler(newValue, oldValue) {
171         this.drawPoster();
172       },
173       deep: true
174     }
175   },
176   methods: {
177     init() {
178       this.$refs.ruleForm.resetFields();
179       this.isLoading = false;
180       this.canvas = this.$refs.canvas;
181       this.context = this.canvas.getContext("2d");
182       this.drawPoster();
183     },
184     // 绘制海报
185     drawPoster() {
186       let _this = this;
187       _this.context.clearRect(0, 0, _this.canvas.width, _this.canvas.height); // 清空画布
188       if (!_this.form.img) {
189         return;
190       }
191       let img = new Image();
192       img.src = this.form.img + "?t=" + new Date().getTime(); // 去掉图片缓存
193       img.setAttribute("crossOrigin", "anonymous");
194       // console.log(_this.canvas)
195       img.onload = e => {
196         const img = e.path[0];
197         const img_w = img.width;
198         const img_h = img.height;
199         _this.canvas.width = img_w;
200         _this.canvas.height = img_h;
201         _this.canvasAttr = {
202           offsetWidth: _this.canvas.offsetWidth,
203           offsetHeight: _this.canvas.offsetHeight,
204           width: _this.canvas.width,
205           height: _this.canvas.height
206         };
207         _this.context.drawImage(img, 0, 0);
208         // 绘制二维码
209         _this.drawQRCode();
210       };
211     },
212     // 绘制二维码
213     drawQRCode() {
214       if (!this.qrcode) {
215         return;
216       }
217       let _this = this;
218       let img = new Image();
219       img.setAttribute("crossOrigin", "anonymous");
220       img.src = _this.qrcode + "?t=" + new Date().getTime(); // 去掉图片缓存
221       // console.log(_this.canvas.offsetWidth);
222       // console.log(_this.canvas.width);
223       // console.log(img.width);
224       // const ratio = _this.canvas.offsetWidth / _this.canvas.width;
225       img.onload = e => {
226         const img = e.path[0];
227         // const ratio = _this.canvas.offsetWidth / img.width;
228         // const size = ((_this.form.size || img.width) * ratio).toFixed(2);
229         // console.log(ratio);
230         // console.log(size);
231         // _this.qrSize = _this.form.size;
232         _this.context.drawImage(
233           img,
234           _this.form.posX,
235           _this.form.posY,
236           _this.form.size,
237           _this.form.size
238         );
239       };
240     },
241     // 提交
242     onSubmit() {
243       // console.log(this.form);
244       this.isLoading = true;
245       this.$refs.ruleForm.validate(async valid => {
246         if (valid) {
247           // console.log(this.form);
248           let base64Url = "";
249           try {
250             this.$message.loading({
251               content: "正在保存",
252               key: "savePoster",
253               duration: 5
254             });
255             base64Url = this.canvas.toDataURL("image/png", 1);
256             const response = (
257               await request({
258                 url: "/content/file/upload-oss-base64-image",
259                 method: "POST",
260                 data: {
261                   image: base64Url
262                 }
263               })
264             ).data;
265             if (!response.code) return;
266             if (response.code == 200) {
267               this.form.posterImg = response.data;
268               // console.log(this.form);
269               this.$emit("save", this.form);
270             } else {
271               this.$message.error({
272                 content: response.msg || response.message,
273                 key: "savePoster",
274                 duration: 2
275               });
276             }
277             this.isLoading = false;
278           } catch (error) {
279             this.$message.error({
280               content: "上传图片发生错误",
281               key: "savePoster",
282               duration: 2
283             });
284             this.isLoading = false;
285             // console.log(error);
286           }
287         } else {
288           // console.log("error submit!!");
289           this.isLoading = false;
290           return false;
291         }
292       });
293     },
294     // 上传分享卡片
295     uploadImg(option) {
296       this.form.img = option.imageUrl;
297     },
298     // 取消上传
299     cancel() {
300       this.$emit("cancel");
301     }
302   }
303 };
304 </script>
305 
306 <style scoped>
307 canvas {
308   width: 375px;
309   height: auto;
310   background-color: #ffffff;
311 }
312 </style>

 

版权声明:本文为kitty-blog原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/kitty-blog/p/14031798.html