当前位置:   article > 正文

vue 生成二维码海报并进行微信分享_vue 生成图片+二维码 分享

vue 生成图片+二维码 分享

插件:Vue Canvas Poster 

网址:Vue Canvas Poster

1、安装

cnpm i vue-canvas-poster --save

2、使用

  1. <template>
  2. <div class="share wh100">
  3. <navBar title="邀请好友" :leftArrowFlag="true" />
  4. <div class="content">
  5. <h2>邀请亲友加入亲友团</h2>
  6. <p>
  7. 邀请亲友加入后,可与您一起编写逝者生平故事,留言、上传照片、跟您一起完善逝者信息、共同缅怀
  8. </p>
  9. <div class="share_item">
  10. <h3>方法一:长按海报发送朋友邀请加入</h3>
  11. <div class="item_content">
  12. <vue-canvas-poster
  13. :widthPixels="1000"
  14. :painting="painting"
  15. @success="success"
  16. @fail="fail"
  17. ></vue-canvas-poster>
  18. <div class="poster_box">
  19. <img v-if="showPoster" class="poster_img" :src="detail.posterImg" alt="" />
  20. </div>
  21. </div>
  22. </div>
  23. <div class="share_item">
  24. <h3>方法二:点击发送链接邀请亲朋加入</h3>
  25. <div class="item_content">
  26. <div class="large_btn" @click="wxShare"><span>点击发送链接邀请亲朋加入</span></div>
  27. </div>
  28. </div>
  29. </div>
  30. <van-overlay class="overlay_box" :show="show" @click="show = false">
  31. <div class="mask_content" @click="show = false">
  32. <img class="arrow" src="http://****/files/app/download/pic/arrow.png" alt="">
  33. <div class="mask_main">
  34. <div class="main_item">
  35. <div class="item_tip"><span>1</span></div>
  36. <div class="item_test">
  37. <span>点击右上角</span>
  38. <div class="item_btn">
  39. <span>. . .</span>
  40. </div>
  41. <span>按钮</span>
  42. </div>
  43. </div>
  44. <div class="main_item">
  45. <div class="item_tip"><span>2</span></div>
  46. <div class="item_test">
  47. <span>将本页面分享给好友</span>
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. </van-overlay>
  53. </div>
  54. </template>
  1. <script>
  2. import navBar from "@/components/navBar";
  3. import { VueCanvasPoster } from "vue-canvas-poster";
  4. import sdk from "@/utils/wxShare"
  5. import {getShareData} from '@/api/memorialHall'
  6. export default {
  7. data() {
  8. return {
  9. painting:null,
  10. showPoster:false,
  11. show:false,//显示隐藏
  12. detail: {
  13. posterImg:null
  14. },
  15. };
  16. },
  17. components: {
  18. navBar,
  19. VueCanvasPoster,
  20. },
  21. created() {
  22. console.log(this.detail.posterImg, "分享");
  23. this.getData(this.$route.params.id)
  24. },
  25. mounted() {
  26. },
  27. methods: {
  28. async getData(id) {
  29. let params={
  30. id
  31. }
  32. let res= await getShareData(params)
  33. console.log(res,'000')
  34. if(res.code!='2000'){
  35. this.$toast.fail(res.msg)
  36. return
  37. }
  38. this.detail=res.data;
  39. this.ininShare(res.data)
  40. this.initPoster(res.data)
  41. },
  42. ininShare(data){
  43. var ua = window.navigator.userAgent.toLowerCase();
  44. if (ua.match(/MicroMessenger/i) == 'micromessenger') {
  45. let obj={
  46. title: `${data.deadName}的纪念馆`,
  47. des:`${data. biography}`,
  48. linkurl: `http://**************/memorialHall/${data.id}`,//分享链接
  49. img: `${data.deadPortraitUrl}`,
  50. }
  51. // let url = encodeURIComponent(location.href.split('#')[0]);
  52. let url = location.href.split('#')[0];
  53. sdk.getJSSDK(url, obj)
  54. }else{
  55. }
  56. },
  57. initPoster(data){
  58. this.painting = {
  59. width: "275px",
  60. height: "365px",
  61. borderRadius: "5px",
  62. background: `${data.captionUrl}`,
  63. views: [
  64. {
  65. type: "image",
  66. url: `${data.deadPortraitUrl}`,
  67. css: {
  68. top: "20px",
  69. left: "107.5px",
  70. borderRadius: "30px",
  71. width: "60px",
  72. height: "60px",
  73. },
  74. },
  75. {
  76. type: "text",
  77. text: `${data.deadName}的纪念馆`,
  78. css: {
  79. top: "90px",
  80. fontSize: "14px",
  81. left: "90px",
  82. color: "#fff",
  83. textAlign: "center",
  84. },
  85. },
  86. {
  87. type: "text",
  88. text: `${data.birthday}-${data.deathday}`,
  89. css: {
  90. top: "110px",
  91. fontSize: "14px",
  92. left: "60px",
  93. color: "#fff",
  94. textAlign: "center",
  95. },
  96. },
  97. {
  98. type: "qrcode",
  99. content: `http://****/memorialHall/${data.id}`,
  100. css: {
  101. background: "#fff",
  102. padding: "10px",
  103. width: "100px",
  104. height: "100px",
  105. left: "90px",
  106. top: "170px",
  107. borderWidth: "10px",
  108. borderRadius: "1px",
  109. borderColor: "#fff",
  110. },
  111. },
  112. {
  113. type: "text",
  114. text: "扫码查看在线纪念馆",
  115. css: {
  116. bottom: "50px",
  117. fontSize: "14px",
  118. left: "80px",
  119. color: "#fff",
  120. textAlign: "center",
  121. },
  122. },
  123. ],
  124. };
  125. },
  126. success(src) {
  127. this.detail.posterImg = src;
  128. this.showPoster=true
  129. },
  130. fail(err) {
  131. console.log("fail", err);
  132. },
  133. wxShare(){
  134. this.show=true
  135. }
  136. },
  137. };
  138. </script>
  1. <style lang="scss" scoped>
  2. .share {
  3. display: flex;
  4. flex-direction: column;
  5. .content {
  6. flex: 1;
  7. padding: 0.12rem 0.37rem;
  8. // background-color: #3e3e3e;
  9. h2 {
  10. font-size: 16px;
  11. line-height: 0.23rem;
  12. font-weight: 600;
  13. margin-bottom: 0.07rem;
  14. }
  15. p {
  16. font-size: 14px;
  17. line-height: 0.2rem;
  18. color: $lightBlack;
  19. margin-bottom: 0.05rem;
  20. }
  21. .share_item {
  22. margin-bottom: 0.1rem;
  23. h3 {
  24. font-size: 16px;
  25. line-height: 0.23rem;
  26. font-weight: 600;
  27. margin-bottom: 0.07rem;
  28. }
  29. .item_content {
  30. display: flex;
  31. flex-direction: column;
  32. align-items: center;
  33. .poster_box {
  34. width: 2.75rem;
  35. height: 3.65rem;
  36. img{
  37. width: 100%;
  38. height: 100%;
  39. }
  40. }
  41. }
  42. }
  43. }
  44. }
  45. .overlay_box{
  46. .mask_content{
  47. padding:1rem 0.5rem;
  48. font-size: 14px;
  49. color: #fff;
  50. }
  51. .main_item{
  52. display: flex;
  53. align-items: center;
  54. margin-bottom: 0.2rem;
  55. }
  56. .item_test{
  57. display: flex;
  58. align-items: center;
  59. }
  60. .item_tip{
  61. width: 0.2rem;
  62. height: 0.2rem;
  63. border-radius: 50%;
  64. background: crimson;
  65. text-align: center;
  66. line-height: 0.2rem;
  67. margin-right: 0.15rem;
  68. }
  69. .item_btn{
  70. padding:0.05rem 0.1rem;
  71. text-align: center;
  72. height: 0.3rem;
  73. background: #282D32;
  74. border-radius: 0.05rem;
  75. margin:0 0.1rem;
  76. }
  77. .item_btn span{
  78. line-height: 0.2rem;
  79. }
  80. .arrow{
  81. position: absolute;
  82. right:0.2rem;
  83. top:0.2rem;
  84. display: block;
  85. width: 1rem;
  86. z-index: 6;
  87. }
  88. }
  89. </style>

wxShare.js

  1. import {wxSignatureVerification} from '@/api/wx'
  2. import {Toast} from 'vant'
  3. //import wx from 'weixin-js-sdk';
  4. import wx from 'weixin-jsapi';
  5. //
  6. //要用到微信API
  7. function getJSSDK(url,shareData) {
  8. let params={url}
  9. console.log(wx,params,'url参数')
  10. wxSignatureVerification(params).then(res => {
  11. console.log('22222',res,shareData);
  12. if(res.code!='2000')return Toast.fail('微信验签失败')
  13. let result=res.data.wxConfig
  14. wx.config({
  15. debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
  16. appId: res.data.appId, // 必填,公众号的唯一标识
  17. timestamp: result.timestamp, // 必填,生成签名的时间戳
  18. nonceStr: result.nonceStr, // 必填,生成签名的随机串
  19. signature: result.signature, // 必填,签名
  20. jsApiList:[
  21. 'onMenuShareTimeline',
  22. 'onMenuShareAppMessage'
  23. ]
  24. })
  25. wx.ready(function () {
  26. //分享给微信朋友
  27. wx.onMenuShareAppMessage({
  28. title: shareData.title,
  29. desc: shareData.des,
  30. link: shareData.linkurl,
  31. imgUrl: shareData.img,
  32. success: function success(res) {
  33. Toast.success('分享成功')
  34. },
  35. cancel: function cancel(res) {
  36. console.log('已取消');
  37. },
  38. fail: function fail(res) {
  39. //alert(JSON.stringify(res));
  40. }
  41. });
  42. // 2.2 监听“分享到朋友圈”按钮点击、自定义分享内容及分享结果接口
  43. wx.onMenuShareTimeline({
  44. title: shareData.title,
  45. link: shareData.linkurl,
  46. imgUrl: shareData.img,
  47. success: function success(res) {
  48. //alert('已分享');
  49. },
  50. cancel: function cancel(res) {
  51. //alert('已取消');
  52. },
  53. fail: function fail(res) {
  54. //alert(JSON.stringify(res));
  55. }
  56. });
  57. // 2.3 监听“分享到QQ”按钮点击、自定义分享内容及分享结果接口
  58. // wx.onMenuShareQQ({
  59. // title: shareData.title,
  60. // desc: shareData.desc,
  61. // link: shareData.linkurl,
  62. // imgUrl: shareData.img,
  63. // trigger: function trigger(res) {
  64. // //alert('用户点击分享到QQ');
  65. // },
  66. // complete: function complete(res) {
  67. // alert(JSON.stringify(res));
  68. // },
  69. // success: function success(res) {
  70. // //alert('已分享');
  71. // },
  72. // cancel: function cancel(res) {
  73. // //alert('已取消');
  74. // },
  75. // fail: function fail(res) {
  76. // //alert(JSON.stringify(res));
  77. // }
  78. // });
  79. // 2.4 监听“分享到微博”按钮点击、自定义分享内容及分享结果接口
  80. // wx.onMenuShareWeibo({
  81. // title: shareData.title,
  82. // desc: shareData.desc,
  83. // link: shareData.linkurl,
  84. // imgUrl: shareData.img,
  85. // trigger: function trigger(res) {
  86. // //alert('用户点击分享到微博');
  87. // },
  88. // complete: function complete(res) {
  89. // // alert(JSON.stringify(res));
  90. // },
  91. // success: function success(res) {
  92. // //alert('已分享');
  93. // },
  94. // cancel: function cancel(res) {
  95. // // alert('已取消');
  96. // },
  97. // fail: function fail(res) {
  98. // // alert(JSON.stringify(res));
  99. // }
  100. // });
  101. })
  102. wx.error(function (res) {
  103. //alert("微信验证失败");
  104. });
  105. })
  106. }
  107. export default {
  108. // 获取JSSDK
  109. getJSSDK
  110. }

备注

该方案生成的海报二维码在IOS上扫描报错,所以更改方案 :生成二维码图片之后在用二维码图片绘制到海报上生成海报

更改后代码:

  1. <template>
  2. <div class="share wh100">
  3. <navBar title="邀请好友" :leftArrowFlag="true" />
  4. <div class="content">
  5. <h2>邀请亲友加入亲友团</h2>
  6. <p>
  7. 邀请亲友加入后,可与您一起编写逝者生平故事,留言、上传照片、跟您一起完善逝者信息、共同缅怀
  8. </p>
  9. <div class="share_item">
  10. <h3>方法一:长按海报发送朋友邀请加入</h3>
  11. <div class="item_content">
  12. <vue-canvas-poster
  13. :widthPixels="1000"
  14. :painting="painting"
  15. @success="success"
  16. @fail="fail"
  17. ></vue-canvas-poster>
  18. <div class="poster_box">
  19. <img
  20. v-if="showPoster"
  21. class="poster_img"
  22. :src="detail.posterImg"
  23. alt=""
  24. />
  25. </div>
  26. </div>
  27. </div>
  28. <div class="share_item">
  29. <h3>方法二:点击发送链接邀请亲朋加入</h3>
  30. <div class="item_content">
  31. <div class="large_btn" @click="wxShare">
  32. <span>点击发送链接邀请亲朋加入</span>
  33. </div>
  34. </div>
  35. </div>
  36. </div>
  37. <van-overlay class="overlay_box" :show="show" @click="show = false">
  38. <div class="mask_content" @click="show = false">
  39. <img
  40. class="arrow"
  41. src="http://linyiapi.fushoubainian.com/files/app/download/pic/arrow.png"
  42. alt=""
  43. />
  44. <div class="mask_main">
  45. <div class="main_item">
  46. <div class="item_tip"><span>1</span></div>
  47. <div class="item_test">
  48. <span>点击右上角</span>
  49. <div class="item_btn">
  50. <span>. . .</span>
  51. </div>
  52. <span>按钮</span>
  53. </div>
  54. </div>
  55. <div class="main_item">
  56. <div class="item_tip"><span>2</span></div>
  57. <div class="item_test">
  58. <span>将本页面分享给好友</span>
  59. </div>
  60. </div>
  61. </div>
  62. </div>
  63. </van-overlay>
  64. <div id="qrcode"></div>
  65. </div>
  66. </template>
  67. <script>
  68. import navBar from "@/components/navBar";
  69. import { VueCanvasPoster } from "vue-canvas-poster";
  70. import sdk from "@/utils/wxShare";
  71. import { getShareData } from "@/api/memorialHall";
  72. import QRCode from "qrcodejs2";
  73. export default {
  74. data() {
  75. return {
  76. loading: null,
  77. painting: null,
  78. qrcode: "", //二维码
  79. defaultAvatar: require("@/assets/imgs/avatar.png"),
  80. showPoster: false,
  81. show: false, //显示隐藏
  82. detail: {
  83. posterImg: null,
  84. },
  85. };
  86. },
  87. components: {
  88. navBar,
  89. VueCanvasPoster,
  90. },
  91. created() {
  92. console.log(this.detail.posterImg, "分享");
  93. this.getData(this.$route.params.id);
  94. },
  95. mounted() {
  96. var ua = window.navigator.userAgent.toLowerCase();
  97. if (ua.match(/MicroMessenger/i) == "micromessenger") {
  98. var u = navigator.userAgent,
  99. app = navigator.appVersion;
  100. var isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
  101. if (isIOS) {
  102. if (window.location.href.indexOf("#reloaded") == -1) {
  103. window.location.href = window.location.href + "#reloaded";
  104. window.location.reload();
  105. }
  106. }
  107. }
  108. },
  109. methods: {
  110. getCodeSrc(link) {
  111. return new Promise((resolve, reject) => {
  112. document.getElementById("qrcode").innerHTML = "";
  113. this.qrcode = new QRCode("qrcode", {
  114. width: 124,
  115. height: 124, // 高度
  116. text: link, // 二维码内容
  117. // render: 'canvas' , // 设置渲染方式(有两种方式 table和canvas,默认是canvas)
  118. // background: '#f0f', // 背景色
  119. // foreground: '#ff0' // 前景色
  120. });
  121. console.log(this.qrcode, "kkkk");
  122. var canvas = this.qrcode._oDrawing._elCanvas;
  123. //如果有循环,此句必不可少 qrcode.find('canvas').remove();
  124. var src = canvas.toDataURL("image/jpg");
  125. resolve(src);
  126. });
  127. },
  128. async getData(id) {
  129. let params = {
  130. id,
  131. };
  132. let res = await getShareData(params);
  133. if (res.code != "2000") {
  134. this.$toast.fail(res.msg || "数据请求失败");
  135. return;
  136. }
  137. this.detail = res.data;
  138. this.initPoster(res.data);
  139. },
  140. ininShare(data) {
  141. var ua = window.navigator.userAgent.toLowerCase();
  142. if (ua.match(/MicroMessenger/i) == "micromessenger") {
  143. let obj = {
  144. title: `${data.deadName}的纪念馆`,
  145. des: `${data.biography}`,
  146. linkurl: `http://*****/memorialHall/${data.id}`, //分享链接
  147. img: `${data.deadPortraitUrl}`,
  148. };
  149. // let url = encodeURIComponent(location.href.split('#')[0]);
  150. let url = location.href.split("#")[0];
  151. sdk.getJSSDK(url, obj);
  152. } else {
  153. }
  154. },
  155. initPoster(data) {
  156. this.loading = this.$toast.loading({
  157. message: "加载中...",
  158. forbidClick: true,
  159. });
  160. this.getCodeSrc(
  161. `http://*****/memorialHall/${data.id}`
  162. ).then((res) => {
  163. this.painting = {
  164. width: "300px",
  165. height: "400px",
  166. borderRadius: "5px",
  167. background: `${data.captionUrl}`,
  168. views: [
  169. {
  170. type: "image",
  171. url: data.deadPortraitUrl
  172. ? `${data.deadPortraitUrl}`
  173. : this.defaultAvatar,
  174. css: {
  175. top: "20px",
  176. left: "120px",
  177. borderRadius: "30px",
  178. width: "60px",
  179. height: "60px",
  180. },
  181. },
  182. {
  183. type: "text",
  184. text: `${data.deadName}的纪念馆`,
  185. css: {
  186. top: "90px",
  187. fontSize: "14px",
  188. left: "105px",
  189. color: "#fff",
  190. textAlign: "center",
  191. },
  192. },
  193. {
  194. type: "text",
  195. text: `${data.birthday}${data.deathday}`,
  196. css: {
  197. top: "120px",
  198. fontSize: "14px",
  199. left: "70px",
  200. color: "#fff",
  201. textAlign: "center",
  202. },
  203. },
  204. {
  205. type: "image",
  206. url: res,
  207. css: {
  208. background: "#fff",
  209. top: "250px",
  210. left: "100px",
  211. width: "100px",
  212. height: "100px",
  213. borderWidth: "6px",
  214. borderRadius: "1px",
  215. borderColor: "#fff",
  216. },
  217. },
  218. // {
  219. // type: "qrcode",
  220. // content: `http://****/memorialHall/${data.id}`,
  221. // css: {
  222. // background: "#fff",
  223. // width: "100px",
  224. // height: "100px",
  225. // left: "100px",
  226. // top: "210px",
  227. // borderWidth: "10px",
  228. // borderRadius: "1px",
  229. // borderColor: "#fff",
  230. // },
  231. // },
  232. {
  233. type: "text",
  234. text: "扫码查看在线纪念馆",
  235. css: {
  236. bottom: "20px",
  237. fontSize: "14px",
  238. left: "90px",
  239. color: "#fff",
  240. textAlign: "center",
  241. },
  242. },
  243. ],
  244. };
  245. });
  246. },
  247. success(src) {
  248. console.log(src, "哈哈哈哈");
  249. this.$toast.clear();
  250. this.detail.posterImg = src;
  251. this.showPoster = true;
  252. },
  253. fail(err) {
  254. console.log("fail", err);
  255. },
  256. wxShare() {
  257. this.show = true;
  258. },
  259. },
  260. };
  261. </script>
  262. <style lang="scss" scoped>
  263. .share {
  264. display: -webkit-box;
  265. display: -moz-box;
  266. display: -ms-flexbox;
  267. display: -webkit-flex;
  268. display: flex;
  269. -moz-flex-direction: column;
  270. -webkit-flex-direction: column;
  271. flex-direction: column;
  272. #qrcode {
  273. display: none;
  274. }
  275. .content {
  276. flex: 1;
  277. padding: 0.05rem 0.37rem;
  278. // background-color: #3e3e3e;
  279. overflow-y: scroll;
  280. h2 {
  281. font-size: 14px;
  282. line-height: 0.2rem;
  283. font-weight: 600;
  284. margin-bottom: 0.07rem;
  285. }
  286. p {
  287. font-size: 14px;
  288. line-height: 0.2rem;
  289. color: $lightBlack;
  290. margin-bottom: 0.05rem;
  291. }
  292. .share_item {
  293. margin-bottom: 0.1rem;
  294. h3 {
  295. font-size: 14px;
  296. line-height: 0.2rem;
  297. font-weight: 600;
  298. margin-bottom: 0.07rem;
  299. }
  300. .item_content {
  301. display: -webkit-box;
  302. display: -moz-box;
  303. display: -ms-flexbox;
  304. display: -webkit-flex;
  305. display: flex;
  306. -moz-flex-direction: column;
  307. -webkit-flex-direction: column;
  308. flex-direction: column;
  309. -moz-align-items: center;
  310. -webkit-align-items: center;
  311. align-items: center;
  312. .poster_box {
  313. width: 3rem;
  314. height: 4rem;
  315. img {
  316. width: 100%;
  317. height: 100%;
  318. }
  319. }
  320. }
  321. }
  322. }
  323. }
  324. .overlay_box {
  325. .mask_content {
  326. padding: 1rem 0.5rem;
  327. font-size: 14px;
  328. color: #fff;
  329. }
  330. .main_item {
  331. display: -webkit-box;
  332. display: -moz-box;
  333. display: -ms-flexbox;
  334. display: -webkit-flex;
  335. display: flex;
  336. -moz-align-items: center;
  337. -webkit-align-items: center;
  338. align-items: center;
  339. margin-bottom: 0.2rem;
  340. }
  341. .item_test {
  342. display: -webkit-box;
  343. display: -moz-box;
  344. display: -ms-flexbox;
  345. display: -webkit-flex;
  346. display: flex;
  347. -moz-align-items: center;
  348. -webkit-align-items: center;
  349. align-items: center;
  350. }
  351. .item_tip {
  352. width: 0.2rem;
  353. height: 0.2rem;
  354. border-radius: 50%;
  355. background: crimson;
  356. text-align: center;
  357. line-height: 0.2rem;
  358. margin-right: 0.15rem;
  359. }
  360. .item_btn {
  361. padding: 0.05rem 0.1rem;
  362. text-align: center;
  363. height: 0.3rem;
  364. background: #282d32;
  365. border-radius: 0.05rem;
  366. margin: 0 0.1rem;
  367. }
  368. .item_btn span {
  369. line-height: 0.2rem;
  370. }
  371. .arrow {
  372. position: absolute;
  373. right: 0.2rem;
  374. top: 0.2rem;
  375. display: block;
  376. width: 1rem;
  377. z-index: 6;
  378. }
  379. }
  380. </style>

图片跨域

1.如果图片在你自己的服务器上,配置 nginx

  1. location / {
  2. add_header Access-Control-Allow-Origin *;
  3. add_header Access-Control-Allow-Headers "Origin, X-Requested-With, Content-Type, Accept";
  4. add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
  5. add_header Access-Control-Allow-Credentials "true";
  6. if ($request_method = "OPTIONS") {
  7. add_header Access-Control-Allow-Origin *;
  8. add_header Access-Control-Allow-Methods "GET, POST, OPTIONS";
  9. return 204;
  10. }
  11. }
  12. location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
  13. {
  14. add_header Access-Control-Allow-Origin *;
  15. expires 30d;
  16. error_log off;
  17. access_log /dev/null;
  18. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/101825
推荐阅读
相关标签