海报图片生成前后端都能实现,个人喜欢在前端生成,主要是前端可以用html+css去实现海报样式,便于调试,对于熟悉前端代码的小伙伴来说再好不过。
以下是在vue项目中的实现,非vue前端同理。
思路及步骤:
1. 用html实现海报效果
制作海报模板图,用js二维码库生成二维码,用CSS的绝对定位实现二维码处于模板图上一层
2. 将html转canvas
用到第三方库html2canvas,npm install html2canvas
3. 将canvas转图片
用到第三方库canvas2image,这个库有点坑,它的源代码并没有实现模块化,然而却提交到了npmjs.com官网!!!无法直接引用其库,我是直接复制代码到项目中使用。
html部分
<el-button type="primary" @click="toShare()" size="small" icon="el-icon-share">生成海报</el-button> <!-- 海报生成html模板,为了不让海报显示在页面上,使用绝对定位,且让其漂移到页面外很远的地方 --> <div id="posterHtml" class="posterHtml" style="width:390px;height:693px;position:absolute;top:-10000px;left:-10000px;"> <img :src="'https://oss-exam.chanjet.com/ckt_html/poster_template/ec_poster.jpg'" crossorigin="anonymous" style="width:inherit;height:inherit;position:absolute;z-index: 10;" > <div style="width:inherit;height:inherit;position:absolute;z-index: 20;display: flex;flex-direction:column;justify-content: flex-start;align-items: center;"> <div style="font-size:18px;position:absolute;top:30px;width:100%;text-align: left;color:#FFFFCC;text-shadow: 0 8px 10px #FFFFCC;"> <div style="margin-left: 20px;font-family: 'Arial Black';">我们是【{{teamName}}】团队</div> <div style="margin-left: 20px;">正在参加“XX杯”XXXXXX大赛</div> <div style="margin-left: 20px;">请为我们的作品投一票吧~</div> </div> <!-- 二维码 --> <img id="posterQRCode" crossorigin="anonymous" style="width:200px;height:200px;position:absolute;top:420px;" /> </div> </div> <!-- 分享海报生成后的图片弹窗 --> <el-dialog width="350px" title="作品分享海报" v-if="posterVisible" :visible.sync="posterVisible" append-to-body> <div style="margin-top:-30px;display: flex;flex-direction:column;justify-content:center;align-items: center;"> <div id="myPosterContainer" style="width:100%;display: flex;justify-content: center;align-items: center;"></div> <div style="line-height: 30px;">长按图片保存或转发</div> </div> </el-dialog>
js部分
method: { toShare() { const text = this.getHost() + '/#/2023ec/videoVote?videoInfoId=' + this.videoInfoId // 生成二维码 QRCode.toDataURL(text, { width: 200, height: 200, src: '' }).then(url => { // <div style="margin:20px 0 20px 0"><img id="qrcode" :src="shortVideoQRCodeURL"/></div> document.querySelector('#posterQRCode').src = url this.createPoster() this.posterVisible = true }).catch(err => { console.error(err) }) }, createPoster() { // 生成海报 const vm = this; const domObj = document.getElementById('posterHtml'); var width = parseInt(domObj.style.width); var height = parseInt(domObj.style.height); var canvas = document.createElement('canvas'); var scale = 1; canvas.width = width * scale; canvas.height = height * scale; canvas.getContext('2d').scale(scale, scale); var opts = { scale: scale, canvas: canvas, width: width, height: height, useCORS: true, allowTaint: false, logging: false, letterRendering: true }; console.info('准备开始html2canvas') html2canvas(domObj, opts).then(function(canvas) { var context = canvas.getContext('2d'); // 重要 关闭抗锯齿 context.mozImageSmoothingEnabled = false; context.webkitImageSmoothingEnabled = false; context.msImageSmoothingEnabled = false; context.imageSmoothingEnabled = false; console.info('准备开始Canvas2Image') console.info('canvas2image:', Canvas2Image) var img = Canvas2Image.convertToImage( canvas, canvas.width, canvas.height ); vm.postshow = false; vm.postcode = false; // img.style.width = canvas.width / 2 + 'px'; img.style.width = '330px'; // img.style.height = canvas.height / 2 + 'px'; document.getElementById('myPosterContainer').appendChild(img); }); }, }
标签:海报,scale,false,canvas,height,width,二维码,var,H5 From: https://www.cnblogs.com/jsper/p/17466402.html