当前位置: 首页 > news >正文

北京seo做排名重庆seo整站优化

北京seo做排名,重庆seo整站优化,仿制网站建设,百度自动点击器下载最近工作中遇到一个需求#xff0c;类似这样 点击商品二维码#xff0c;生成一张带有商品图片、标题、描述、二维码等信息的图片#xff0c;用户长按进行保存。 在使用html2canvas进行项目开发的时候#xff0c;遇到很多的问题#xff0c;主要为一下方面#xff1a; 1、…最近工作中遇到一个需求类似这样 点击商品二维码生成一张带有商品图片、标题、描述、二维码等信息的图片用户长按进行保存。 在使用html2canvas进行项目开发的时候遇到很多的问题主要为一下方面 1、图片跨域问题 2、截图不全问题 3、html2canvas在IOS13.4.1 上失效问题 4、canvas 嵌套 canvas 问题 5、img标签使用 base64 文件 在安卓真机上闪退问题 下面把我的探坑之旅和解决思路做个梳理 → 需求实现主要为以下三大步 第一如何生成二维码 第二如何生成图片 第三如何实现长按保存 如何生成二维码 这里我使用的是 qrcode 插件(官网地址https://davidshimjs.github.io/qrcodejs/) QRCode组件 附上代码 import React, { PureComponent } from react import QRCode from qrcode import { color as d3Color } from d3-color/*** 转化css颜色值为 RGBA hex形式的值 比如: #fff #ffffffff* param {css color} cssColor - css颜色值*/ const convertColor (cssColor) {const temp d3Color(cssColor)if (temp null) {return undefined}const alpha Number(((temp.a || 1) * 255).toFixed(0))const result [temp.r, temp.g, temp.b, alpha].map((e) {const s e.toString(16)return s.length 2 ? 0${s} : s}).join()return result }// 合并配置信息 const mergeConfig (options) {const {ecLevel,margin,width,color,background, // scale,} optionsreturn {errorCorrectionLevel: ecLevel || M, // L, M, Q, H,margin: margin || 2,// scale: scale || 4,width: width || 100,color: {dark: convertColor(color) || #000000ff,light: convertColor(background) || #ffffffff,},} }export default class ReactQRCode extends PureComponent {componentDidMount () {this.draw()}componentDidUpdate () {this.draw()}draw () {const { value, onDrowSuccess, ...rest } this.propsconst cfg mergeConfig(rest)QRCode.toCanvas(this.canvas, ${value}, cfg).then(() {onDrowSuccess onDrowSuccess(this.canvas.toDataURL(image/jpeg))}).catch((err) {window.console.error(err)})}render() {return (canvasstyle{{ width: 0 }}ref{(ref) {this.canvas ref}}/)} }调用方式 QRCode valuehttp://abc width{240} colorblack background#fff ecLevelH /如何生成图片 经过多方考察调研最终我使用的是 html2Canvas插件官网地址http://html2canvas.hertzen.com/ html2Canvas的git⭐️⭐️指数还挺高的并且浏览器兼容版本还不错。 下面开始进入正题→ 首先想要使用html2Canvas画图之前我们需要确保想要绘制的html页面已经生成否则画出来的图可能不完整所以我们将画图的操作放到 componentDidMount 这一生命周期进行确保页面已经渲染完成。 附上代码 class DrowProductQrCode extends Component {componentDidMount() {// 获取dom节点this.element document.getElementById(productQrCode)this.canvas2Image()}canvas2Image () {html2canvas(this.element).then((canvas) {const url canvas.toDataURL(image/jpeg)const oImg document.createElement(img)oImg.href urldocument.body.appendChild(oImg)})}render() {const { qrCodeUrl, goodImg, name, title } this.propsreturn (div className{styles.container} idproductQrCodeFlexdiv className{styles.goodImg}img className{styles.img} crossOriginAnonymous src{goodImg} alt商品图片 //divdiv className{styles.goodInfo}div className{styles.title}{name}/divdiv className{styles.desc}{title}/div/div/FlexQrCode value{qrCodeUrl} width{220} /div className{styles.tips}扫描上面的二维码查看内容/div/div)} }这时候我们会发现控制台报错了 最直观的报错提示 been blocked by CORS policy: Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled. 意思是我们的 图片 跨域了因为我们的图片大多都存储在阿里云或者其他服务器上从我们本地去使用canvas去访问这张图片时会存在跨域问题。 接下来如何解决跨域问题成了关键 根据 html2Canvas 的官方文档我们可以知道 html2Canvas为我们提供了两个参数以解决跨域问题而这里根据我们的报错信息by CORS policy我们使用的就是useCORS。 于是我们给代码加上这一参数 html2canvas(this.element, {useCORS: true,}).then((canvas) {...})结果还是不起作用我们再一次在控制台看见了这可怕的鲜红字眼 这是怎么回事呐 原来当我们在设置 useCORS: true 这一参数时需要给img 标签加上 允许跨域的 标识crossOrigin“Anonymous” 像这样 img className{styles.img} crossOriginAnonymous src{goodImg} alt商品图片 / 这时候我的内心已经小有雀跃了持着激动的心颤抖的手按下了保存按钮 啊哦。。。 这可怕的鲜红字眼又出现了。。 但其中有一条信息非常值得我们关注No ‘Access-Control-Allow-Origin’ header is present on the requested resource. 这表明我们需要我们的后端在我们请求这张图片时给我么加上 Access-Control-Allow-Origin 允许跨域访问的域名 这项设置必须这张图片是允许我们这个域 跨域访问时 我们才能成功拿到这张图片。 有的人很好奇为什么平时我们的代码中 使用过那么多img 标签为什么没有遇到这个问题。这是因为 我们给 img 标签设置了 crossOrigin“Anonymous” 这才导致的。 接下来我就屁颠屁颠去找到我司可爱的运维小哥让他把我的域给允许跨域了。 现在现在我感觉已经越过了艰难险阻是时候看见光明了我再次怀着激动的心颤抖的手刷新页面 我 我 我 我去 这鲜红的字眼 让我有点恶心了 这 这 究竟是怎么肥事我不忙明白了。运营小哥也仔仔细细的看了他加的配置 写错了字母 于是我的眼里又燃起了希望呀运营小哥一顿操作猛如虎图片请求还是 500 这时候我注意到了一个问题 为什么 5f68413ce4b0c9f1400679f6.jpg 这张图片被请求了好几次而且居然前面还有请求成功的。这这。。 这时候百度的一篇文章给了我答案 CORS的配置方法一般是针对每个访问来源单独配置规则勿将多个来源驾到一个规则多个规则之间不要有覆盖冲突。原来因为我是在商品详情页引入的 DrowProductQrCode 组件商品详情页可能有很多地方在同时访问这张商品的图片这就导致了我们的配置冲突了这张图片到底是走缓存还是走请求走请求是一次还是多次 所以我灵机一动给我们的 卡片 DrowProductQrCode 里的这张图片加上一个时间戳这样浏览器每次就会认为这是一个新的请求这样就不在存在以上问题了。 const getTimestamp new Date().getTime() goodImg ${goodImg}?timestamp${getTimestamp}再次怀着激动的心颤抖的手按下保存按钮, 终于成功的出来了商品图片 但是里面的二维码却没有出来。。。。 这这又是为什么呐 我们在仔仔细细的康康我们代码 我们在我们将要绘制canvas的html片段里又嵌套了一个canvas,这可如何是好canvas画图的时候没有支持这个canvas嵌套canvas的操作。 接下来如何解决canvas嵌套canvas的操作问题又成了关键 其实这很好解决 如果不能使canvas嵌套canvas那我们就把里面的cavas转化成为html,不就行了 // 在 QrCode 组件上传入一个回调函数当二维码的 canvas 绘制完成之后我们将canvas 转化成为 base 64 的文件返回回来 QrCode onDrowSuccess{this.drowQrCodeSuccess} value{invitaionUrl(currentUserId, id)} width{220} / 我们的再去调一下后端上传图片的接口将base 64 的图片上传上去得到存在我们自己服务器上的二维码 url. /*** 将以base64的图片url数据转换为Blob* param base64 用url方式表示的base64图片数据* return blob 返回blob对象*/ function dataURItoBlob(dataURI) {let byteStringif (dataURI.split(,)[0].indexOf(base64) 0) byteString atob(dataURI.split(,)[1])else byteString unescape(dataURI.split(,)[1])const mimeString dataURI.split(,)[0].split(:)[1].split(;)[0]const ia new Uint8Array(byteString.length)for (let i 0; i byteString.length; i) {ia[i] byteString.charCodeAt(i)}return new Blob([ia], { type: mimeString }) }drowQrCodeSuccess (url) {uploadPublicFile(dataURItoBlob(url)).then((data) {const imgUrl getOssFileUrl(data)this.setState({qrCodeUrl: imgUrl,})}).catch(err console.log(err, err))}大家一定也想问为什么不直接用base 64 的图片作为 img 标签的 url 放在 html 文件里继续往后面读。。。 就这样我们的 二维码 卡片 canvas终于画出来了普天同庆可喜可贺 吗 我们突然发现画出来的canvas图不太完整少了一些东西 头 头 头有点大… 接下来如何解决截图不完整问题又成了关键 经过多方调研发现是因为我们的内容过长出现了滚动条或者其他原因导致 html2Canvas 截图不完整网上有很多解决方法但是经过我的多方实践如果是出现了滚动条最好用的方法还是这个 加上这两个参数就可以了简单粗暴效果完美 接下来就是最后一步 如何实现长按保存 二维码卡片画出来了接下来就是保存图片。 老规矩我们先将canvas 转化为 url const url canvas.toDataURL(image/jpeg)然后写一个长按下载函数 componentDidMount() {// 监听容器点击事件this.longPress(this.downloadImg, this.element)}// 组件销毁时移除监听事件componentWillUnmount() {this.element.removeEventListener(touchstart, this.touchstart)this.element.removeEventListener(touchend, this.touchend)}// 封装一个长按方法longPress () {this.timeout 0this.element.addEventListener(touchstart, this.touchstart, false)this.element.addEventListener(touchend, this.touchend, false)}touchstart () {// 长按时间超过800ms则执行传入的方法this.timeout setTimeout(this.downloadImg, 800)}touchend () {// 长按时间少于800ms不会执行传入的方法clearTimeout(this.timeout)}// 图片下载downloadImg () {const { goodQrCode, fileName } this.propsconst oImg document.createElement(a)oImg.download fileNameoImg.href goodQrCodeoImg.click()oImg.remove()}致此下载就此完成。在pc端操作起来特别顺畅 于是我拿出测试机在ios手机上测试, IOS手机长按会自动调起系统的保存图片方法好像没什么问题虽然没使用我们的代码但是目的是达到了。接下来就是安卓机 长按闪退。。。 长按 闪退。。。 换个安卓机 长按闪退。。。 长按 闪退。。。 怎么肥事。。 拿出数据线打开uc-devtools, 连接手机真机调试一看发现每次长按后页面就被 crash 掉了。经过百度发现因为 base 64的文件太长了在很多手机上无法支持预览及下载。 这下明白了为什么我上面生成的 qrCode 为什么不直接使用 base 64的文件作为 img 的 src 路径了吧。 老办法我们调用后端接口将图片上传到我们自己的服务器然后用后端返回的地址作为图片链接。 你以为这就结束了吗 no no no 坑还没踏完呐 测试在测试的时候发现ios的一款手机的二维码怎么也出不来 经过调查发现我所使用的 html2canvas 版本1.0.0-rc.7 在IOS13.4.1 系统版本不生效需要把它降到 html2canvas 1.0.0-rc.4 版本方可成功 附上代码 - // npm 管理 // 先卸载旧版本 npm uninstall html2canvas // 安装新版本 npm install --save html2canvas1.0.0-rc.4// yarn 管理 // 先卸载旧版本 yarn remove html2canvas // 安装新版本 yarn add html2canvas1.0.0-rc.4 完美解决 但是大家也知道使用 a 标签下载图片 基本不太现实他只能新开一个窗口预览图片然后用户自己手动截屏或者靠系统、浏览器自带的长按保存图片方法。想要是实现长按保存的效果只能靠调起 native 方法、或者后端实现下载功能我们请求接口来得以实现。 那么问题来如果后端和native都不愿意或者没法实现产品又非让你做出这个效果来 那你就… 你就… 你就… 找他理论(低头)去 最后附上完整代码逻辑 GoodsDetailPage handleCanvas2ImageOK (url) {this.setState({goodQrCode: url,productQrCodeDivShow: false,})}render() {return {div// 商品二维码卡片GoodQrCodeModal// 影藏modal弹框方法hideCodeModal{this.hideCodeModal}// 是否展示modal弹框codeModalShow{codeModalShow}// qrcode 生成的二维码上传到后端后的url地址goodQrCode{goodQrCode}// 下载的文件名fileName{name}/// 生成商品二维码的HTML代码 通过 productQrCodeDivShow 字段控制其展示// productQrCodeDivShow 的作用就是让GoodsDetailPage页面渲染时将 商品二维码卡片 生成然后返回 商品二维码卡片 的url, 影藏商品二维码的HTML。{productQrCodeDivShow (ProductQrCodecurrentUserId{userId}detail{detail}onCanvas2ImageOK{this.handleCanvas2ImageOK}/)}/div} }ProductQrCode /*** 将以base64的图片url数据转换为Blob* param base64 用url方式表示的base64图片数据* return blob 返回blob对象*/ function dataURItoBlob(dataURI) {let byteStringif (dataURI.split(,)[0].indexOf(base64) 0) byteString atob(dataURI.split(,)[1])else byteString unescape(dataURI.split(,)[1])const mimeString dataURI.split(,)[0].split(:)[1].split(;)[0]const ia new Uint8Array(byteString.length)for (let i 0; i byteString.length; i) {ia[i] byteString.charCodeAt(i)}return new Blob([ia], { type: mimeString }) }class ProductQrCode extends Component {state {qrCodeUrl: ,}componentDidMount() {}drowQrCodeSuccess (url) {uploadPublicFile(dataURItoBlob(url)).then((data) {const imgUrl getOssFileUrl(data)this.setState({qrCodeUrl: imgUrl,})}).catch(err console.log(err, err))}render() {const { currentUserId, detail, onCanvas2ImageOK } this.propsconst { name, title, pics, id } detail || []const getTimestamp new Date().getTime()let goodImg getObjField(getOssFileUrl(pics), [0])goodImg ${goodImg}?timestamp${getTimestamp}const { qrCodeUrl } this.statereturn (divQrCode onDrowSuccess{this.drowQrCodeSuccess} value{invitaionUrl(currentUserId, id)} width{220} /// 确保qrcode 已生成 二维码并且上传到服务器获取到url地址{qrCodeUrl (DrowProductQrCodeonCanvas2ImageOK{onCanvas2ImageOK}qrCodeUrl{qrCodeUrl}name{name}title{title}goodImg{goodImg}/)}/div)} }export default ProductQrCodeclass DrowProductQrCode extends Component {componentDidMount() {// 获取dom节点this.element document.getElementById(productQrCode)this.canvas2Image()}canvas2Image () {const { onCanvas2ImageOK } this.propshtml2canvas(this.element, {// 允许跨域 (allowTaint, useCORS)设置其一useCORS: true,scrolly: 0,scrollx: 0,}).then((canvas) {const url canvas.toDataURL(image/jpeg)// 将canvas生成的 base64 的地址转化为 blobbase64 过长导致手机下载出现问题 , 上传到oss获取图片URLconst blobFile dataURItoBlob(url)uploadPublicFile(blobFile).then((data) {const imgUrl getOssFileUrl(data)onCanvas2ImageOK onCanvas2ImageOK(imgUrl)}).catch(err console.log(err, err))})}render() {const { qrCodeUrl, goodImg, name, title } this.propsreturn (div className{styles.container} idproductQrCodeFlexdiv className{styles.goodImg}img className{styles.img} crossOriginAnonymous src{goodImg} alt商品图片 //divdiv className{styles.goodInfo}div className{styles.title}{name}/divdiv className{styles.desc}{title}/div/div/Fleximg className{styles.qrCode} crossOriginAnonymous src{qrCodeUrl} alt商品图片 /div className{styles.tips}扫描上面的二维码查看内容/div/div)} }GoodQrCodeModal import React from react import { Modal } from antd-mobile import styles from ./GoodQrCodeModal.scssclass GoodQrCodeModal extends React.PureComponent {componentDidMount() {}render() {const {codeModalShow, hideCodeModal, goodQrCode, fileName,} this.propsreturn (ModalclassName{styles.codeModal}visible{codeModalShow}maskClosabletransparentonClose{hideCodeModal}GoodQrCodeImg goodQrCode{goodQrCode} fileName{fileName} //Modal)} }export default GoodQrCodeModalclass GoodQrCodeImg extends React.PureComponent {componentDidMount() {this.element document.getElementById(goodQrCode)// 监听容器点击事件this.longPress(this.downloadImg, this.element)}componentWillUnmount() {this.element.removeEventListener(touchstart, this.touchstart)this.element.removeEventListener(touchend, this.touchend)}// 封装一个长按方法longPress () {this.timeout 0this.element.addEventListener(touchstart, this.touchstart, false)this.element.addEventListener(touchend, this.touchend, false)}touchstart () {// 长按时间超过800ms则执行传入的方法this.timeout setTimeout(this.downloadImg, 800)}touchend () {// 长按时间少于800ms不会执行传入的方法clearTimeout(this.timeout)}// 图片下载downloadImg () {const { goodQrCode, fileName } this.propsconst oImg document.createElement(a)oImg.download fileNameoImg.href goodQrCodeoImg.click()oImg.remove()}render() {const { goodQrCode } this.propsreturn (img idgoodQrCode className{styles.goodQrCode} src{goodQrCode} alt商品二维码 /)} }以上就是全部大致思路啦 如有bug, 请多指教✍️✍️✍️ 如果对你有帮助就给我点个赞吧
http://www.pierceye.com/news/259160/

相关文章:

  • 域名查询网ip郑州百度网站优化
  • 泉州网站建设 乐本园东昌府网站制作
  • 电子产品配件采购网站阿里云 虚拟主机 wordpress
  • 网站的电子手册用什么做的百度云搜索引擎官网
  • 网站代码隐蔽代码jsp网站开发pdf
  • 厚街手机网站制作网站开发年终总结
  • 泉州网站建设技术外包网站建设的具体奖罚措施
  • 汕头企业网站推广技巧南宁关键词网站排名
  • 做我的世界背景图的网站阿里云服务器做网站外网访问慢
  • 云南百度智能建站登录wordpress数据库吗
  • 万网买好域名后如何开通网站网站历史记录怎么恢复
  • 游戏租号网站开发网页设计的技术有哪些
  • 工信部网站备案文件合肥网站制作建设
  • 网站架设标准网站域名注册费用
  • 东莞网站制作功能十堰微网站建设价格
  • google关键词分析工具网站建设seo 视频教程
  • 泸州市规划建设局网站网站建设及维护包括范围
  • 网站设计培训成都哪个网站开发软件
  • 四川炜航建筑公司网站新郑网络推广外包
  • 网站建设名头网站项目建设方案
  • 可以用asp做哪些网站简历模板大学生免费
  • 公司 宜宾网站建设头条小程序
  • 大连h5建站学院网站建设申请报告
  • 大蒜做营销型网站贵州最好的网站建设推广公司
  • 单仁资讯做网站怎样备案网站应用服务
  • 如何生成一个网站怎么查看一个网站有没有做推广
  • 温州网站设计案例wdcp创建多个网站
  • 做个公司网站专业做网站app的公司
  • 动漫网站源码下载莱芜金点子最新招工信息
  • 小区住宅可以注册公司吗简述seo的概念