zoukankan      html  css  js  c++  java
  • 使用canvas 自定义海报 (自定义二维码位置、实时预览)

    生成海报: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            _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    375px;
    309   height: auto;
    310   background-color: #ffffff;
    311 }
    312 </style>
  • 相关阅读:
    CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡
    三大WEB服务器对比分析(apache ,lighttpd,nginx)
    linux sudo 命令
    linux 添加用户、权限
    LeetCode——Find Largest Value in Each Tree Row
    LeetCode——Single Element in a Sorted Array
    LeetCode——Find All Duplicates in an Array
    LeetCode—— Partition Equal Subset Sum
    LeetCode——Unique Binary Search Trees II
    LeetCode——Is Subsequence
  • 原文地址:https://www.cnblogs.com/kitty-blog/p/14031798.html
Copyright © 2011-2022 走看看